Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Part 3 of pedant day: replaced all tabs in Django with spaces. Python…

… the way Guido intended it, baby!

git-svn-id: http://code.djangoproject.com/svn/django/trunk@3415 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 1687b025dc2a03e9ef111b8fd3db63fce48b77b7 1 parent a926046
@jacobian jacobian authored
View
4 django/contrib/admin/media/css/changelists.css
@@ -42,9 +42,9 @@
/* PAGINATOR */
.paginator { font-size:11px; padding-top:10px; padding-bottom:10px; line-height:22px; margin:0; border-top:1px solid #ddd; }
-.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
+.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
.paginator a.showall { padding:0 !important; border:none !important; }
.paginator a.showall:hover { color:#036 !important; background:transparent !important; }
-.paginator .end { border-width:2px !important; margin-right:6px; }
+.paginator .end { border-width:2px !important; margin-right:6px; }
.paginator .this-page { padding:2px 6px; font-weight:bold; font-size:13px; vertical-align:top; }
.paginator a:hover { color:white; background:#5b80b2; border-color:#036; }
View
4 django/contrib/admin/media/css/forms.css
@@ -7,10 +7,10 @@
form .form-row p { padding-left:0; font-size:11px; }
/* FORM LABELS */
-form h4 { margin:0 !important; padding:0 !important; border:none !important; }
+form h4 { margin:0 !important; padding:0 !important; border:none !important; }
label { font-weight:normal !important; color:#666; font-size:12px; }
label.inline { margin-left:20px; }
-.required label, label.required { font-weight:bold !important; color:#333 !important; }
+.required label, label.required { font-weight:bold !important; color:#333 !important; }
/* RADIO BUTTONS */
form ul.radiolist li { list-style-type:none; }
View
6 django/contrib/admin/media/css/global.css
@@ -31,7 +31,7 @@ fieldset { margin:0; padding:0; }
blockquote { font-size:11px; color:#777; margin-left:2px; padding-left:10px; border-left:5px solid #ddd; }
code, pre { font-family:"Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; background:inherit; color:#666; font-size:11px; }
pre.literal-block { margin:10px; background:#eee; padding:6px 8px; }
-code strong { color:#930; }
+code strong { color:#930; }
hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; }
/* TEXT STYLES & MODIFIERS */
@@ -81,7 +81,7 @@ table.orderable tbody tr td:first-child { padding-left:14px; background-image:ur
table.orderable-initalized .order-cell, body>tr>td.order-cell { display:none; }
/* FORM DEFAULTS */
-input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
+input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
textarea { vertical-align:top !important; }
input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
@@ -92,7 +92,7 @@ input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2
input[type=submit].default:active { background-image:url(../img/admin/default-bg-reverse.gif); background-position:top; }
/* MODULES */
-.module { border:1px solid #ccc; margin-bottom:5px; background:white; }
+.module { border:1px solid #ccc; margin-bottom:5px; background:white; }
.module p, .module ul, .module h3, .module h4, .module dl, .module pre { padding-left:10px; padding-right:10px; }
.module blockquote { margin-left:12px; }
.module ul, .module ol { margin-left:1.5em; }
View
8 django/contrib/admin/media/css/layout.css
@@ -4,7 +4,7 @@
#header { width:100%; }
#content-main { float:left; width:100%; }
#content-related { float:right; width:18em; position:relative; margin-right:-19em; }
-#footer { clear:both; padding:10px; }
+#footer { clear:both; padding:10px; }
/* COLUMN TYPES */
.colMS { margin-right:20em !important; }
@@ -16,14 +16,14 @@
.dashboard #content { width:500px; }
/* HEADER */
-#header { background:#417690; color:#ffc; overflow:hidden; }
+#header { background:#417690; color:#ffc; overflow:hidden; }
#header a:link, #header a:visited { color:white; }
#header a:hover { text-decoration:underline; }
#branding h1 { padding:0 10px; font-size:18px; margin:8px 0; font-weight:normal; color:#f4f379; }
#branding h2 { padding:0 10px; font-size:14px; margin:-8px 0 8px 0; font-weight:normal; color:#ffc; }
-#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
+#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
/* SIDEBAR */
#content-related h3 { font-size:12px; color:#666; margin-bottom:3px; }
#content-related h4 { font-size:11px; }
-#content-related .module h2 { background:#eee url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; }
+#content-related .module h2 { background:#eee url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; }
View
2  django/contrib/admin/media/css/rtl.css
@@ -16,7 +16,7 @@ th { text-align: right; }
/* layout styles */
-#user-tools { right:auto; left:0; text-align:left; }
+#user-tools { right:auto; left:0; text-align:left; }
div.breadcrumbs { text-align:right; }
#content-main { float:right;}
#content-related { float:left; margin-left:-19em; margin-right:auto;}
View
144 django/contrib/admin/media/js/admin/CollapsedFieldsets.js
@@ -3,83 +3,83 @@
// link when the fieldset is visible.
function findForm(node) {
- // returns the node of the form containing the given node
- if (node.tagName.toLowerCase() != 'form') {
- return findForm(node.parentNode);
- }
- return node;
+ // returns the node of the form containing the given node
+ if (node.tagName.toLowerCase() != 'form') {
+ return findForm(node.parentNode);
+ }
+ return node;
}
var CollapsedFieldsets = {
- collapse_re: /\bcollapse\b/, // Class of fieldsets that should be dealt with.
- collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden.
- collapsed_class: 'collapsed',
- init: function() {
- var fieldsets = document.getElementsByTagName('fieldset');
- var collapsed_seen = false;
- for (var i = 0, fs; fs = fieldsets[i]; i++) {
- // Collapse this fieldset if it has the correct class, and if it
- // doesn't have any errors. (Collapsing shouldn't apply in the case
- // of error messages.)
- if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) {
- collapsed_seen = true;
- // Give it an additional class, used by CSS to hide it.
- fs.className += ' ' + CollapsedFieldsets.collapsed_class;
- // (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>)
- var collapse_link = document.createElement('a');
- collapse_link.className = 'collapse-toggle';
- collapse_link.id = 'fieldsetcollapser' + i;
- collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
- collapse_link.href = '#';
- collapse_link.innerHTML = gettext('Show');
- var h2 = fs.getElementsByTagName('h2')[0];
- h2.appendChild(document.createTextNode(' ('));
- h2.appendChild(collapse_link);
- h2.appendChild(document.createTextNode(')'));
- }
- }
- if (collapsed_seen) {
- // Expand all collapsed fieldsets when form is submitted.
- addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); });
- }
- },
- fieldset_has_errors: function(fs) {
- // Returns true if any fields in the fieldset have validation errors.
- var divs = fs.getElementsByTagName('div');
- for (var i=0; i<divs.length; i++) {
- if (divs[i].className.match(/\berror\b/)) {
- return true;
- }
- }
- return false;
- },
- show: function(fieldset_index) {
- var fs = document.getElementsByTagName('fieldset')[fieldset_index];
- // Remove the class name that causes the "display: none".
- fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, '');
- // Toggle the "Show" link to a "Hide" link
- var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
- collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
- collapse_link.innerHTML = gettext('Hide');
- },
- hide: function(fieldset_index) {
- var fs = document.getElementsByTagName('fieldset')[fieldset_index];
- // Add the class name that causes the "display: none".
- fs.className += ' ' + CollapsedFieldsets.collapsed_class;
- // Toggle the "Hide" link to a "Show" link
- var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
+ collapse_re: /\bcollapse\b/, // Class of fieldsets that should be dealt with.
+ collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden.
+ collapsed_class: 'collapsed',
+ init: function() {
+ var fieldsets = document.getElementsByTagName('fieldset');
+ var collapsed_seen = false;
+ for (var i = 0, fs; fs = fieldsets[i]; i++) {
+ // Collapse this fieldset if it has the correct class, and if it
+ // doesn't have any errors. (Collapsing shouldn't apply in the case
+ // of error messages.)
+ if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) {
+ collapsed_seen = true;
+ // Give it an additional class, used by CSS to hide it.
+ fs.className += ' ' + CollapsedFieldsets.collapsed_class;
+ // (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>)
+ var collapse_link = document.createElement('a');
+ collapse_link.className = 'collapse-toggle';
+ collapse_link.id = 'fieldsetcollapser' + i;
+ collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
+ collapse_link.href = '#';
+ collapse_link.innerHTML = gettext('Show');
+ var h2 = fs.getElementsByTagName('h2')[0];
+ h2.appendChild(document.createTextNode(' ('));
+ h2.appendChild(collapse_link);
+ h2.appendChild(document.createTextNode(')'));
+ }
+ }
+ if (collapsed_seen) {
+ // Expand all collapsed fieldsets when form is submitted.
+ addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); });
+ }
+ },
+ fieldset_has_errors: function(fs) {
+ // Returns true if any fields in the fieldset have validation errors.
+ var divs = fs.getElementsByTagName('div');
+ for (var i=0; i<divs.length; i++) {
+ if (divs[i].className.match(/\berror\b/)) {
+ return true;
+ }
+ }
+ return false;
+ },
+ show: function(fieldset_index) {
+ var fs = document.getElementsByTagName('fieldset')[fieldset_index];
+ // Remove the class name that causes the "display: none".
+ fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, '');
+ // Toggle the "Show" link to a "Hide" link
+ var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
+ collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
+ collapse_link.innerHTML = gettext('Hide');
+ },
+ hide: function(fieldset_index) {
+ var fs = document.getElementsByTagName('fieldset')[fieldset_index];
+ // Add the class name that causes the "display: none".
+ fs.className += ' ' + CollapsedFieldsets.collapsed_class;
+ // Toggle the "Hide" link to a "Show" link
+ var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
collapse_link.onclick = new Function('CollapsedFieldsets.show('+fieldset_index+'); return false;');
- collapse_link.innerHTML = gettext('Show');
- },
+ collapse_link.innerHTML = gettext('Show');
+ },
- uncollapse_all: function() {
- var fieldsets = document.getElementsByTagName('fieldset');
- for (var i=0; i<fieldsets.length; i++) {
- if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) {
- CollapsedFieldsets.show(i);
- }
- }
- }
+ uncollapse_all: function() {
+ var fieldsets = document.getElementsByTagName('fieldset');
+ for (var i=0; i<fieldsets.length; i++) {
+ if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) {
+ CollapsedFieldsets.show(i);
+ }
+ }
+ }
}
addEvent(window, 'load', CollapsedFieldsets.init);
View
22 django/contrib/admin/templates/admin/login.html
@@ -13,17 +13,17 @@
{% endif %}
<div id="content-main">
<form action="{{ app_path }}" method="post" id="login-form">
- <div class="form-row">
- <label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" />
- </div>
- <div class="form-row">
- <label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
- <input type="hidden" name="this_is_the_login_form" value="1" />
- <input type="hidden" name="post_data" value="{{ post_data }}" /> {% comment %}<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>{% endcomment %}
- </div>
- <div class="submit-row">
- <label>&nbsp;</label><input type="submit" value="{% trans 'Log in' %}" />
- </div>
+ <div class="form-row">
+ <label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" />
+ </div>
+ <div class="form-row">
+ <label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
+ <input type="hidden" name="this_is_the_login_form" value="1" />
+ <input type="hidden" name="post_data" value="{{ post_data }}" /> {% comment %}<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>{% endcomment %}
+ </div>
+ <div class="submit-row">
+ <label>&nbsp;</label><input type="submit" value="{% trans 'Log in' %}" />
+ </div>
</form>
<script type="text/javascript">
View
16 django/contrib/admin/templates/admin_doc/index.html
@@ -9,17 +9,17 @@
<h1>Documentation</h1>
<div id="content-main">
- <h3><a href="tags/">Tags</a></h3>
- <p>List of all the template tags and their functions.</p>
+ <h3><a href="tags/">Tags</a></h3>
+ <p>List of all the template tags and their functions.</p>
- <h3><a href="filters/">Filters</a></h3>
- <p>Filters are actions which can be applied to variables in a template to alter the output.</p>
+ <h3><a href="filters/">Filters</a></h3>
+ <p>Filters are actions which can be applied to variables in a template to alter the output.</p>
- <h3><a href="models/">Models</a></h3>
- <p>Models are descriptions of all the objects in the system and their associated fields. Each model has a list of fields which can be accessed as template variables.</p>
+ <h3><a href="models/">Models</a></h3>
+ <p>Models are descriptions of all the objects in the system and their associated fields. Each model has a list of fields which can be accessed as template variables.</p>
- <h3><a href="views/">Views</a></h3>
- <p>Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.</p>
+ <h3><a href="views/">Views</a></h3>
+ <p>Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.</p>
<h3><a href="bookmarklets/">Bookmarklets</a></h3>
<p>Tools for your browser to quickly access admin functionality.</p>
View
4 django/contrib/admin/templates/admin_doc/missing_docutils.html
@@ -9,9 +9,9 @@
<h1>Documentation</h1>
<div id="content-main">
- <h3>The admin documentation system requires Python's <a href="http://docutils.sf.net/">docutils</a> library.</h3>
+ <h3>The admin documentation system requires Python's <a href="http://docutils.sf.net/">docutils</a> library.</h3>
- <p>Please ask your administrators to install <a href="http://docutils.sf.net/">docutils</a>.</p>
+ <p>Please ask your administrators to install <a href="http://docutils.sf.net/">docutils</a>.</p>
</div>
{% endblock %}
View
2  django/contrib/comments/models.py
@@ -51,7 +51,7 @@ def get_list_with_karma(self, **kwargs):
extra_kwargs.setdefault('select', {})
extra_kwargs['select']['_karma_total_good'] = 'SELECT COUNT(*) FROM comments_karmascore, comments_comment WHERE comments_karmascore.comment_id=comments_comment.id AND score=1'
extra_kwargs['select']['_karma_total_bad'] = 'SELECT COUNT(*) FROM comments_karmascore, comments_comment WHERE comments_karmascore.comment_id=comments_comment.id AND score=-1'
- return self.filter(**kwargs).extra(**extra_kwargs)
+ return self.filter(**kwargs).extra(**extra_kwargs)
def user_is_moderator(self, user):
if user.is_superuser:
View
862 django/dispatch/dispatcher.py
@@ -6,24 +6,24 @@
Module attributes of note:
- Any -- Singleton used to signal either "Any Sender" or
- "Any Signal". See documentation of the _Any class.
- Anonymous -- Singleton used to signal "Anonymous Sender"
- See documentation of the _Anonymous class.
+ Any -- Singleton used to signal either "Any Sender" or
+ "Any Signal". See documentation of the _Any class.
+ Anonymous -- Singleton used to signal "Anonymous Sender"
+ See documentation of the _Anonymous class.
Internal attributes:
- WEAKREF_TYPES -- tuple of types/classes which represent
- weak references to receivers, and thus must be de-
- referenced on retrieval to retrieve the callable
- object
- connections -- { senderkey (id) : { signal : [receivers...]}}
- senders -- { senderkey (id) : weakref(sender) }
- used for cleaning up sender references on sender
- deletion
- sendersBack -- { receiverkey (id) : [senderkey (id)...] }
- used for cleaning up receiver references on receiver
- deletion, (considerably speeds up the cleanup process
- vs. the original code.)
+ WEAKREF_TYPES -- tuple of types/classes which represent
+ weak references to receivers, and thus must be de-
+ referenced on retrieval to retrieve the callable
+ object
+ connections -- { senderkey (id) : { signal : [receivers...]}}
+ senders -- { senderkey (id) : weakref(sender) }
+ used for cleaning up sender references on sender
+ deletion
+ sendersBack -- { receiverkey (id) : [senderkey (id)...] }
+ used for cleaning up receiver references on receiver
+ deletion, (considerably speeds up the cleanup process
+ vs. the original code.)
"""
from __future__ import generators
import types, weakref
@@ -34,44 +34,44 @@
__version__ = "$Revision: 1.9 $"[11:-2]
try:
- True
+ True
except NameError:
- True = 1==1
- False = 1==0
+ True = 1==1
+ False = 1==0
class _Parameter:
- """Used to represent default parameter values."""
- def __repr__(self):
- return self.__class__.__name__
+ """Used to represent default parameter values."""
+ def __repr__(self):
+ return self.__class__.__name__
class _Any(_Parameter):
- """Singleton used to signal either "Any Sender" or "Any Signal"
+ """Singleton used to signal either "Any Sender" or "Any Signal"
- The Any object can be used with connect, disconnect,
- send, or sendExact to signal that the parameter given
- Any should react to all senders/signals, not just
- a particular sender/signal.
- """
+ The Any object can be used with connect, disconnect,
+ send, or sendExact to signal that the parameter given
+ Any should react to all senders/signals, not just
+ a particular sender/signal.
+ """
Any = _Any()
class _Anonymous(_Parameter):
- """Singleton used to signal "Anonymous Sender"
-
- The Anonymous object is used to signal that the sender
- of a message is not specified (as distinct from being
- "any sender"). Registering callbacks for Anonymous
- will only receive messages sent without senders. Sending
- with anonymous will only send messages to those receivers
- registered for Any or Anonymous.
-
- Note:
- The default sender for connect is Any, while the
- default sender for send is Anonymous. This has
- the effect that if you do not specify any senders
- in either function then all messages are routed
- as though there was a single sender (Anonymous)
- being used everywhere.
- """
+ """Singleton used to signal "Anonymous Sender"
+
+ The Anonymous object is used to signal that the sender
+ of a message is not specified (as distinct from being
+ "any sender"). Registering callbacks for Anonymous
+ will only receive messages sent without senders. Sending
+ with anonymous will only send messages to those receivers
+ registered for Any or Anonymous.
+
+ Note:
+ The default sender for connect is Any, while the
+ default sender for send is Anonymous. This has
+ the effect that if you do not specify any senders
+ in either function then all messages are routed
+ as though there was a single sender (Anonymous)
+ being used everywhere.
+ """
Anonymous = _Anonymous()
WEAKREF_TYPES = (weakref.ReferenceType, saferef.BoundMethodWeakref)
@@ -82,416 +82,416 @@ class _Anonymous(_Parameter):
def connect(receiver, signal=Any, sender=Any, weak=True):
- """Connect receiver to sender for signal
-
- receiver -- a callable Python object which is to receive
- messages/signals/events. Receivers must be hashable
- objects.
-
- if weak is True, then receiver must be weak-referencable
- (more precisely saferef.safeRef() must be able to create
- a reference to the receiver).
-
- Receivers are fairly flexible in their specification,
- as the machinery in the robustApply module takes care
- of most of the details regarding figuring out appropriate
- subsets of the sent arguments to apply to a given
- receiver.
-
- Note:
- if receiver is itself a weak reference (a callable),
- it will be de-referenced by the system's machinery,
- so *generally* weak references are not suitable as
- receivers, though some use might be found for the
- facility whereby a higher-level library passes in
- pre-weakrefed receiver references.
-
- signal -- the signal to which the receiver should respond
-
- if Any, receiver will receive any signal from the
- indicated sender (which might also be Any, but is not
- necessarily Any).
-
- Otherwise must be a hashable Python object other than
- None (DispatcherError raised on None).
-
- sender -- the sender to which the receiver should respond
-
- if Any, receiver will receive the indicated signals
- from any sender.
-
- if Anonymous, receiver will only receive indicated
- signals from send/sendExact which do not specify a
- sender, or specify Anonymous explicitly as the sender.
-
- Otherwise can be any python object.
-
- weak -- whether to use weak references to the receiver
- By default, the module will attempt to use weak
- references to the receiver objects. If this parameter
- is false, then strong references will be used.
-
- returns None, may raise DispatcherTypeError
- """
- if signal is None:
- raise errors.DispatcherTypeError(
- 'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
- )
- if weak:
- receiver = saferef.safeRef(receiver, onDelete=_removeReceiver)
- senderkey = id(sender)
- if connections.has_key(senderkey):
- signals = connections[senderkey]
- else:
- connections[senderkey] = signals = {}
- # Keep track of senders for cleanup.
- # Is Anonymous something we want to clean up?
- if sender not in (None, Anonymous, Any):
- def remove(object, senderkey=senderkey):
- _removeSender(senderkey=senderkey)
- # Skip objects that can not be weakly referenced, which means
- # they won't be automatically cleaned up, but that's too bad.
- try:
- weakSender = weakref.ref(sender, remove)
- senders[senderkey] = weakSender
- except:
- pass
-
- receiverID = id(receiver)
- # get current set, remove any current references to
- # this receiver in the set, including back-references
- if signals.has_key(signal):
- receivers = signals[signal]
- _removeOldBackRefs(senderkey, signal, receiver, receivers)
- else:
- receivers = signals[signal] = []
- try:
- current = sendersBack.get( receiverID )
- if current is None:
- sendersBack[ receiverID ] = current = []
- if senderkey not in current:
- current.append(senderkey)
- except:
- pass
-
- receivers.append(receiver)
+ """Connect receiver to sender for signal
+
+ receiver -- a callable Python object which is to receive
+ messages/signals/events. Receivers must be hashable
+ objects.
+
+ if weak is True, then receiver must be weak-referencable
+ (more precisely saferef.safeRef() must be able to create
+ a reference to the receiver).
+
+ Receivers are fairly flexible in their specification,
+ as the machinery in the robustApply module takes care
+ of most of the details regarding figuring out appropriate
+ subsets of the sent arguments to apply to a given
+ receiver.
+
+ Note:
+ if receiver is itself a weak reference (a callable),
+ it will be de-referenced by the system's machinery,
+ so *generally* weak references are not suitable as
+ receivers, though some use might be found for the
+ facility whereby a higher-level library passes in
+ pre-weakrefed receiver references.
+
+ signal -- the signal to which the receiver should respond
+
+ if Any, receiver will receive any signal from the
+ indicated sender (which might also be Any, but is not
+ necessarily Any).
+
+ Otherwise must be a hashable Python object other than
+ None (DispatcherError raised on None).
+
+ sender -- the sender to which the receiver should respond
+
+ if Any, receiver will receive the indicated signals
+ from any sender.
+
+ if Anonymous, receiver will only receive indicated
+ signals from send/sendExact which do not specify a
+ sender, or specify Anonymous explicitly as the sender.
+
+ Otherwise can be any python object.
+
+ weak -- whether to use weak references to the receiver
+ By default, the module will attempt to use weak
+ references to the receiver objects. If this parameter
+ is false, then strong references will be used.
+
+ returns None, may raise DispatcherTypeError
+ """
+ if signal is None:
+ raise errors.DispatcherTypeError(
+ 'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
+ )
+ if weak:
+ receiver = saferef.safeRef(receiver, onDelete=_removeReceiver)
+ senderkey = id(sender)
+ if connections.has_key(senderkey):
+ signals = connections[senderkey]
+ else:
+ connections[senderkey] = signals = {}
+ # Keep track of senders for cleanup.
+ # Is Anonymous something we want to clean up?
+ if sender not in (None, Anonymous, Any):
+ def remove(object, senderkey=senderkey):
+ _removeSender(senderkey=senderkey)
+ # Skip objects that can not be weakly referenced, which means
+ # they won't be automatically cleaned up, but that's too bad.
+ try:
+ weakSender = weakref.ref(sender, remove)
+ senders[senderkey] = weakSender
+ except:
+ pass
+
+ receiverID = id(receiver)
+ # get current set, remove any current references to
+ # this receiver in the set, including back-references
+ if signals.has_key(signal):
+ receivers = signals[signal]
+ _removeOldBackRefs(senderkey, signal, receiver, receivers)
+ else:
+ receivers = signals[signal] = []
+ try:
+ current = sendersBack.get( receiverID )
+ if current is None:
+ sendersBack[ receiverID ] = current = []
+ if senderkey not in current:
+ current.append(senderkey)
+ except:
+ pass
+
+ receivers.append(receiver)
def disconnect(receiver, signal=Any, sender=Any, weak=True):
- """Disconnect receiver from sender for signal
-
- receiver -- the registered receiver to disconnect
- signal -- the registered signal to disconnect
- sender -- the registered sender to disconnect
- weak -- the weakref state to disconnect
-
- disconnect reverses the process of connect,
- the semantics for the individual elements are
- logically equivalent to a tuple of
- (receiver, signal, sender, weak) used as a key
- to be deleted from the internal routing tables.
- (The actual process is slightly more complex
- but the semantics are basically the same).
-
- Note:
- Using disconnect is not required to cleanup
- routing when an object is deleted, the framework
- will remove routes for deleted objects
- automatically. It's only necessary to disconnect
- if you want to stop routing to a live object.
-
- returns None, may raise DispatcherTypeError or
- DispatcherKeyError
- """
- if signal is None:
- raise errors.DispatcherTypeError(
- 'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
- )
- if weak: receiver = saferef.safeRef(receiver)
- senderkey = id(sender)
- try:
- signals = connections[senderkey]
- receivers = signals[signal]
- except KeyError:
- raise errors.DispatcherKeyError(
- """No receivers found for signal %r from sender %r""" %(
- signal,
- sender
- )
- )
- try:
- # also removes from receivers
- _removeOldBackRefs(senderkey, signal, receiver, receivers)
- except ValueError:
- raise errors.DispatcherKeyError(
- """No connection to receiver %s for signal %s from sender %s""" %(
- receiver,
- signal,
- sender
- )
- )
- _cleanupConnections(senderkey, signal)
+ """Disconnect receiver from sender for signal
+
+ receiver -- the registered receiver to disconnect
+ signal -- the registered signal to disconnect
+ sender -- the registered sender to disconnect
+ weak -- the weakref state to disconnect
+
+ disconnect reverses the process of connect,
+ the semantics for the individual elements are
+ logically equivalent to a tuple of
+ (receiver, signal, sender, weak) used as a key
+ to be deleted from the internal routing tables.
+ (The actual process is slightly more complex
+ but the semantics are basically the same).
+
+ Note:
+ Using disconnect is not required to cleanup
+ routing when an object is deleted, the framework
+ will remove routes for deleted objects
+ automatically. It's only necessary to disconnect
+ if you want to stop routing to a live object.
+
+ returns None, may raise DispatcherTypeError or
+ DispatcherKeyError
+ """
+ if signal is None:
+ raise errors.DispatcherTypeError(
+ 'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
+ )
+ if weak: receiver = saferef.safeRef(receiver)
+ senderkey = id(sender)
+ try:
+ signals = connections[senderkey]
+ receivers = signals[signal]
+ except KeyError:
+ raise errors.DispatcherKeyError(
+ """No receivers found for signal %r from sender %r""" %(
+ signal,
+ sender
+ )
+ )
+ try:
+ # also removes from receivers
+ _removeOldBackRefs(senderkey, signal, receiver, receivers)
+ except ValueError:
+ raise errors.DispatcherKeyError(
+ """No connection to receiver %s for signal %s from sender %s""" %(
+ receiver,
+ signal,
+ sender
+ )
+ )
+ _cleanupConnections(senderkey, signal)
def getReceivers( sender = Any, signal = Any ):
- """Get list of receivers from global tables
-
- This utility function allows you to retrieve the
- raw list of receivers from the connections table
- for the given sender and signal pair.
-
- Note:
- there is no guarantee that this is the actual list
- stored in the connections table, so the value
- should be treated as a simple iterable/truth value
- rather than, for instance a list to which you
- might append new records.
-
- Normally you would use liveReceivers( getReceivers( ...))
- to retrieve the actual receiver objects as an iterable
- object.
- """
- try:
- return connections[id(sender)][signal]
- except KeyError:
- return []
+ """Get list of receivers from global tables
+
+ This utility function allows you to retrieve the
+ raw list of receivers from the connections table
+ for the given sender and signal pair.
+
+ Note:
+ there is no guarantee that this is the actual list
+ stored in the connections table, so the value
+ should be treated as a simple iterable/truth value
+ rather than, for instance a list to which you
+ might append new records.
+
+ Normally you would use liveReceivers( getReceivers( ...))
+ to retrieve the actual receiver objects as an iterable
+ object.
+ """
+ try:
+ return connections[id(sender)][signal]
+ except KeyError:
+ return []
def liveReceivers(receivers):
- """Filter sequence of receivers to get resolved, live receivers
+ """Filter sequence of receivers to get resolved, live receivers
- This is a generator which will iterate over
- the passed sequence, checking for weak references
- and resolving them, then returning all live
- receivers.
- """
- for receiver in receivers:
- if isinstance( receiver, WEAKREF_TYPES):
- # Dereference the weak reference.
- receiver = receiver()
- if receiver is not None:
- yield receiver
- else:
- yield receiver
+ This is a generator which will iterate over
+ the passed sequence, checking for weak references
+ and resolving them, then returning all live
+ receivers.
+ """
+ for receiver in receivers:
+ if isinstance( receiver, WEAKREF_TYPES):
+ # Dereference the weak reference.
+ receiver = receiver()
+ if receiver is not None:
+ yield receiver
+ else:
+ yield receiver
def getAllReceivers( sender = Any, signal = Any ):
- """Get list of all receivers from global tables
-
- This gets all receivers which should receive
- the given signal from sender, each receiver should
- be produced only once by the resulting generator
- """
- receivers = {}
- for set in (
- # Get receivers that receive *this* signal from *this* sender.
- getReceivers( sender, signal ),
- # Add receivers that receive *any* signal from *this* sender.
- getReceivers( sender, Any ),
- # Add receivers that receive *this* signal from *any* sender.
- getReceivers( Any, signal ),
- # Add receivers that receive *any* signal from *any* sender.
- getReceivers( Any, Any ),
- ):
- for receiver in set:
- if receiver: # filter out dead instance-method weakrefs
- try:
- if not receivers.has_key( receiver ):
- receivers[receiver] = 1
- yield receiver
- except TypeError:
- # dead weakrefs raise TypeError on hash...
- pass
+ """Get list of all receivers from global tables
+
+ This gets all receivers which should receive
+ the given signal from sender, each receiver should
+ be produced only once by the resulting generator
+ """
+ receivers = {}
+ for set in (
+ # Get receivers that receive *this* signal from *this* sender.
+ getReceivers( sender, signal ),
+ # Add receivers that receive *any* signal from *this* sender.
+ getReceivers( sender, Any ),
+ # Add receivers that receive *this* signal from *any* sender.
+ getReceivers( Any, signal ),
+ # Add receivers that receive *any* signal from *any* sender.
+ getReceivers( Any, Any ),
+ ):
+ for receiver in set:
+ if receiver: # filter out dead instance-method weakrefs
+ try:
+ if not receivers.has_key( receiver ):
+ receivers[receiver] = 1
+ yield receiver
+ except TypeError:
+ # dead weakrefs raise TypeError on hash...
+ pass
def send(signal=Any, sender=Anonymous, *arguments, **named):
- """Send signal from sender to all connected receivers.
-
- signal -- (hashable) signal value, see connect for details
-
- sender -- the sender of the signal
-
- if Any, only receivers registered for Any will receive
- the message.
-
- if Anonymous, only receivers registered to receive
- messages from Anonymous or Any will receive the message
-
- Otherwise can be any python object (normally one
- registered with a connect if you actually want
- something to occur).
-
- arguments -- positional arguments which will be passed to
- *all* receivers. Note that this may raise TypeErrors
- if the receivers do not allow the particular arguments.
- Note also that arguments are applied before named
- arguments, so they should be used with care.
-
- named -- named arguments which will be filtered according
- to the parameters of the receivers to only provide those
- acceptable to the receiver.
-
- Return a list of tuple pairs [(receiver, response), ... ]
-
- if any receiver raises an error, the error propagates back
- through send, terminating the dispatch loop, so it is quite
- possible to not have all receivers called if a raises an
- error.
- """
- # Call each receiver with whatever arguments it can accept.
- # Return a list of tuple pairs [(receiver, response), ... ].
- responses = []
- for receiver in liveReceivers(getAllReceivers(sender, signal)):
- response = robustapply.robustApply(
- receiver,
- signal=signal,
- sender=sender,
- *arguments,
- **named
- )
- responses.append((receiver, response))
- return responses
+ """Send signal from sender to all connected receivers.
+
+ signal -- (hashable) signal value, see connect for details
+
+ sender -- the sender of the signal
+
+ if Any, only receivers registered for Any will receive
+ the message.
+
+ if Anonymous, only receivers registered to receive
+ messages from Anonymous or Any will receive the message
+
+ Otherwise can be any python object (normally one
+ registered with a connect if you actually want
+ something to occur).
+
+ arguments -- positional arguments which will be passed to
+ *all* receivers. Note that this may raise TypeErrors
+ if the receivers do not allow the particular arguments.
+ Note also that arguments are applied before named
+ arguments, so they should be used with care.
+
+ named -- named arguments which will be filtered according
+ to the parameters of the receivers to only provide those
+ acceptable to the receiver.
+
+ Return a list of tuple pairs [(receiver, response), ... ]
+
+ if any receiver raises an error, the error propagates back
+ through send, terminating the dispatch loop, so it is quite
+ possible to not have all receivers called if a raises an
+ error.
+ """
+ # Call each receiver with whatever arguments it can accept.
+ # Return a list of tuple pairs [(receiver, response), ... ].
+ responses = []
+ for receiver in liveReceivers(getAllReceivers(sender, signal)):
+ response = robustapply.robustApply(
+ receiver,
+ signal=signal,
+ sender=sender,
+ *arguments,
+ **named
+ )
+ responses.append((receiver, response))
+ return responses
def sendExact( signal=Any, sender=Anonymous, *arguments, **named ):
- """Send signal only to those receivers registered for exact message
-
- sendExact allows for avoiding Any/Anonymous registered
- handlers, sending only to those receivers explicitly
- registered for a particular signal on a particular
- sender.
- """
- responses = []
- for receiver in liveReceivers(getReceivers(sender, signal)):
- response = robustapply.robustApply(
- receiver,
- signal=signal,
- sender=sender,
- *arguments,
- **named
- )
- responses.append((receiver, response))
- return responses
-
+ """Send signal only to those receivers registered for exact message
+
+ sendExact allows for avoiding Any/Anonymous registered
+ handlers, sending only to those receivers explicitly
+ registered for a particular signal on a particular
+ sender.
+ """
+ responses = []
+ for receiver in liveReceivers(getReceivers(sender, signal)):
+ response = robustapply.robustApply(
+ receiver,
+ signal=signal,
+ sender=sender,
+ *arguments,
+ **named
+ )
+ responses.append((receiver, response))
+ return responses
+
def _removeReceiver(receiver):
- """Remove receiver from connections."""
- if not sendersBack:
- # During module cleanup the mapping will be replaced with None
- return False
- backKey = id(receiver)
- for senderkey in sendersBack.get(backKey,()):
- try:
- signals = connections[senderkey].keys()
- except KeyError,err:
- pass
- else:
- for signal in signals:
- try:
- receivers = connections[senderkey][signal]
- except KeyError:
- pass
- else:
- try:
- receivers.remove( receiver )
- except Exception, err:
- pass
- _cleanupConnections(senderkey, signal)
- try:
- del sendersBack[ backKey ]
- except KeyError:
- pass
-
+ """Remove receiver from connections."""
+ if not sendersBack:
+ # During module cleanup the mapping will be replaced with None
+ return False
+ backKey = id(receiver)
+ for senderkey in sendersBack.get(backKey,()):
+ try:
+ signals = connections[senderkey].keys()
+ except KeyError,err:
+ pass
+ else:
+ for signal in signals:
+ try:
+ receivers = connections[senderkey][signal]
+ except KeyError:
+ pass
+ else:
+ try:
+ receivers.remove( receiver )
+ except Exception, err:
+ pass
+ _cleanupConnections(senderkey, signal)
+ try:
+ del sendersBack[ backKey ]
+ except KeyError:
+ pass
+
def _cleanupConnections(senderkey, signal):
- """Delete any empty signals for senderkey. Delete senderkey if empty."""
- try:
- receivers = connections[senderkey][signal]
- except:
- pass
- else:
- if not receivers:
- # No more connected receivers. Therefore, remove the signal.
- try:
- signals = connections[senderkey]
- except KeyError:
- pass
- else:
- del signals[signal]
- if not signals:
- # No more signal connections. Therefore, remove the sender.
- _removeSender(senderkey)
+ """Delete any empty signals for senderkey. Delete senderkey if empty."""
+ try:
+ receivers = connections[senderkey][signal]
+ except:
+ pass
+ else:
+ if not receivers:
+ # No more connected receivers. Therefore, remove the signal.
+ try:
+ signals = connections[senderkey]
+ except KeyError:
+ pass
+ else:
+ del signals[signal]
+ if not signals:
+ # No more signal connections. Therefore, remove the sender.
+ _removeSender(senderkey)
def _removeSender(senderkey):
- """Remove senderkey from connections."""
- _removeBackrefs(senderkey)
- try:
- del connections[senderkey]
- except KeyError:
- pass
- # Senderkey will only be in senders dictionary if sender
- # could be weakly referenced.
- try:
- del senders[senderkey]
- except:
- pass
+ """Remove senderkey from connections."""
+ _removeBackrefs(senderkey)
+ try:
+ del connections[senderkey]
+ except KeyError:
+ pass
+ # Senderkey will only be in senders dictionary if sender
+ # could be weakly referenced.
+ try:
+ del senders[senderkey]
+ except:
+ pass
def _removeBackrefs( senderkey):
- """Remove all back-references to this senderkey"""
- try:
- signals = connections[senderkey]
- except KeyError:
- signals = None
- else:
- items = signals.items()
- def allReceivers( ):
- for signal,set in items:
- for item in set:
- yield item
- for receiver in allReceivers():
- _killBackref( receiver, senderkey )
+ """Remove all back-references to this senderkey"""
+ try:
+ signals = connections[senderkey]
+ except KeyError:
+ signals = None
+ else:
+ items = signals.items()
+ def allReceivers( ):
+ for signal,set in items:
+ for item in set:
+ yield item
+ for receiver in allReceivers():
+ _killBackref( receiver, senderkey )
def _removeOldBackRefs(senderkey, signal, receiver, receivers):
- """Kill old sendersBack references from receiver
-
- This guards against multiple registration of the same
- receiver for a given signal and sender leaking memory
- as old back reference records build up.
-
- Also removes old receiver instance from receivers
- """
- try:
- index = receivers.index(receiver)
- # need to scan back references here and remove senderkey
- except ValueError:
- return False
- else:
- oldReceiver = receivers[index]
- del receivers[index]
- found = 0
- signals = connections.get(signal)
- if signals is not None:
- for sig,recs in connections.get(signal,{}).iteritems():
- if sig != signal:
- for rec in recs:
- if rec is oldReceiver:
- found = 1
- break
- if not found:
- _killBackref( oldReceiver, senderkey )
- return True
- return False
-
-
+ """Kill old sendersBack references from receiver
+
+ This guards against multiple registration of the same
+ receiver for a given signal and sender leaking memory
+ as old back reference records build up.
+
+ Also removes old receiver instance from receivers
+ """
+ try:
+ index = receivers.index(receiver)
+ # need to scan back references here and remove senderkey
+ except ValueError:
+ return False
+ else:
+ oldReceiver = receivers[index]
+ del receivers[index]
+ found = 0
+ signals = connections.get(signal)
+ if signals is not None:
+ for sig,recs in connections.get(signal,{}).iteritems():
+ if sig != signal:
+ for rec in recs:
+ if rec is oldReceiver:
+ found = 1
+ break
+ if not found:
+ _killBackref( oldReceiver, senderkey )
+ return True
+ return False
+
+
def _killBackref( receiver, senderkey ):
- """Do the actual removal of back reference from receiver to senderkey"""
- receiverkey = id(receiver)
- set = sendersBack.get( receiverkey, () )
- while senderkey in set:
- try:
- set.remove( senderkey )
- except:
- break
- if not set:
- try:
- del sendersBack[ receiverkey ]
- except KeyError:
- pass
- return True
+ """Do the actual removal of back reference from receiver to senderkey"""
+ receiverkey = id(receiver)
+ set = sendersBack.get( receiverkey, () )
+ while senderkey in set:
+ try:
+ set.remove( senderkey )
+ except:
+ break
+ if not set:
+ try:
+ del sendersBack[ receiverkey ]
+ except KeyError:
+ pass
+ return True
View
6 django/dispatch/errors.py
@@ -2,9 +2,9 @@
"""
class DispatcherError(Exception):
- """Base class for all Dispatcher errors"""
+ """Base class for all Dispatcher errors"""
class DispatcherKeyError(KeyError, DispatcherError):
- """Error raised when unknown (sender,signal) set specified"""
+ """Error raised when unknown (sender,signal) set specified"""
class DispatcherTypeError(TypeError, DispatcherError):
- """Error raised when inappropriate signal-type specified (None)"""
+ """Error raised when inappropriate signal-type specified (None)"""
View
62 django/dispatch/license.txt
@@ -1,34 +1,34 @@
PyDispatcher License
- Copyright (c) 2001-2003, Patrick K. O'Brien and Contributors
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- The name of Patrick K. O'Brien, or the name of any Contributor,
- may not be used to endorse or promote products derived from this
- software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- OF THE POSSIBILITY OF SUCH DAMAGE.
+ Copyright (c) 2001-2003, Patrick K. O'Brien and Contributors
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ The name of Patrick K. O'Brien, or the name of any Contributor,
+ may not be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ OF THE POSSIBILITY OF SUCH DAMAGE.
View
102 django/dispatch/robust.py
@@ -3,55 +3,55 @@
from django.dispatch.robustapply import robustApply
def sendRobust(
- signal=Any,
- sender=Anonymous,
- *arguments, **named
+ signal=Any,
+ sender=Anonymous,
+ *arguments, **named
):
- """Send signal from sender to all connected receivers catching errors
-
- signal -- (hashable) signal value, see connect for details
-
- sender -- the sender of the signal
-
- if Any, only receivers registered for Any will receive
- the message.
-
- if Anonymous, only receivers registered to receive
- messages from Anonymous or Any will receive the message
-
- Otherwise can be any python object (normally one
- registered with a connect if you actually want
- something to occur).
-
- arguments -- positional arguments which will be passed to
- *all* receivers. Note that this may raise TypeErrors
- if the receivers do not allow the particular arguments.
- Note also that arguments are applied before named
- arguments, so they should be used with care.
-
- named -- named arguments which will be filtered according
- to the parameters of the receivers to only provide those
- acceptable to the receiver.
-
- Return a list of tuple pairs [(receiver, response), ... ]
-
- if any receiver raises an error (specifically any subclass of Exception),
- the error instance is returned as the result for that receiver.
- """
- # Call each receiver with whatever arguments it can accept.
- # Return a list of tuple pairs [(receiver, response), ... ].
- responses = []
- for receiver in liveReceivers(getAllReceivers(sender, signal)):
- try:
- response = robustApply(
- receiver,
- signal=signal,
- sender=sender,
- *arguments,
- **named
- )
- except Exception, err:
- responses.append((receiver, err))
- else:
- responses.append((receiver, response))
- return responses
+ """Send signal from sender to all connected receivers catching errors
+
+ signal -- (hashable) signal value, see connect for details
+
+ sender -- the sender of the signal
+
+ if Any, only receivers registered for Any will receive
+ the message.
+
+ if Anonymous, only receivers registered to receive
+ messages from Anonymous or Any will receive the message
+
+ Otherwise can be any python object (normally one
+ registered with a connect if you actually want
+ something to occur).
+
+ arguments -- positional arguments which will be passed to
+ *all* receivers. Note that this may raise TypeErrors
+ if the receivers do not allow the particular arguments.
+ Note also that arguments are applied before named
+ arguments, so they should be used with care.
+
+ named -- named arguments which will be filtered according
+ to the parameters of the receivers to only provide those
+ acceptable to the receiver.
+
+ Return a list of tuple pairs [(receiver, response), ... ]
+
+ if any receiver raises an error (specifically any subclass of Exception),
+ the error instance is returned as the result for that receiver.
+ """
+ # Call each receiver with whatever arguments it can accept.
+ # Return a list of tuple pairs [(receiver, response), ... ].
+ responses = []
+ for receiver in liveReceivers(getAllReceivers(sender, signal)):
+ try:
+ response = robustApply(
+ receiver,
+ signal=signal,
+ sender=sender,
+ *arguments,
+ **named
+ )
+ except Exception, err:
+ responses.append((receiver, err))
+ else:
+ responses.append((receiver, response))
+ return responses
View
70 django/dispatch/robustapply.py
@@ -7,43 +7,41 @@
"""
def function( receiver ):
- """Get function-like callable object for given receiver
+ """Get function-like callable object for given receiver
- returns (function_or_method, codeObject, fromMethod)
+ returns (function_or_method, codeObject, fromMethod)
- If fromMethod is true, then the callable already
- has its first argument bound
- """
- if hasattr(receiver, '__call__'):
- # receiver is a class instance; assume it is callable.
- # Reassign receiver to the actual method that will be called.
- if hasattr( receiver.__call__, 'im_func') or hasattr( receiver.__call__, 'im_code'):
- receiver = receiver.__call__
- if hasattr( receiver, 'im_func' ):
- # an instance-method...
- return receiver, receiver.im_func.func_code, 1
- elif not hasattr( receiver, 'func_code'):
- raise ValueError('unknown reciever type %s %s'%(receiver, type(receiver)))
- return receiver, receiver.func_code, 0
+ If fromMethod is true, then the callable already
+ has its first argument bound
+ """
+ if hasattr(receiver, '__call__'):
+ # receiver is a class instance; assume it is callable.
+ # Reassign receiver to the actual method that will be called.
+ if hasattr( receiver.__call__, 'im_func') or hasattr( receiver.__call__, 'im_code'):
+ receiver = receiver.__call__
+ if hasattr( receiver, 'im_func' ):
+ # an instance-method...
+ return receiver, receiver.im_func.func_code, 1
+ elif not hasattr( receiver, 'func_code'):
+ raise ValueError('unknown reciever type %s %s'%(receiver, type(receiver)))
+ return receiver, receiver.func_code, 0
def robustApply(receiver, *arguments, **named):
- """Call receiver with arguments and an appropriate subset of named
- """
- receiver, codeObject, startIndex = function( receiver )
- acceptable = codeObject.co_varnames[startIndex+len(arguments):codeObject.co_argcount]
- for name in codeObject.co_varnames[startIndex:startIndex+len(arguments)]:
- if named.has_key( name ):
- raise TypeError(
- """Argument %r specified both positionally and as a keyword for calling %r"""% (
- name, receiver,
- )
- )
- if not (codeObject.co_flags & 8):
- # fc does not have a **kwds type parameter, therefore
- # remove unacceptable arguments.
- for arg in named.keys():
- if arg not in acceptable:
- del named[arg]
- return receiver(*arguments, **named)
-
-
+ """Call receiver with arguments and an appropriate subset of named
+ """
+ receiver, codeObject, startIndex = function( receiver )
+ acceptable = codeObject.co_varnames[startIndex+len(arguments):codeObject.co_argcount]
+ for name in codeObject.co_varnames[startIndex:startIndex+len(arguments)]:
+ if named.has_key( name ):
+ raise TypeError(
+ """Argument %r specified both positionally and as a keyword for calling %r"""% (
+ name, receiver,
+ )
+ )
+ if not (codeObject.co_flags & 8):
+ # fc does not have a **kwds type parameter, therefore
+ # remove unacceptable arguments.
+ for arg in named.keys():
+ if arg not in acceptable:
+ del named[arg]
+ return receiver(*arguments, **named)
View
298 django/dispatch/saferef.py
@@ -2,164 +2,164 @@
import weakref, traceback
def safeRef(target, onDelete = None):
- """Return a *safe* weak reference to a callable target
+ """Return a *safe* weak reference to a callable target
- target -- the object to be weakly referenced, if it's a
- bound method reference, will create a BoundMethodWeakref,
- otherwise creates a simple weakref.
- onDelete -- if provided, will have a hard reference stored
- to the callable to be called after the safe reference
- goes out of scope with the reference object, (either a
- weakref or a BoundMethodWeakref) as argument.
- """
- if hasattr(target, 'im_self'):
- if target.im_self is not None:
- # Turn a bound method into a BoundMethodWeakref instance.
- # Keep track of these instances for lookup by disconnect().
- assert hasattr(target, 'im_func'), """safeRef target %r has im_self, but no im_func, don't know how to create reference"""%( target,)
- reference = BoundMethodWeakref(
- target=target,
- onDelete=onDelete
- )
- return reference
- if callable(onDelete):
- return weakref.ref(target, onDelete)
- else:
- return weakref.ref( target )
+ target -- the object to be weakly referenced, if it's a
+ bound method reference, will create a BoundMethodWeakref,
+ otherwise creates a simple weakref.
+ onDelete -- if provided, will have a hard reference stored
+ to the callable to be called after the safe reference
+ goes out of scope with the reference object, (either a
+ weakref or a BoundMethodWeakref) as argument.
+ """
+ if hasattr(target, 'im_self'):
+ if target.im_self is not None:
+ # Turn a bound method into a BoundMethodWeakref instance.
+ # Keep track of these instances for lookup by disconnect().
+ assert hasattr(target, 'im_func'), """safeRef target %r has im_self, but no im_func, don't know how to create reference"""%( target,)
+ reference = BoundMethodWeakref(
+ target=target,
+ onDelete=onDelete
+ )
+ return reference
+ if callable(onDelete):
+ return weakref.ref(target, onDelete)
+ else:
+ return weakref.ref( target )
class BoundMethodWeakref(object):
- """'Safe' and reusable weak references to instance methods
+ """'Safe' and reusable weak references to instance methods
- BoundMethodWeakref objects provide a mechanism for
- referencing a bound method without requiring that the
- method object itself (which is normally a transient
- object) is kept alive. Instead, the BoundMethodWeakref
- object keeps weak references to both the object and the
- function which together define the instance method.
+ BoundMethodWeakref objects provide a mechanism for
+ referencing a bound method without requiring that the
+ method object itself (which is normally a transient
+ object) is kept alive. Instead, the BoundMethodWeakref
+ object keeps weak references to both the object and the
+ function which together define the instance method.
- Attributes:
- key -- the identity key for the reference, calculated
- by the class's calculateKey method applied to the
- target instance method
- deletionMethods -- sequence of callable objects taking
- single argument, a reference to this object which
- will be called when *either* the target object or
- target function is garbage collected (i.e. when
- this object becomes invalid). These are specified
- as the onDelete parameters of safeRef calls.
- weakSelf -- weak reference to the target object
- weakFunc -- weak reference to the target function
+ Attributes:
+ key -- the identity key for the reference, calculated
+ by the class's calculateKey method applied to the
+ target instance method
+ deletionMethods -- sequence of callable objects taking
+ single argument, a reference to this object which
+ will be called when *either* the target object or
+ target function is garbage collected (i.e. when
+ this object becomes invalid). These are specified
+ as the onDelete parameters of safeRef calls.
+ weakSelf -- weak reference to the target object
+ weakFunc -- weak reference to the target function
- Class Attributes:
- _allInstances -- class attribute pointing to all live
- BoundMethodWeakref objects indexed by the class's
- calculateKey(target) method applied to the target
- objects. This weak value dictionary is used to
- short-circuit creation so that multiple references
- to the same (object, function) pair produce the
- same BoundMethodWeakref instance.
+ Class Attributes:
+ _allInstances -- class attribute pointing to all live
+ BoundMethodWeakref objects indexed by the class's
+ calculateKey(target) method applied to the target
+ objects. This weak value dictionary is used to
+ short-circuit creation so that multiple references
+ to the same (object, function) pair produce the
+ same BoundMethodWeakref instance.
- """
- _allInstances = weakref.WeakValueDictionary()
- def __new__( cls, target, onDelete=None, *arguments,**named ):
- """Create new instance or return current instance
+ """
+ _allInstances = weakref.WeakValueDictionary()
+ def __new__( cls, target, onDelete=None, *arguments,**named ):
+ """Create new instance or return current instance
- Basically this method of construction allows us to
- short-circuit creation of references to already-
- referenced instance methods. The key corresponding
- to the target is calculated, and if there is already
- an existing reference, that is returned, with its
- deletionMethods attribute updated. Otherwise the
- new instance is created and registered in the table
- of already-referenced methods.
- """
- key = cls.calculateKey(target)
- current =cls._allInstances.get(key)
- if current is not None:
- current.deletionMethods.append( onDelete)
- return current
- else:
- base = super( BoundMethodWeakref, cls).__new__( cls )
- cls._allInstances[key] = base
- base.__init__( target, onDelete, *arguments,**named)
- return base
- def __init__(self, target, onDelete=None):
- """Return a weak-reference-like instance for a bound method
+ Basically this method of construction allows us to
+ short-circuit creation of references to already-
+ referenced instance methods. The key corresponding
+ to the target is calculated, and if there is already
+ an existing reference, that is returned, with its
+ deletionMethods attribute updated. Otherwise the
+ new instance is created and registered in the table
+ of already-referenced methods.
+ """
+ key = cls.calculateKey(target)
+ current =cls._allInstances.get(key)
+ if current is not None:
+ current.deletionMethods.append( onDelete)
+ return current
+ else:
+ base = super( BoundMethodWeakref, cls).__new__( cls )
+ cls._allInstances[key] = base
+ base.__init__( target, onDelete, *arguments,**named)
+ return base
+ def __init__(self, target, onDelete=None):
+ """Return a weak-reference-like instance for a bound method
- target -- the instance-method target for the weak
- reference, must have im_self and im_func attributes
- and be reconstructable via:
- target.im_func.__get__( target.im_self )
- which is true of built-in instance methods.
- onDelete -- optional callback which will be called
- when this weak reference ceases to be valid
- (i.e. either the object or the function is garbage
- collected). Should take a single argument,
- which will be passed a pointer to this object.
- """
- def remove(weak, self=self):
- """Set self.isDead to true when method or instance is destroyed"""
- methods = self.deletionMethods[:]
- del self.deletionMethods[:]
- try:
- del self.__class__._allInstances[ self.key ]
- except KeyError:
- pass
- for function in methods:
- try:
- if callable( function ):
- function( self )
- except Exception, e:
- try:
- traceback.print_exc()
- except AttributeError, err:
- print '''Exception during saferef %s cleanup function %s: %s'''%(
- self, function, e
- )
- self.deletionMethods = [onDelete]
- self.key = self.calculateKey( target )
- self.weakSelf = weakref.ref(target.im_self, remove)
- self.weakFunc = weakref.ref(target.im_func, remove)
- self.selfName = str(target.im_self)
- self.funcName = str(target.im_func.__name__)
- def calculateKey( cls, target ):
- """Calculate the reference key for this reference
+ target -- the instance-method target for the weak
+ reference, must have im_self and im_func attributes
+ and be reconstructable via:
+ target.im_func.__get__( target.im_self )
+ which is true of built-in instance methods.
+ onDelete -- optional callback which will be called
+ when this weak reference ceases to be valid
+ (i.e. either the object or the function is garbage
+ collected). Should take a single argument,
+ which will be passed a pointer to this object.
+ """
+ def remove(weak, self=self):
+ """Set self.isDead to true when method or instance is destroyed"""
+ methods = self.deletionMethods[:]
+ del self.deletionMethods[:]
+ try:
+ del self.__class__._allInstances[ self.key ]
+ except KeyError:
+ pass
+ for function in methods:
+ try:
+ if callable( function ):
+ function( self )
+ except Exception, e:
+ try:
+ traceback.print_exc()
+ except AttributeError, err:
+ print '''Exception during saferef %s cleanup function %s: %s'''%(
+ self, function, e
+ )
+ self.deletionMethods = [onDelete]
+ self.key = self.calculateKey( target )
+ self.weakSelf = weakref.ref(target.im_self, remove)
+ self.weakFunc = weakref.ref(target.im_func, remove)
+ self.selfName = str(target.im_self)
+ self.funcName = str(target.im_func.__name__)
+ def calculateKey( cls, target ):
+ """Calculate the reference key for this reference
- Currently this is a two-tuple of the id()'s of the
- target object and the target function respectively.
- """
- return (id(target.im_self),id(target.im_func))
- calculateKey = classmethod( calculateKey )
- def __str__(self):
- """Give a friendly representation of the object"""
- return """%s( %s.%s )"""%(
- self.__class__.__name__,
- self.selfName,
- self.funcName,
- )
- __repr__ = __str__
- def __nonzero__( self ):
- """Whether we are still a valid reference"""
- return self() is not None
- def __cmp__( self, other ):
- """Compare with another reference"""
- if not isinstance (other,self.__class__):
- return cmp( self.__class__, type(other) )
- return cmp( self.key, other.key)
- def __call__(self):
- """Return a strong reference to the bound method
+ Currently this is a two-tuple of the id()'s of the
+ target object and the target function respectively.
+ """
+ return (id(target.im_self),id(target.im_func))
+ calculateKey = classmethod( calculateKey )
+ def __str__(self):
+ """Give a friendly representation of the object"""
+ return """%s( %s.%s )"""%(
+ self.__class__.__name__,
+ self.selfName,
+ self.funcName,
+ )
+ __repr__ = __str__
+ def __nonzero__( self ):
+ """Whether we are still a valid reference"""
+ return self() is not None
+ def __cmp__( self, other ):
+ """Compare with another reference"""
+ if not isinstance (other,self.__class__):
+ return cmp( self.__class__, type(other) )
+ return cmp( self.key, other.key)
+ def __call__(self):
+ """Return a strong reference to the bound method
- If the target cannot be retrieved, then will
- return None, otherwise returns a bound instance
- method for our object and function.
+ If the target cannot be retrieved, then will
+ return None, otherwise returns a bound instance
+ method for our object and function.
- Note:
- You may call this method any number of times,
- as it does not invalidate the reference.
- """
- target = self.weakSelf()
- if target is not None:
- function = self.weakFunc()
- if function is not None:
- return function.__get__(target)
- return None
+ Note:
+ You may call this method any number of times,
+ as it does not invalidate the reference.
+ """
+ target = self.weakSelf()
+ if target is not None:
+ function = self.weakFunc()
+ if function is not None:
+ return function.__get__(target)
+ return None
View
2  django/template/defaultfilters.py
@@ -438,7 +438,7 @@ def pluralize(value, arg='s'):
the comma is used for the singular case.
"""
if not ',' in arg:
- arg = ',' + arg
+ arg = ',' + arg
bits = arg.split(',')
if len(bits) > 2:
return ''
View
4 docs/admin_css.txt
@@ -118,8 +118,8 @@ additional class on the ``a`` for that tool. These are ``.addlink`` and
Example from a changelist page::
<ul class="object-tools">
- <li><a href="/stories/add/" class="addlink">Add redirect</a></li>
- </ul>
+ <li><a href="/stories/add/" class="addlink">Add redirect</a></li>
+ </ul>
.. image:: http://media.djangoproject.com/img/doc/admincss/objecttools_01.gif
:alt: Object tools on a changelist page
Please sign in to comment.
Something went wrong with that request. Please try again.