Skip to content

Commit 5af6e59

Browse files
committed
documentation
1 parent 7f276e8 commit 5af6e59

File tree

10 files changed

+286
-21
lines changed

10 files changed

+286
-21
lines changed

CHANGES

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Release 0.5.0
1414
---------------------------------
1515

1616
* python 3.x compatibility
17-
* new :ref:`CONCURRENCY_FIELD_SIGNER`
17+
* new :setting:`CONCURRENCY_FIELD_SIGNER`
1818

1919

2020
Release 0.4.0

concurrency/templatetags/concurrency.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,23 @@
1010

1111
@register.filter
1212
def identity(obj):
13+
"""
14+
returns a string representing "<pk>,<version>" of the passed object
15+
"""
1316
return mark_safe("{0},{1}".format(unlocalize(obj.pk), get_revision_of_object(obj)))
1417

1518

1619
@register.filter
1720
def version(obj):
21+
"""
22+
returns the value of the VersionField of the passed object
23+
"""
1824
return get_revision_of_object(obj)
1925

2026

2127
@register.filter
2228
def is_version(field):
29+
"""
30+
returns True if passed argument is a VersionField instance
31+
"""
2332
return isinstance(field, VersionField)

concurrency/views.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ def conflict(request, target=None, template_name='409.html'):
2121
2222
Templates: `409.html`
2323
Context:
24-
`target` : The model to save
25-
`saved` : The object stored in the db that produce the
26-
conflict or None if not found (ie. deleted)
27-
`request_path` : The path of the requested URL (e.g., '/app/pages/bad_page/')
24+
`target` : The model to save
25+
`saved` : The object stored in the db that produce the
26+
conflict or None if not found (ie. deleted)
27+
`request_path` : The path of the requested URL (e.g., '/app/pages/bad_page/')
2828
2929
"""
3030
try:

docs/_ext/djangodocs.py

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
"""
2+
Sphinx plugins for Django documentation.
3+
"""
4+
import json
5+
import os
6+
import re
7+
8+
from sphinx import addnodes, __version__ as sphinx_ver
9+
from sphinx.builders.html import StandaloneHTMLBuilder
10+
from sphinx.writers.html import SmartyPantsHTMLTranslator
11+
from sphinx.util.console import bold
12+
from sphinx.util.compat import Directive
13+
14+
# RE for option descriptions without a '--' prefix
15+
simple_option_desc_re = re.compile(
16+
r'([-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)')
17+
18+
def setup(app):
19+
app.add_crossref_type(
20+
directivename = "setting",
21+
rolename = "setting",
22+
indextemplate = "pair: %s; setting",
23+
)
24+
app.add_crossref_type(
25+
directivename = "templatetag",
26+
rolename = "ttag",
27+
indextemplate = "pair: %s; template tag"
28+
)
29+
app.add_crossref_type(
30+
directivename = "templatefilter",
31+
rolename = "tfilter",
32+
indextemplate = "pair: %s; template filter"
33+
)
34+
app.add_crossref_type(
35+
directivename = "fieldlookup",
36+
rolename = "lookup",
37+
indextemplate = "pair: %s; field lookup type",
38+
)
39+
app.add_description_unit(
40+
directivename = "django-admin",
41+
rolename = "djadmin",
42+
indextemplate = "pair: %s; django-admin command",
43+
parse_node = parse_django_admin_node,
44+
)
45+
app.add_description_unit(
46+
directivename = "django-admin-option",
47+
rolename = "djadminopt",
48+
indextemplate = "pair: %s; django-admin command-line option",
49+
parse_node = parse_django_adminopt_node,
50+
)
51+
app.add_config_value('django_next_version', '0.0', True)
52+
app.add_directive('versionadded', VersionDirective)
53+
app.add_directive('versionchanged', VersionDirective)
54+
app.add_builder(DjangoStandaloneHTMLBuilder)
55+
56+
57+
class VersionDirective(Directive):
58+
has_content = True
59+
required_arguments = 1
60+
optional_arguments = 1
61+
final_argument_whitespace = True
62+
option_spec = {}
63+
64+
def run(self):
65+
if len(self.arguments) > 1:
66+
msg = """Only one argument accepted for directive '{directive_name}::'.
67+
Comments should be provided as content,
68+
not as an extra argument.""".format(directive_name=self.name)
69+
raise self.error(msg)
70+
71+
env = self.state.document.settings.env
72+
ret = []
73+
node = addnodes.versionmodified()
74+
ret.append(node)
75+
76+
if self.arguments[0] == env.config.django_next_version:
77+
node['version'] = "Development version"
78+
else:
79+
node['version'] = self.arguments[0]
80+
81+
node['type'] = self.name
82+
if self.content:
83+
self.state.nested_parse(self.content, self.content_offset, node)
84+
env.note_versionchange(node['type'], node['version'], node, self.lineno)
85+
return ret
86+
87+
88+
class DjangoHTMLTranslator(SmartyPantsHTMLTranslator):
89+
"""
90+
Django-specific reST to HTML tweaks.
91+
"""
92+
93+
# Don't use border=1, which docutils does by default.
94+
def visit_table(self, node):
95+
self._table_row_index = 0 # Needed by Sphinx
96+
self.body.append(self.starttag(node, 'table', CLASS='docutils'))
97+
98+
# <big>? Really?
99+
def visit_desc_parameterlist(self, node):
100+
self.body.append('(')
101+
self.first_param = 1
102+
self.param_separator = node.child_text_separator
103+
104+
def depart_desc_parameterlist(self, node):
105+
self.body.append(')')
106+
107+
if sphinx_ver < '1.0.8':
108+
#
109+
# Don't apply smartypants to literal blocks
110+
#
111+
def visit_literal_block(self, node):
112+
self.no_smarty += 1
113+
SmartyPantsHTMLTranslator.visit_literal_block(self, node)
114+
115+
def depart_literal_block(self, node):
116+
SmartyPantsHTMLTranslator.depart_literal_block(self, node)
117+
self.no_smarty -= 1
118+
119+
#
120+
# Turn the "new in version" stuff (versionadded/versionchanged) into a
121+
# better callout -- the Sphinx default is just a little span,
122+
# which is a bit less obvious that I'd like.
123+
#
124+
# FIXME: these messages are all hardcoded in English. We need to change
125+
# that to accommodate other language docs, but I can't work out how to make
126+
# that work.
127+
#
128+
version_text = {
129+
'deprecated': 'Deprecated in Django %s',
130+
'versionchanged': 'Changed in Django %s',
131+
'versionadded': 'New in Django %s',
132+
}
133+
134+
def visit_versionmodified(self, node):
135+
self.body.append(
136+
self.starttag(node, 'div', CLASS=node['type'])
137+
)
138+
title = "%s%s" % (
139+
self.version_text[node['type']] % node['version'],
140+
":" if len(node) else "."
141+
)
142+
self.body.append('<span class="title">%s</span> ' % title)
143+
144+
def depart_versionmodified(self, node):
145+
self.body.append("</div>\n")
146+
147+
# Give each section a unique ID -- nice for custom CSS hooks
148+
def visit_section(self, node):
149+
old_ids = node.get('ids', [])
150+
node['ids'] = ['s-' + i for i in old_ids]
151+
node['ids'].extend(old_ids)
152+
SmartyPantsHTMLTranslator.visit_section(self, node)
153+
node['ids'] = old_ids
154+
155+
def parse_django_admin_node(env, sig, signode):
156+
command = sig.split(' ')[0]
157+
env._django_curr_admin_command = command
158+
title = "django-admin.py %s" % sig
159+
signode += addnodes.desc_name(title, title)
160+
return sig
161+
162+
def parse_django_adminopt_node(env, sig, signode):
163+
"""A copy of sphinx.directives.CmdoptionDesc.parse_signature()"""
164+
from sphinx.domains.std import option_desc_re
165+
count = 0
166+
firstname = ''
167+
for m in option_desc_re.finditer(sig):
168+
optname, args = m.groups()
169+
if count:
170+
signode += addnodes.desc_addname(', ', ', ')
171+
signode += addnodes.desc_name(optname, optname)
172+
signode += addnodes.desc_addname(args, args)
173+
if not count:
174+
firstname = optname
175+
count += 1
176+
if not count:
177+
for m in simple_option_desc_re.finditer(sig):
178+
optname, args = m.groups()
179+
if count:
180+
signode += addnodes.desc_addname(', ', ', ')
181+
signode += addnodes.desc_name(optname, optname)
182+
signode += addnodes.desc_addname(args, args)
183+
if not count:
184+
firstname = optname
185+
count += 1
186+
if not firstname:
187+
raise ValueError
188+
return firstname
189+
190+
191+
class DjangoStandaloneHTMLBuilder(StandaloneHTMLBuilder):
192+
"""
193+
Subclass to add some extra things we need.
194+
"""
195+
196+
name = 'djangohtml'
197+
198+
def finish(self):
199+
super(DjangoStandaloneHTMLBuilder, self).finish()
200+
self.info(bold("writing templatebuiltins.js..."))
201+
xrefs = self.env.domaindata["std"]["objects"]
202+
templatebuiltins = {
203+
"ttags": [n for ((t, n), (l, a)) in xrefs.items()
204+
if t == "templatetag" and l == "ref/templates/builtins"],
205+
"tfilters": [n for ((t, n), (l, a)) in xrefs.items()
206+
if t == "templatefilter" and l == "ref/templates/builtins"],
207+
}
208+
outfilename = os.path.join(self.outdir, "templatebuiltins.js")
209+
with open(outfilename, 'w') as fp:
210+
fp.write('var django_template_builtins = ')
211+
json.dump(templatebuiltins, fp)
212+
fp.write(';\n')

docs/admin.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ Handle ``list_editable``
1515
------------------------
1616
.. versionadded:: 0.6
1717

18-
Extend your ModelAdmin with :ref:`ConcurrencyListEditableMixin` or use :ref:`ConcurrentModelAdmin`
18+
|concurrency| is able to handle conflicts in the admin's changelist view when
19+
:attr:`ModelAdmin.list_editable` is enabled. To enable this feature simply extends your ModelAdmin from
20+
:ref:`ConcurrentModelAdmin` or use :ref:`ConcurrencyListEditableMixin`
1921

2022
.. seealso:: :ref:`list_editable_policies`
2123

@@ -36,10 +38,12 @@ Update existing actions templates to be managed by concurrency
3638

3739
.. versionadded:: 0.6
3840

39-
You ca use the ``identity`` filter to pass both ``pk`` and ``version`` to your ModelAdmin.
41+
You ca use the :tfilter:`identity`filter to pass both ``pk`` and ``version`` to your ModelAdmin.
4042
Each time you use ``{{obj.pk}}`` simply change to ``{{ obj|identity }}``.
4143
So in the ``admin/delete_selected_confirmation.html`` will have::
4244

45+
.. code-block:: html
46+
4347
{% for obj in queryset %}
4448
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj|identity }}" />
4549
{% endfor %}

docs/api.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,28 @@ Context manager to temporary disable concurrency checking
162162
Context manager to disable sanity check checking for one model. see :ref:`import_data`
163163

164164

165+
.. templatefilter:: identity
166+
167+
``identity``
168+
------------
169+
.. autofunction:: concurrency.templatetags.concurrency.identity
170+
171+
172+
.. templatefilter:: version
173+
174+
``version``
175+
------------
176+
.. autofunction:: concurrency.templatetags.concurrency.version
177+
178+
179+
180+
.. templatefilter:: is_version
181+
182+
``is_version``
183+
---------------
184+
.. autofunction:: concurrency.templatetags.concurrency.is_version
185+
186+
165187

166188
---------------------
167189
Test Utilties

docs/conf.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
# serve to show the default.
1313

1414
import sys, os
15+
1516
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)))
1617

1718
from django.conf import settings
19+
1820
settings.configure()
1921

2022
import concurrency
@@ -43,7 +45,13 @@
4345
'sphinx.ext.coverage',
4446
'sphinx.ext.viewcode',
4547
'version',
46-
'github']
48+
'github',
49+
'djangodocs']
50+
intersphinx_mapping = {
51+
'python': ('http://python.readthedocs.org/en/v2.7.2/', None),
52+
'django': ('http://django.readthedocs.org/en/latest/', None),
53+
'sphinx': ('http://sphinx.readthedocs.org/en/latest/', None),
54+
}
4755

4856
next_version = '0.6'
4957
todo_include_todos = True

0 commit comments

Comments
 (0)