1
0
mirror of https://github.com/django/django.git synced 2025-03-12 10:22:37 +00:00

Refs #27656 -- Updated django.utils docstring verbs according to PEP 257.

This commit is contained in:
Anton Samarchyan 2017-01-24 15:32:33 -05:00 committed by Tim Graham
parent 98bcc5d81b
commit 9718fa2e8a
30 changed files with 255 additions and 329 deletions

View File

@ -24,11 +24,11 @@ def npath(path):
def safe_join(base, *paths): def safe_join(base, *paths):
""" """
Joins one or more path components to the base path component intelligently. Join one or more path components to the base path component intelligently.
Returns a normalized, absolute version of the final path. Return a normalized, absolute version of the final path.
The final path must be located inside of the base path component (otherwise Raise ValueError if the final path isn't located inside of the base path
a ValueError is raised). component.
""" """
base = force_text(base) base = force_text(base)
paths = [force_text(p) for p in paths] paths = [force_text(p) for p in paths]
@ -52,9 +52,9 @@ def safe_join(base, *paths):
def symlinks_supported(): def symlinks_supported():
""" """
A function to check if creating symlinks are supported in the Return whether or not creating symlinks are supported in the host platform
host platform and/or if they are allowed to be created (e.g. and/or if they are allowed to be created (e.g. on Windows it requires admin
on Windows it requires admin permissions). permissions).
""" """
with tempfile.TemporaryDirectory() as temp_dir: with tempfile.TemporaryDirectory() as temp_dir:
original_path = os.path.join(temp_dir, 'original') original_path = os.path.join(temp_dir, 'original')

View File

@ -119,8 +119,8 @@ class BaseArchive:
def has_leading_dir(self, paths): def has_leading_dir(self, paths):
""" """
Returns true if all the paths have the same leading path name Return True if all the paths have the same leading path name
(i.e., everything is in one subdirectory in an archive) (i.e., everything is in one subdirectory in an archive).
""" """
common_prefix = None common_prefix = None
for path in paths: for path in paths:

View File

@ -81,8 +81,7 @@ _cached_filenames = []
def gen_filenames(only_new=False): def gen_filenames(only_new=False):
""" """
Returns a list of filenames referenced in sys.modules and translation Return a list of filenames referenced in sys.modules and translation files.
files.
""" """
# N.B. ``list(...)`` is needed, because this runs in parallel with # N.B. ``list(...)`` is needed, because this runs in parallel with
# application code which might be mutating ``sys.modules``, and this will # application code which might be mutating ``sys.modules``, and this will
@ -152,7 +151,7 @@ def reset_translations():
def inotify_code_changed(): def inotify_code_changed():
""" """
Checks for changed code using inotify. After being called Check for changed code using inotify. After being called
it blocks until a change event has been fired. it blocks until a change event has been fired.
""" """
class EventHandler(pyinotify.ProcessEvent): class EventHandler(pyinotify.ProcessEvent):

View File

@ -40,8 +40,8 @@ logger = logging.getLogger('django.request')
def patch_cache_control(response, **kwargs): def patch_cache_control(response, **kwargs):
""" """
This function patches the Cache-Control header by adding all Patch the Cache-Control header by adding all keyword arguments to it.
keyword arguments to it. The transformation is as follows: The transformation is as follows:
* All keyword parameter names are turned to lowercase, and underscores * All keyword parameter names are turned to lowercase, and underscores
are converted to hyphens. are converted to hyphens.
@ -89,8 +89,8 @@ def patch_cache_control(response, **kwargs):
def get_max_age(response): def get_max_age(response):
""" """
Returns the max-age from the response Cache-Control header as an integer Return the max-age from the response Cache-Control header as an integer,
(or ``None`` if it wasn't found or wasn't an integer. or None if it wasn't found or wasn't an integer.
""" """
if not response.has_header('Cache-Control'): if not response.has_header('Cache-Control'):
return return
@ -267,7 +267,7 @@ def patch_response_headers(response, cache_timeout=None):
def add_never_cache_headers(response): def add_never_cache_headers(response):
""" """
Adds headers to a response to indicate that a page should never be cached. Add headers to a response to indicate that a page should never be cached.
""" """
patch_response_headers(response, cache_timeout=-1) patch_response_headers(response, cache_timeout=-1)
patch_cache_control(response, no_cache=True, no_store=True, must_revalidate=True) patch_cache_control(response, no_cache=True, no_store=True, must_revalidate=True)
@ -275,7 +275,7 @@ def add_never_cache_headers(response):
def patch_vary_headers(response, newheaders): def patch_vary_headers(response, newheaders):
""" """
Adds (or updates) the "Vary" header in the given HttpResponse object. Add (or update) the "Vary" header in the given HttpResponse object.
newheaders is a list of header names that should be in "Vary". Existing newheaders is a list of header names that should be in "Vary". Existing
headers in "Vary" aren't removed. headers in "Vary" aren't removed.
""" """
@ -295,7 +295,7 @@ def patch_vary_headers(response, newheaders):
def has_vary_header(response, header_query): def has_vary_header(response, header_query):
""" """
Checks to see if the response has a given header name in its Vary header. Check to see if the response has a given header name in its Vary header.
""" """
if not response.has_header('Vary'): if not response.has_header('Vary'):
return False return False
@ -305,7 +305,7 @@ def has_vary_header(response, header_query):
def _i18n_cache_key_suffix(request, cache_key): def _i18n_cache_key_suffix(request, cache_key):
"""If necessary, adds the current locale or time zone to the cache key.""" """If necessary, add the current locale or time zone to the cache key."""
if settings.USE_I18N or settings.USE_L10N: if settings.USE_I18N or settings.USE_L10N:
# first check if LocaleMiddleware or another middleware added # first check if LocaleMiddleware or another middleware added
# LANGUAGE_CODE to request, then fall back to the active language # LANGUAGE_CODE to request, then fall back to the active language
@ -322,7 +322,7 @@ def _i18n_cache_key_suffix(request, cache_key):
def _generate_cache_key(request, method, headerlist, key_prefix): def _generate_cache_key(request, method, headerlist, key_prefix):
"""Returns a cache key from the headers given in the header list.""" """Return a cache key from the headers given in the header list."""
ctx = hashlib.md5() ctx = hashlib.md5()
for header in headerlist: for header in headerlist:
value = request.META.get(header) value = request.META.get(header)
@ -335,7 +335,7 @@ def _generate_cache_key(request, method, headerlist, key_prefix):
def _generate_cache_header_key(key_prefix, request): def _generate_cache_header_key(key_prefix, request):
"""Returns a cache key for the header cache.""" """Return a cache key for the header cache."""
url = hashlib.md5(force_bytes(iri_to_uri(request.build_absolute_uri()))) url = hashlib.md5(force_bytes(iri_to_uri(request.build_absolute_uri())))
cache_key = 'views.decorators.cache.cache_header.%s.%s' % ( cache_key = 'views.decorators.cache.cache_header.%s.%s' % (
key_prefix, url.hexdigest()) key_prefix, url.hexdigest())
@ -344,13 +344,13 @@ def _generate_cache_header_key(key_prefix, request):
def get_cache_key(request, key_prefix=None, method='GET', cache=None): def get_cache_key(request, key_prefix=None, method='GET', cache=None):
""" """
Returns a cache key based on the request URL and query. It can be used Return a cache key based on the request URL and query. It can be used
in the request phase because it pulls the list of headers to take into in the request phase because it pulls the list of headers to take into
account from the global URL registry and uses those to build a cache key account from the global URL registry and uses those to build a cache key
to check against. to check against.
If there is no headerlist stored, the page needs to be rebuilt, so this If there isn't a headerlist stored, return None, indicating that the page
function returns None. needs to be rebuilt.
""" """
if key_prefix is None: if key_prefix is None:
key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
@ -366,8 +366,8 @@ def get_cache_key(request, key_prefix=None, method='GET', cache=None):
def learn_cache_key(request, response, cache_timeout=None, key_prefix=None, cache=None): def learn_cache_key(request, response, cache_timeout=None, key_prefix=None, cache=None):
""" """
Learns what headers to take into account for some request URL from the Learn what headers to take into account for some request URL from the
response object. It stores those headers in a global URL registry so that response object. Store those headers in a global URL registry so that
later access to that URL will know what headers to take into account later access to that URL will know what headers to take into account
without building the response object itself. The headers are named in the without building the response object itself. The headers are named in the
Vary header of the response, but we want to prevent response generation. Vary header of the response, but we want to prevent response generation.

View File

@ -22,7 +22,7 @@ except NotImplementedError:
def salted_hmac(key_salt, value, secret=None): def salted_hmac(key_salt, value, secret=None):
""" """
Returns the HMAC-SHA1 of 'value', using a key generated from key_salt and a Return the HMAC-SHA1 of 'value', using a key generated from key_salt and a
secret (which defaults to settings.SECRET_KEY). secret (which defaults to settings.SECRET_KEY).
A different key_salt should be passed in for every application of HMAC. A different key_salt should be passed in for every application of HMAC.
@ -49,7 +49,7 @@ def get_random_string(length=12,
allowed_chars='abcdefghijklmnopqrstuvwxyz' allowed_chars='abcdefghijklmnopqrstuvwxyz'
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'): 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):
""" """
Returns a securely generated random string. Return a securely generated random string.
The default length of 12 with the a-z, A-Z, 0-9 character set returns The default length of 12 with the a-z, A-Z, 0-9 character set returns
a 71-bit value. log_2((26+26+10)^12) =~ 71 bits a 71-bit value. log_2((26+26+10)^12) =~ 71 bits

View File

@ -70,8 +70,8 @@ class MultiValueDict(dict):
def __getitem__(self, key): def __getitem__(self, key):
""" """
Returns the last data value for this key, or [] if it's an empty list; Return the last data value for this key, or [] if it's an empty list;
raises KeyError if not found. raise KeyError if not found.
""" """
try: try:
list_ = super().__getitem__(key) list_ = super().__getitem__(key)
@ -114,8 +114,8 @@ class MultiValueDict(dict):
def get(self, key, default=None): def get(self, key, default=None):
""" """
Returns the last data value for the passed key. If key doesn't exist Return the last data value for the passed key. If key doesn't exist
or value is an empty list, then default is returned. or value is an empty list, return `default`.
""" """
try: try:
val = self[key] val = self[key]
@ -170,19 +170,19 @@ class MultiValueDict(dict):
return self._getlist(key) return self._getlist(key)
def appendlist(self, key, value): def appendlist(self, key, value):
"""Appends an item to the internal list associated with key.""" """Append an item to the internal list associated with key."""
self.setlistdefault(key).append(value) self.setlistdefault(key).append(value)
def items(self): def items(self):
""" """
Yields (key, value) pairs, where value is the last item in the list Yield (key, value) pairs, where value is the last item in the list
associated with the key. associated with the key.
""" """
for key in self: for key in self:
yield key, self[key] yield key, self[key]
def lists(self): def lists(self):
"""Yields (key, list) pairs.""" """Yield (key, list) pairs."""
return iter(super().items()) return iter(super().items())
def values(self): def values(self):
@ -191,14 +191,11 @@ class MultiValueDict(dict):
yield self[key] yield self[key]
def copy(self): def copy(self):
"""Returns a shallow copy of this object.""" """Return a shallow copy of this object."""
return copy.copy(self) return copy.copy(self)
def update(self, *args, **kwargs): def update(self, *args, **kwargs):
""" """Extend rather than replace existing key lists."""
update() extends rather than replaces existing key lists.
Also accepts keyword args.
"""
if len(args) > 1: if len(args) > 1:
raise TypeError("update expected at most 1 arguments, got %d" % len(args)) raise TypeError("update expected at most 1 arguments, got %d" % len(args))
if args: if args:
@ -216,9 +213,7 @@ class MultiValueDict(dict):
self.setlistdefault(key).append(value) self.setlistdefault(key).append(value)
def dict(self): def dict(self):
""" """Return current object as a dict with singular values."""
Returns current object as a dict with singular values.
"""
return {key: self[key] for key in self} return {key: self[key] for key in self}
@ -264,7 +259,7 @@ class ImmutableList(tuple):
class DictWrapper(dict): class DictWrapper(dict):
""" """
Wraps accesses to a dictionary so that certain values (those starting with Wrap accesses to a dictionary so that certain values (those starting with
the specified prefix) are passed through a function before being returned. the specified prefix) are passed through a function before being returned.
The prefix is removed before looking up the real value. The prefix is removed before looking up the real value.
@ -278,7 +273,7 @@ class DictWrapper(dict):
def __getitem__(self, key): def __getitem__(self, key):
""" """
Retrieves the real value after stripping the prefix string (if Retrieve the real value after stripping the prefix string (if
present). If the prefix is present, pass the value through self.func present). If the prefix is present, pass the value through self.func
before returning, otherwise return the raw value. before returning, otherwise return the raw value.
""" """

View File

@ -77,8 +77,7 @@ class TimeFormat(Formatter):
""" """
Timezone name. Timezone name.
If timezone information is not available, this method returns If timezone information is not available, return an empty string.
an empty string.
""" """
if not self.timezone: if not self.timezone:
return "" return ""
@ -129,8 +128,7 @@ class TimeFormat(Formatter):
""" """
Difference to Greenwich time in hours; e.g. '+0200', '-0430'. Difference to Greenwich time in hours; e.g. '+0200', '-0430'.
If timezone information is not available, this method returns If timezone information is not available, return an empty string.
an empty string.
""" """
if not self.timezone: if not self.timezone:
return "" return ""
@ -163,8 +161,7 @@ class TimeFormat(Formatter):
""" """
Time zone of this machine; e.g. 'EST' or 'MDT'. Time zone of this machine; e.g. 'EST' or 'MDT'.
If timezone information is not available, this method returns If timezone information is not available, return an empty string.
an empty string.
""" """
if not self.timezone: if not self.timezone:
return "" return ""
@ -191,8 +188,7 @@ class TimeFormat(Formatter):
timezones west of UTC is always negative, and for those east of UTC is timezones west of UTC is always negative, and for those east of UTC is
always positive. always positive.
If timezone information is not available, this method returns If timezone information is not available, return an empty string.
an empty string.
""" """
if not self.timezone: if not self.timezone:
return "" return ""

View File

@ -52,10 +52,10 @@ iso8601_duration_re = re.compile(
def parse_date(value): def parse_date(value):
"""Parses a string and return a datetime.date. """Parse a string and return a datetime.date.
Raises ValueError if the input is well formatted but not a valid date. Raise ValueError if the input is well formatted but not a valid date.
Returns None if the input isn't well formatted. Return None if the input isn't well formatted.
""" """
match = date_re.match(value) match = date_re.match(value)
if match: if match:
@ -64,12 +64,12 @@ def parse_date(value):
def parse_time(value): def parse_time(value):
"""Parses a string and return a datetime.time. """Parse a string and return a datetime.time.
This function doesn't support time zone offsets. This function doesn't support time zone offsets.
Raises ValueError if the input is well formatted but not a valid time. Raise ValueError if the input is well formatted but not a valid time.
Returns None if the input isn't well formatted, in particular if it Return None if the input isn't well formatted, in particular if it
contains an offset. contains an offset.
""" """
match = time_re.match(value) match = time_re.match(value)
@ -82,13 +82,13 @@ def parse_time(value):
def parse_datetime(value): def parse_datetime(value):
"""Parses a string and return a datetime.datetime. """Parse a string and return a datetime.datetime.
This function supports time zone offsets. When the input contains one, This function supports time zone offsets. When the input contains one,
the output uses a timezone with a fixed offset from UTC. the output uses a timezone with a fixed offset from UTC.
Raises ValueError if the input is well formatted but not a valid datetime. Raise ValueError if the input is well formatted but not a valid datetime.
Returns None if the input isn't well formatted. Return None if the input isn't well formatted.
""" """
match = datetime_re.match(value) match = datetime_re.match(value)
if match: if match:
@ -110,7 +110,7 @@ def parse_datetime(value):
def parse_duration(value): def parse_duration(value):
"""Parses a duration string and returns a datetime.timedelta. """Parse a duration string and return a datetime.timedelta.
The preferred format for durations in Django is '%d %H:%M:%S.%f'. The preferred format for durations in Django is '%d %H:%M:%S.%f'.

View File

@ -5,10 +5,10 @@ from django.utils.version import get_docs_version
def deconstructible(*args, path=None): def deconstructible(*args, path=None):
""" """
Class decorator that allow the decorated class to be serialized Class decorator that allows the decorated class to be serialized
by the migrations subsystem. by the migrations subsystem.
Accepts an optional kwarg `path` to specify the import path. The `path` kwarg specifies the import path.
""" """
def decorator(klass): def decorator(klass):
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
@ -19,7 +19,7 @@ def deconstructible(*args, path=None):
def deconstruct(obj): def deconstruct(obj):
""" """
Returns a 3-tuple of class import path, positional arguments, Return a 3-tuple of class import path, positional arguments,
and keyword arguments. and keyword arguments.
""" """
# Fallback version # Fallback version

View File

@ -14,7 +14,7 @@ class classonlymethod(classmethod):
def method_decorator(decorator, name=''): def method_decorator(decorator, name=''):
""" """
Converts a function decorator into a method decorator Convert a function decorator into a method decorator
""" """
# 'obj' can be a class or a function. If 'obj' is a function at the time it # 'obj' can be a class or a function. If 'obj' is a function at the time it
# is passed to _dec, it will eventually be a method of the class it is # is passed to _dec, it will eventually be a method of the class it is
@ -90,7 +90,7 @@ def method_decorator(decorator, name=''):
def decorator_from_middleware_with_args(middleware_class): def decorator_from_middleware_with_args(middleware_class):
""" """
Like decorator_from_middleware, but returns a function Like decorator_from_middleware, but return a function
that accepts the arguments to be passed to the middleware_class. that accepts the arguments to be passed to the middleware_class.
Use like:: Use like::
@ -106,7 +106,7 @@ def decorator_from_middleware_with_args(middleware_class):
def decorator_from_middleware(middleware_class): def decorator_from_middleware(middleware_class):
""" """
Given a middleware class (not an instance), returns a view decorator. This Given a middleware class (not an instance), return a view decorator. This
lets you use middleware functionality on a per-view basis. The middleware lets you use middleware functionality on a per-view basis. The middleware
is created with no params passed. is created with no params passed.
""" """

View File

@ -72,7 +72,7 @@ def force_text(s, encoding='utf-8', strings_only=False, errors='strict'):
def smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict'): def smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict'):
""" """
Returns a bytestring version of 's', encoded as specified in 'encoding'. Return a bytestring version of 's', encoded as specified in 'encoding'.
If strings_only is True, don't convert (some) non-string-like objects. If strings_only is True, don't convert (some) non-string-like objects.
""" """
@ -171,12 +171,12 @@ _hextobyte.update({
def uri_to_iri(uri): def uri_to_iri(uri):
""" """
Converts a Uniform Resource Identifier(URI) into an Internationalized Convert a Uniform Resource Identifier(URI) into an Internationalized
Resource Identifier(IRI). Resource Identifier(IRI).
This is the algorithm from section 3.2 of RFC 3987, excluding step 4. This is the algorithm from section 3.2 of RFC 3987, excluding step 4.
Takes an URI in ASCII bytes (e.g. '/I%20%E2%99%A5%20Django/') and returns Take an URI in ASCII bytes (e.g. '/I%20%E2%99%A5%20Django/') and return
a string containing the encoded result (e.g. '/I%20♥%20Django/'). a string containing the encoded result (e.g. '/I%20♥%20Django/').
""" """
if uri is None: if uri is None:
@ -225,8 +225,8 @@ def escape_uri_path(path):
def repercent_broken_unicode(path): def repercent_broken_unicode(path):
""" """
As per section 3.2 of RFC 3987, step three of converting a URI into an IRI, As per section 3.2 of RFC 3987, step three of converting a URI into an IRI,
we need to re-percent-encode any octet produced that is not part of a repercent-encode any octet produced that is not part of a strictly legal
strictly legal UTF-8 octet sequence. UTF-8 octet sequence.
""" """
try: try:
path.decode() path.decode()
@ -241,12 +241,9 @@ def filepath_to_uri(path):
"""Convert a file system path to a URI portion that is suitable for """Convert a file system path to a URI portion that is suitable for
inclusion in a URL. inclusion in a URL.
This method will encode certain chars that would normally be recognized as Encode certain chars that would normally be recognized as special chars
special chars for URIs. Note that this method does not encode the ' for URIs. Do not encode the ' character, as it is a valid character
character, as it is a valid character within URIs. See within URIs. See the encodeURIComponent() JavaScript function for details.
encodeURIComponent() JavaScript function for more details.
Return a string containing the result.
""" """
if path is None: if path is None:
return path return path
@ -257,9 +254,9 @@ def filepath_to_uri(path):
def get_system_encoding(): def get_system_encoding():
""" """
The encoding of the default system locale but falls back to the given The encoding of the default system locale. Fallback to 'ascii' if the
fallback encoding if the encoding is unsupported by python or could #encoding is unsupported by Python or could not be determined. See tickets
not be determined. See tickets #10335 and #5846 #10335 and #5846.
""" """
try: try:
encoding = locale.getdefaultlocale()[1] or 'ascii' encoding = locale.getdefaultlocale()[1] or 'ascii'

View File

@ -68,7 +68,7 @@ def rfc3339_date(date):
def get_tag_uri(url, date): def get_tag_uri(url, date):
""" """
Creates a TagURI. Create a TagURI.
See http://web.archive.org/web/20110514113830/http://diveintomark.org/archives/2004/05/28/howto-atom-id See http://web.archive.org/web/20110514113830/http://diveintomark.org/archives/2004/05/28/howto-atom-id
""" """
@ -176,14 +176,14 @@ class SyndicationFeed:
def write(self, outfile, encoding): def write(self, outfile, encoding):
""" """
Outputs the feed in the given encoding to outfile, which is a file-like Output the feed in the given encoding to outfile, which is a file-like
object. Subclasses should override this. object. Subclasses should override this.
""" """
raise NotImplementedError('subclasses of SyndicationFeed must provide a write() method') raise NotImplementedError('subclasses of SyndicationFeed must provide a write() method')
def writeString(self, encoding): def writeString(self, encoding):
""" """
Returns the feed in the given encoding as a string. Return the feed in the given encoding as a string.
""" """
s = StringIO() s = StringIO()
self.write(s, encoding) self.write(s, encoding)
@ -191,8 +191,8 @@ class SyndicationFeed:
def latest_post_date(self): def latest_post_date(self):
""" """
Returns the latest item's pubdate or updateddate. If no items Return the latest item's pubdate or updateddate. If no items
have either of these attributes this returns the current UTC date/time. have either of these attributes this return the current UTC date/time.
""" """
latest_date = None latest_date = None
date_keys = ('updateddate', 'pubdate') date_keys = ('updateddate', 'pubdate')
@ -209,7 +209,7 @@ class SyndicationFeed:
class Enclosure: class Enclosure:
"Represents an RSS enclosure" """An RSS enclosure"""
def __init__(self, url, length, mime_type): def __init__(self, url, length, mime_type):
"All args are expected to be strings" "All args are expected to be strings"
self.length, self.mime_type = length, mime_type self.length, self.mime_type = length, mime_type

View File

@ -59,9 +59,7 @@ def reset_format_cache():
def iter_format_modules(lang, format_module_path=None): def iter_format_modules(lang, format_module_path=None):
""" """Find format modules."""
Does the heavy lifting of finding format modules.
"""
if not check_for_language(lang): if not check_for_language(lang):
return return
@ -88,9 +86,7 @@ def iter_format_modules(lang, format_module_path=None):
def get_format_modules(lang=None, reverse=False): def get_format_modules(lang=None, reverse=False):
""" """Return a list of the format modules found."""
Returns a list of the format modules found
"""
if lang is None: if lang is None:
lang = get_language() lang = get_language()
if lang not in _format_modules_cache: if lang not in _format_modules_cache:
@ -103,11 +99,11 @@ def get_format_modules(lang=None, reverse=False):
def get_format(format_type, lang=None, use_l10n=None): def get_format(format_type, lang=None, use_l10n=None):
""" """
For a specific format type, returns the format for the current For a specific format type, return the format for the current
language (locale), defaults to the format in the settings. language (locale). Default to the format in the settings.
format_type is the name of the format, e.g. 'DATE_FORMAT' format_type is the name of the format, e.g. 'DATE_FORMAT'.
If use_l10n is provided and is not None, that will force the value to If use_l10n is provided and is not None, it forces the value to
be localized (or not), overriding the value of settings.USE_L10N. be localized (or not), overriding the value of settings.USE_L10N.
""" """
use_l10n = use_l10n or (use_l10n is None and settings.USE_L10N) use_l10n = use_l10n or (use_l10n is None and settings.USE_L10N)
@ -151,8 +147,8 @@ get_format_lazy = lazy(get_format, str, list, tuple)
def date_format(value, format=None, use_l10n=None): def date_format(value, format=None, use_l10n=None):
""" """
Formats a datetime.date or datetime.datetime object using a Format a datetime.date or datetime.datetime object using a
localizable format localizable format.
If use_l10n is provided and is not None, that will force the value to If use_l10n is provided and is not None, that will force the value to
be localized (or not), overriding the value of settings.USE_L10N. be localized (or not), overriding the value of settings.USE_L10N.
@ -162,9 +158,9 @@ def date_format(value, format=None, use_l10n=None):
def time_format(value, format=None, use_l10n=None): def time_format(value, format=None, use_l10n=None):
""" """
Formats a datetime.time object using a localizable format Format a datetime.time object using a localizable format.
If use_l10n is provided and is not None, that will force the value to If use_l10n is provided and is not None, it forces the value to
be localized (or not), overriding the value of settings.USE_L10N. be localized (or not), overriding the value of settings.USE_L10N.
""" """
return dateformat.time_format(value, get_format(format or 'TIME_FORMAT', use_l10n=use_l10n)) return dateformat.time_format(value, get_format(format or 'TIME_FORMAT', use_l10n=use_l10n))
@ -172,9 +168,9 @@ def time_format(value, format=None, use_l10n=None):
def number_format(value, decimal_pos=None, use_l10n=None, force_grouping=False): def number_format(value, decimal_pos=None, use_l10n=None, force_grouping=False):
""" """
Formats a numeric value using localization settings Format a numeric value using localization settings.
If use_l10n is provided and is not None, that will force the value to If use_l10n is provided and is not None, it forces the value to
be localized (or not), overriding the value of settings.USE_L10N. be localized (or not), overriding the value of settings.USE_L10N.
""" """
if use_l10n or (use_l10n is None and settings.USE_L10N): if use_l10n or (use_l10n is None and settings.USE_L10N):
@ -193,10 +189,10 @@ def number_format(value, decimal_pos=None, use_l10n=None, force_grouping=False):
def localize(value, use_l10n=None): def localize(value, use_l10n=None):
""" """
Checks if value is a localizable type (date, number...) and returns it Check if value is a localizable type (date, number...) and return it
formatted as a string using current locale format. formatted as a string using current locale format.
If use_l10n is provided and is not None, that will force the value to If use_l10n is provided and is not None, it forces the value to
be localized (or not), overriding the value of settings.USE_L10N. be localized (or not), overriding the value of settings.USE_L10N.
""" """
if isinstance(value, str): # Handle strings first for performance reasons. if isinstance(value, str): # Handle strings first for performance reasons.
@ -216,7 +212,7 @@ def localize(value, use_l10n=None):
def localize_input(value, default=None): def localize_input(value, default=None):
""" """
Checks if an input value is a localizable type and returns it Check if an input value is a localizable type and return it
formatted with the appropriate formatting string of the current locale. formatted with the appropriate formatting string of the current locale.
""" """
if isinstance(value, str): # Handle strings first for performance reasons. if isinstance(value, str): # Handle strings first for performance reasons.
@ -241,7 +237,7 @@ def localize_input(value, default=None):
def sanitize_separators(value): def sanitize_separators(value):
""" """
Sanitizes a value according to the current decimal and Sanitize a value according to the current decimal and
thousand separator setting. Used with form field input. thousand separator setting. Used with form field input.
""" """
if settings.USE_L10N and isinstance(value, str): if settings.USE_L10N and isinstance(value, str):

View File

@ -34,17 +34,16 @@ class cached_property:
class Promise: class Promise:
""" """
This is just a base class for the proxy class created in Base class for the proxy class created in the closure of the lazy function.
the closure of the lazy function. It can be used to recognize It's used to recognize promises in code.
promises in code.
""" """
pass pass
def lazy(func, *resultclasses): def lazy(func, *resultclasses):
""" """
Turns any callable into a lazy evaluated callable. You need to give result Turn any callable into a lazy evaluated callable. result classes or types
classes or types -- at least one is needed so that the automatic forcing of is required -- at least one is needed so that the automatic forcing of
the lazy evaluation code is triggered. Results are not memoized; the the lazy evaluation code is triggered. Results are not memoized; the
function is evaluated on every access. function is evaluated on every access.
""" """
@ -383,7 +382,7 @@ class SimpleLazyObject(LazyObject):
def partition(predicate, values): def partition(predicate, values):
""" """
Splits the values into two sets, based on the return value of the function Split the values into two sets, based on the return value of the function
(True/False). e.g.: (True/False). e.g.:
>>> partition(lambda x: x > 3, range(5)) >>> partition(lambda x: x > 3, range(5))

View File

@ -35,12 +35,12 @@ simple_email_re = re.compile(r'^\S+@\S+\.\S+$')
@keep_lazy(str, SafeText) @keep_lazy(str, SafeText)
def escape(text): def escape(text):
""" """
Returns the given text with ampersands, quotes and angle brackets encoded Return the given text with ampersands, quotes and angle brackets encoded
for use in HTML. for use in HTML.
This function always escapes its input, even if it's already escaped and Always escape input, even if it's already escaped and marked as such.
marked as such. This may result in double-escaping. If this is a concern, This may result in double-escaping. If this is a concern, use
use conditional_escape() instead. conditional_escape() instead.
""" """
return mark_safe( return mark_safe(
force_text(text).replace('&', '&amp;').replace('<', '&lt;') force_text(text).replace('&', '&amp;').replace('<', '&lt;')
@ -68,7 +68,7 @@ _js_escapes.update((ord('%c' % z), '\\u%04X' % z) for z in range(32))
@keep_lazy(str, SafeText) @keep_lazy(str, SafeText)
def escapejs(value): def escapejs(value):
"""Hex encodes characters for use in JavaScript strings.""" """Hex encode characters for use in JavaScript strings."""
return mark_safe(force_text(value).translate(_js_escapes)) return mark_safe(force_text(value).translate(_js_escapes))
@ -89,8 +89,8 @@ def conditional_escape(text):
def format_html(format_string, *args, **kwargs): def format_html(format_string, *args, **kwargs):
""" """
Similar to str.format, but passes all arguments through conditional_escape, Similar to str.format, but pass all arguments through conditional_escape(),
and calls 'mark_safe' on the result. This function should be used instead and call mark_safe() on the result. This function should be used instead
of str.format or % interpolation to build up small HTML fragments. of str.format or % interpolation to build up small HTML fragments.
""" """
args_safe = map(conditional_escape, args) args_safe = map(conditional_escape, args)
@ -119,7 +119,7 @@ def format_html_join(sep, format_string, args_generator):
@keep_lazy_text @keep_lazy_text
def linebreaks(value, autoescape=False): def linebreaks(value, autoescape=False):
"""Converts newlines into <p> and <br />s.""" """Convert newlines into <p> and <br />s."""
value = normalize_newlines(force_text(value)) value = normalize_newlines(force_text(value))
paras = re.split('\n{2,}', value) paras = re.split('\n{2,}', value)
if autoescape: if autoescape:
@ -167,7 +167,7 @@ def _strip_once(value):
@keep_lazy_text @keep_lazy_text
def strip_tags(value): def strip_tags(value):
"""Returns the given HTML with all tags stripped.""" """Return the given HTML with all tags stripped."""
# Note: in typical case this loop executes _strip_once once. Loop condition # Note: in typical case this loop executes _strip_once once. Loop condition
# is redundant, but helps to reduce number of executions of _strip_once. # is redundant, but helps to reduce number of executions of _strip_once.
value = force_text(value) value = force_text(value)
@ -182,12 +182,12 @@ def strip_tags(value):
@keep_lazy_text @keep_lazy_text
def strip_spaces_between_tags(value): def strip_spaces_between_tags(value):
"""Returns the given HTML with spaces between tags removed.""" """Return the given HTML with spaces between tags removed."""
return re.sub(r'>\s+<', '><', force_text(value)) return re.sub(r'>\s+<', '><', force_text(value))
def smart_urlquote(url): def smart_urlquote(url):
"Quotes a URL if it isn't already quoted." """Quote a URL if it isn't already quoted."""
def unquote_quote(segment): def unquote_quote(segment):
segment = unquote(segment) segment = unquote(segment)
# Tilde is part of RFC3986 Unreserved Characters # Tilde is part of RFC3986 Unreserved Characters
@ -225,20 +225,19 @@ def smart_urlquote(url):
@keep_lazy_text @keep_lazy_text
def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False): def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
""" """
Converts any URLs in text into clickable links. Convert any URLs in text into clickable links.
Works on http://, https://, www. links, and also on links ending in one of Works on http://, https://, www. links, and also on links ending in one of
the original seven gTLDs (.com, .edu, .gov, .int, .mil, .net, and .org). the original seven gTLDs (.com, .edu, .gov, .int, .mil, .net, and .org).
Links can have trailing punctuation (periods, commas, close-parens) and Links can have trailing punctuation (periods, commas, close-parens) and
leading punctuation (opening parens) and it'll still do the right thing. leading punctuation (opening parens) and it'll still do the right thing.
If trim_url_limit is not None, the URLs in the link text longer than this If trim_url_limit is not None, truncate the URLs in the link text longer
limit will be truncated to trim_url_limit-3 characters and appended with than this limit to trim_url_limit-3 characters and append an ellipsis.
an ellipsis.
If nofollow is True, the links will get a rel="nofollow" attribute. If nofollow is True, give the links a rel="nofollow" attribute.
If autoescape is True, the link text and URLs will be autoescaped. If autoescape is True, autoescape the link text and URLs.
""" """
safe_input = isinstance(text, SafeData) safe_input = isinstance(text, SafeData)
@ -249,8 +248,8 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
def unescape(text, trail): def unescape(text, trail):
""" """
If input URL is HTML-escaped, unescape it so as we can safely feed it to If input URL is HTML-escaped, unescape it so that it can be safely fed
smart_urlquote. For example: to smart_urlquote. For example:
http://example.com?x=1&amp;y=&lt;2&gt; => http://example.com?x=1&y=<2> http://example.com?x=1&amp;y=&lt;2&gt; => http://example.com?x=1&y=<2>
""" """
unescaped = (text + trail).replace( unescaped = (text + trail).replace(

View File

@ -98,13 +98,13 @@ def urlencode(query, doseq=False):
def cookie_date(epoch_seconds=None): def cookie_date(epoch_seconds=None):
""" """
Formats the time to ensure compatibility with Netscape's cookie standard. Format the time to ensure compatibility with Netscape's cookie standard.
Accepts a floating point number expressed in seconds since the epoch, in `epoch_seconds` is a floating point number expressed in seconds since the
UTC - such as that outputted by time.time(). If set to None, defaults to epoch, in UTC - such as that outputted by time.time(). If set to None, it
the current time. defaults to the current time.
Outputs a string in the format 'Wdy, DD-Mon-YYYY HH:MM:SS GMT'. Output a string in the format 'Wdy, DD-Mon-YYYY HH:MM:SS GMT'.
""" """
rfcdate = formatdate(epoch_seconds) rfcdate = formatdate(epoch_seconds)
return '%s-%s-%s GMT' % (rfcdate[:7], rfcdate[8:11], rfcdate[12:25]) return '%s-%s-%s GMT' % (rfcdate[:7], rfcdate[8:11], rfcdate[12:25])
@ -112,26 +112,26 @@ def cookie_date(epoch_seconds=None):
def http_date(epoch_seconds=None): def http_date(epoch_seconds=None):
""" """
Formats the time to match the RFC1123 date format as specified by HTTP Format the time to match the RFC1123 date format as specified by HTTP
RFC7231 section 7.1.1.1. RFC7231 section 7.1.1.1.
Accepts a floating point number expressed in seconds since the epoch, in `epoch_seconds` is a floating point number expressed in seconds since the
UTC - such as that outputted by time.time(). If set to None, defaults to epoch, in UTC - such as that outputted by time.time(). If set to None, it
the current time. defaults to the current time.
Outputs a string in the format 'Wdy, DD Mon YYYY HH:MM:SS GMT'. Output a string in the format 'Wdy, DD Mon YYYY HH:MM:SS GMT'.
""" """
return formatdate(epoch_seconds, usegmt=True) return formatdate(epoch_seconds, usegmt=True)
def parse_http_date(date): def parse_http_date(date):
""" """
Parses a date format as specified by HTTP RFC7231 section 7.1.1.1. Parse a date format as specified by HTTP RFC7231 section 7.1.1.1.
The three formats allowed by the RFC are accepted, even if only the first The three formats allowed by the RFC are accepted, even if only the first
one is still in widespread use. one is still in widespread use.
Returns an integer expressed in seconds since the epoch, in UTC. Return an integer expressed in seconds since the epoch, in UTC.
""" """
# emails.Util.parsedate does the job for RFC1123 dates; unfortunately # emails.Util.parsedate does the job for RFC1123 dates; unfortunately
# RFC7231 makes it mandatory to support RFC850 dates too. So we roll # RFC7231 makes it mandatory to support RFC850 dates too. So we roll
@ -162,7 +162,7 @@ def parse_http_date(date):
def parse_http_date_safe(date): def parse_http_date_safe(date):
""" """
Same as parse_http_date, but returns None if the input is invalid. Same as parse_http_date, but return None if the input is invalid.
""" """
try: try:
return parse_http_date(date) return parse_http_date(date)
@ -174,8 +174,8 @@ def parse_http_date_safe(date):
def base36_to_int(s): def base36_to_int(s):
""" """
Converts a base 36 string to an ``int``. Raises ``ValueError` if the Convert a base 36 string to an int. Raise ValueError if the input won't fit
input won't fit into an int. into an int.
""" """
# To prevent overconsumption of server resources, reject any # To prevent overconsumption of server resources, reject any
# base36 string that is longer than 13 base36 digits (13 digits # base36 string that is longer than 13 base36 digits (13 digits
@ -186,9 +186,7 @@ def base36_to_int(s):
def int_to_base36(i): def int_to_base36(i):
""" """Convert an integer to a base36 string."""
Converts an integer to a base36 string
"""
char_set = '0123456789abcdefghijklmnopqrstuvwxyz' char_set = '0123456789abcdefghijklmnopqrstuvwxyz'
if i < 0: if i < 0:
raise ValueError("Negative base36 conversion input.") raise ValueError("Negative base36 conversion input.")
@ -203,15 +201,15 @@ def int_to_base36(i):
def urlsafe_base64_encode(s): def urlsafe_base64_encode(s):
""" """
Encodes a bytestring in base64 for use in URLs, stripping any trailing Encode a bytestring in base64 for use in URLs. Strip any trailing equal
equal signs. signs.
""" """
return base64.urlsafe_b64encode(s).rstrip(b'\n=') return base64.urlsafe_b64encode(s).rstrip(b'\n=')
def urlsafe_base64_decode(s): def urlsafe_base64_decode(s):
""" """
Decodes a base64 encoded string, adding back any trailing equal signs that Decode a base64 encoded string. Add back any trailing equal signs that
might have been stripped. might have been stripped.
""" """
s = force_bytes(s) s = force_bytes(s)
@ -270,7 +268,7 @@ def is_safe_url(url, host=None, allowed_hosts=None, require_https=False):
Return ``True`` if the url is a safe redirection (i.e. it doesn't point to Return ``True`` if the url is a safe redirection (i.e. it doesn't point to
a different host and uses a safe scheme). a different host and uses a safe scheme).
Always returns ``False`` on an empty url. Always return ``False`` on an empty url.
If ``require_https`` is ``True``, only 'https' will be considered a valid If ``require_https`` is ``True``, only 'https' will be considered a valid
scheme, as opposed to 'http' and 'https' with the default, ``False``. scheme, as opposed to 'http' and 'https' with the default, ``False``.

View File

@ -37,13 +37,7 @@ def clean_ipv6_address(ip_str, unpack_ipv4=False,
def is_valid_ipv6_address(ip_str): def is_valid_ipv6_address(ip_str):
""" """
Ensure we have a valid IPv6 address. Return whether or not the `ip_str` string is a valid IPv6 address.
Args:
ip_str: A string, the IPv6 address.
Returns:
A boolean, True if this is a valid IPv6 address.
""" """
try: try:
ipaddress.IPv6Address(ip_str) ipaddress.IPv6Address(ip_str)

View File

@ -1,12 +1,5 @@
"""
Providing iterator functions that are not in all version of Python we support.
Where possible, we try to use the system-native version and only fall back to
these implementations if necessary.
"""
def is_iterable(x): def is_iterable(x):
"A implementation independent way of checking for iterables" "An implementation independent way of checking for iterables"
try: try:
iter(x) iter(x)
except TypeError: except TypeError:

View File

@ -50,7 +50,7 @@ class Lexer:
""" """
Lexically analyze `text`. Lexically analyze `text`.
Yields pairs (`name`, `tokentext`). Yield pairs (`name`, `tokentext`).
""" """
end = len(text) end = len(text)
state = self.state state = self.state

View File

@ -55,7 +55,7 @@ COMMON_WORDS = (
def sentence(): def sentence():
""" """
Returns a randomly generated sentence of lorem ipsum text. Return a randomly generated sentence of lorem ipsum text.
The first word is capitalized, and the sentence ends in either a period or The first word is capitalized, and the sentence ends in either a period or
question mark. Commas are added at random. question mark. Commas are added at random.
@ -70,7 +70,7 @@ def sentence():
def paragraph(): def paragraph():
""" """
Returns a randomly generated paragraph of lorem ipsum text. Return a randomly generated paragraph of lorem ipsum text.
The paragraph consists of between 1 and 4 sentences, inclusive. The paragraph consists of between 1 and 4 sentences, inclusive.
""" """
@ -79,7 +79,7 @@ def paragraph():
def paragraphs(count, common=True): def paragraphs(count, common=True):
""" """
Returns a list of paragraphs as returned by paragraph(). Return a list of paragraphs as returned by paragraph().
If `common` is True, then the first paragraph will be the standard If `common` is True, then the first paragraph will be the standard
'lorem ipsum' paragraph. Otherwise, the first paragraph will be random 'lorem ipsum' paragraph. Otherwise, the first paragraph will be random
@ -96,7 +96,7 @@ def paragraphs(count, common=True):
def words(count, common=True): def words(count, common=True):
""" """
Returns a string of `count` lorem ipsum words separated by a single space. Return a string of `count` lorem ipsum words separated by a single space.
If `common` is True, then the first 19 words will be the standard If `common` is True, then the first 19 words will be the standard
'lorem ipsum' words. Otherwise, all words will be selected randomly. 'lorem ipsum' words. Otherwise, all words will be selected randomly.

View File

@ -7,7 +7,7 @@ from django.utils.safestring import mark_safe
def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='', def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='',
force_grouping=False): force_grouping=False):
""" """
Gets a number (as a number or string), and returns it as a string, Get a number (as a number or string), and return it as a string,
using formats defined as arguments: using formats defined as arguments:
* decimal_sep: Decimal separator symbol (for example ".") * decimal_sep: Decimal separator symbol (for example ".")

View File

@ -27,28 +27,20 @@ ESCAPE_MAPPINGS = {
class Choice(list): class Choice(list):
""" """Represent multiple possibilities at this point in a pattern string."""
Used to represent multiple possibilities at this point in a pattern string.
We use a distinguished type, rather than a list, so that the usage in the
code is clear.
"""
class Group(list): class Group(list):
""" """Represent a capturing group in the pattern string."""
Used to represent a capturing group in the pattern string.
"""
class NonCapture(list): class NonCapture(list):
""" """Represent a non-capturing group in the pattern string."""
Used to represent a non-capturing group in the pattern string.
"""
def normalize(pattern): def normalize(pattern):
r""" r"""
Given a reg-exp pattern, normalizes it to an iterable of forms that Given a reg-exp pattern, normalize it to an iterable of forms that
suffice for reverse matching. This does the following: suffice for reverse matching. This does the following:
(1) For any repeating sections, keeps the minimum number of occurrences (1) For any repeating sections, keeps the minimum number of occurrences
@ -212,7 +204,7 @@ def next_char(input_iter):
its class (e.g. \w -> "x"). If the escaped character is one that is its class (e.g. \w -> "x"). If the escaped character is one that is
skipped, it is not returned (the next character is returned instead). skipped, it is not returned (the next character is returned instead).
Yields the next character, along with a boolean indicating whether it is a Yield the next character, along with a boolean indicating whether it is a
raw (unescaped) character or not. raw (unescaped) character or not.
""" """
for ch in input_iter: for ch in input_iter:
@ -228,8 +220,8 @@ def next_char(input_iter):
def walk_to_end(ch, input_iter): def walk_to_end(ch, input_iter):
""" """
The iterator is currently inside a capturing group. We want to walk to the The iterator is currently inside a capturing group. Walk to the close of
close of this group, skipping over any nested groups and handling escaped this group, skipping over any nested groups and handling escaped
parentheses correctly. parentheses correctly.
""" """
if ch == '(': if ch == '(':
@ -252,7 +244,7 @@ def get_quantifier(ch, input_iter):
Parse a quantifier from the input, where "ch" is the first character in the Parse a quantifier from the input, where "ch" is the first character in the
quantifier. quantifier.
Returns the minimum number of occurrences permitted by the quantifier and Return the minimum number of occurrences permitted by the quantifier and
either None or the next character from the input_iter if the next character either None or the next character from the input_iter if the next character
is not part of the quantifier. is not part of the quantifier.
""" """
@ -286,7 +278,7 @@ def get_quantifier(ch, input_iter):
def contains(source, inst): def contains(source, inst):
""" """
Returns True if the "source" contains an instance of "inst". False, Return True if the "source" contains an instance of "inst". False,
otherwise. otherwise.
""" """
if isinstance(source, inst): if isinstance(source, inst):
@ -300,8 +292,8 @@ def contains(source, inst):
def flatten_result(source): def flatten_result(source):
""" """
Turns the given source sequence into a list of reg-exp possibilities and Turn the given source sequence into a list of reg-exp possibilities and
their arguments. Returns a list of strings and a list of argument lists. their arguments. Return a list of strings and a list of argument lists.
Each of the two lists will be of the same length. Each of the two lists will be of the same length.
""" """
if source is None: if source is None:

View File

@ -11,7 +11,7 @@ from django.utils.functional import Promise, wraps
class SafeData: class SafeData:
def __html__(self): def __html__(self):
""" """
Returns the html representation of a string for interoperability. Return the html representation of a string for interoperability.
This allows other template engines to understand Django's SafeData. This allows other template engines to understand Django's SafeData.
""" """

View File

@ -12,12 +12,12 @@ opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conce
def colorize(text='', opts=(), **kwargs): def colorize(text='', opts=(), **kwargs):
""" """
Returns your text, enclosed in ANSI graphics codes. Return your text, enclosed in ANSI graphics codes.
Depends on the keyword arguments 'fg' and 'bg', and the contents of Depends on the keyword arguments 'fg' and 'bg', and the contents of
the opts tuple/list. the opts tuple/list.
Returns the RESET code if no parameters are given. Return the RESET code if no parameters are given.
Valid colors: Valid colors:
'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white' 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'
@ -57,7 +57,7 @@ def colorize(text='', opts=(), **kwargs):
def make_style(opts=(), **kwargs): def make_style(opts=(), **kwargs):
""" """
Returns a function with default parameters for colorize() Return a function with default parameters for colorize()
Example: Example:
bold_red = make_style(opts=('bold',), fg='red') bold_red = make_style(opts=('bold',), fg='red')

View File

@ -32,10 +32,10 @@ def wrap(text, width):
A word-wrap function that preserves existing line breaks. Expects that A word-wrap function that preserves existing line breaks. Expects that
existing line breaks are posix newlines. existing line breaks are posix newlines.
All white space is preserved except added line breaks consume the space on Preserve all white space except added line breaks consume the space on
which they break the line. which they break the line.
Long words are not wrapped, so the output text may have lines longer than Don't wrap long words, thus the output text may have lines longer than
``width``. ``width``.
""" """
text = force_text(text) text = force_text(text)
@ -84,12 +84,12 @@ class Truncator(SimpleLazyObject):
def chars(self, num, truncate=None, html=False): def chars(self, num, truncate=None, html=False):
""" """
Returns the text truncated to be no longer than the specified number Return the text truncated to be no longer than the specified number
of characters. of characters.
Takes an optional argument of what should be used to notify that the `truncate` specifies what should be used to notify that the string has
string has been truncated, defaulting to a translatable string of an been truncated, defaulting to a translatable string of an ellipsis
ellipsis (...). (...).
""" """
self._setup() self._setup()
length = int(num) length = int(num)
@ -107,9 +107,7 @@ class Truncator(SimpleLazyObject):
return self._text_chars(length, truncate, text, truncate_len) return self._text_chars(length, truncate, text, truncate_len)
def _text_chars(self, length, truncate, text, truncate_len): def _text_chars(self, length, truncate, text, truncate_len):
""" """Truncate a string after a certain number of chars."""
Truncates a string after a certain number of chars.
"""
s_len = 0 s_len = 0
end_index = None end_index = None
for i, char in enumerate(text): for i, char in enumerate(text):
@ -130,9 +128,9 @@ class Truncator(SimpleLazyObject):
def words(self, num, truncate=None, html=False): def words(self, num, truncate=None, html=False):
""" """
Truncates a string after a certain number of words. Takes an optional Truncate a string after a certain number of words. `truncate` specifies
argument of what should be used to notify that the string has been what should be used to notify that the string has been truncated,
truncated, defaulting to ellipsis (...). defaulting to ellipsis (...).
""" """
self._setup() self._setup()
length = int(num) length = int(num)
@ -142,9 +140,9 @@ class Truncator(SimpleLazyObject):
def _text_words(self, length, truncate): def _text_words(self, length, truncate):
""" """
Truncates a string after a certain number of words. Truncate a string after a certain number of words.
Newlines in the string will be stripped. Strip newlines in the string.
""" """
words = self._wrapped.split() words = self._wrapped.split()
if len(words) > length: if len(words) > length:
@ -154,11 +152,11 @@ class Truncator(SimpleLazyObject):
def _truncate_html(self, length, truncate, text, truncate_len, words): def _truncate_html(self, length, truncate, text, truncate_len, words):
""" """
Truncates HTML to a certain number of chars (not counting tags and Truncate HTML to a certain number of chars (not counting tags and
comments), or, if words is True, then to a certain number of words. comments), or, if words is True, then to a certain number of words.
Closes opened tags if they were correctly closed in the given HTML. Close opened tags if they were correctly closed in the given HTML.
Newlines in the HTML are preserved. Preserve newlines in the HTML.
""" """
if words and length <= 0: if words and length <= 0:
return '' return ''
@ -228,10 +226,10 @@ class Truncator(SimpleLazyObject):
@keep_lazy_text @keep_lazy_text
def get_valid_filename(s): def get_valid_filename(s):
""" """
Returns the given string converted to a string that can be used for a clean Return the given string converted to a string that can be used for a clean
filename. Specifically, leading and trailing spaces are removed; other filename. Remove leading and trailing spaces; convert other spaces to
spaces are converted to underscores; and anything that is not an underscores; and remove anything that is not an alphanumeric, dash,
alphanumeric, dash, underscore, or dot, is removed. underscore, or dot.
>>> get_valid_filename("john's portrait in 2004.jpg") >>> get_valid_filename("john's portrait in 2004.jpg")
'johns_portrait_in_2004.jpg' 'johns_portrait_in_2004.jpg'
""" """
@ -265,14 +263,14 @@ def get_text_list(list_, last_word=gettext_lazy('or')):
@keep_lazy_text @keep_lazy_text
def normalize_newlines(text): def normalize_newlines(text):
"""Normalizes CRLF and CR newlines to just LF.""" """Normalize CRLF and CR newlines to just LF."""
text = force_text(text) text = force_text(text)
return re_newlines.sub('\n', text) return re_newlines.sub('\n', text)
@keep_lazy_text @keep_lazy_text
def phone2numeric(phone): def phone2numeric(phone):
"""Converts a phone number with letters into its numeric equivalent.""" """Convert a phone number with letters into its numeric equivalent."""
char2number = { char2number = {
'a': '2', 'b': '2', 'c': '2', 'd': '3', 'e': '3', 'f': '3', 'g': '4', 'a': '2', 'b': '2', 'c': '2', 'd': '3', 'e': '3', 'f': '3', 'g': '4',
'h': '4', 'i': '4', 'j': '5', 'k': '5', 'l': '5', 'm': '6', 'n': '6', 'h': '4', 'i': '4', 'j': '5', 'k': '5', 'l': '5', 'm': '6', 'n': '6',
@ -426,8 +424,7 @@ def slugify(value, allow_unicode=False):
def camel_case_to_spaces(value): def camel_case_to_spaces(value):
""" """
Splits CamelCase and converts to lower case. Also strips leading and Split CamelCase and convert to lower case. Strip surrounding whitespace.
trailing whitespace.
""" """
return re_camel_case.sub(r' \1', value).strip().lower() return re_camel_case.sub(r' \1', value).strip().lower()

View File

@ -17,9 +17,9 @@ TIMESINCE_CHUNKS = (
def timesince(d, now=None, reversed=False): def timesince(d, now=None, reversed=False):
""" """
Takes two datetime objects and returns the time between d and now Take two datetime objects and return the time between d and now as a nicely
as a nicely formatted string, e.g. "10 minutes". If d occurs after now, formatted string, e.g. "10 minutes". If d occurs after now, return
then "0 minutes" is returned. "0 minutes".
Units used are years, months, weeks, days, hours, and minutes. Units used are years, months, weeks, days, hours, and minutes.
Seconds and microseconds are ignored. Up to two adjacent units will be Seconds and microseconds are ignored. Up to two adjacent units will be
@ -72,7 +72,6 @@ def timesince(d, now=None, reversed=False):
def timeuntil(d, now=None): def timeuntil(d, now=None):
""" """
Like timesince, but returns a string measuring the time until Like timesince, but return a string measuring the time until the given time.
the given time.
""" """
return timesince(d, now, reversed=True) return timesince(d, now, reversed=True)

View File

@ -51,14 +51,12 @@ class FixedOffset(tzinfo):
return ZERO return ZERO
# UTC time zone as a tzinfo instance.
utc = pytz.utc utc = pytz.utc
"""UTC time zone as a tzinfo instance."""
def get_fixed_timezone(offset): def get_fixed_timezone(offset):
""" """Return a tzinfo instance with a fixed offset from UTC."""
Returns a tzinfo instance with a fixed offset from UTC.
"""
if isinstance(offset, timedelta): if isinstance(offset, timedelta):
offset = offset.seconds // 60 offset = offset.seconds // 60
sign = '-' if offset < 0 else '+' sign = '-' if offset < 0 else '+'
@ -72,7 +70,7 @@ def get_fixed_timezone(offset):
@functools.lru_cache() @functools.lru_cache()
def get_default_timezone(): def get_default_timezone():
""" """
Returns the default time zone as a tzinfo instance. Return the default time zone as a tzinfo instance.
This is the time zone defined by settings.TIME_ZONE. This is the time zone defined by settings.TIME_ZONE.
""" """
@ -81,9 +79,7 @@ def get_default_timezone():
# This function exists for consistency with get_current_timezone_name # This function exists for consistency with get_current_timezone_name
def get_default_timezone_name(): def get_default_timezone_name():
""" """Return the name of the default time zone."""
Returns the name of the default time zone.
"""
return _get_timezone_name(get_default_timezone()) return _get_timezone_name(get_default_timezone())
@ -91,23 +87,17 @@ _active = local()
def get_current_timezone(): def get_current_timezone():
""" """Return the currently active time zone as a tzinfo instance."""
Returns the currently active time zone as a tzinfo instance.
"""
return getattr(_active, "value", get_default_timezone()) return getattr(_active, "value", get_default_timezone())
def get_current_timezone_name(): def get_current_timezone_name():
""" """Return the name of the currently active time zone."""
Returns the name of the currently active time zone.
"""
return _get_timezone_name(get_current_timezone()) return _get_timezone_name(get_current_timezone())
def _get_timezone_name(timezone): def _get_timezone_name(timezone):
""" """Return the name of ``timezone``."""
Returns the name of ``timezone``.
"""
try: try:
# for pytz timezones # for pytz timezones
return timezone.zone return timezone.zone
@ -123,7 +113,7 @@ def _get_timezone_name(timezone):
def activate(timezone): def activate(timezone):
""" """
Sets the time zone for the current thread. Set the time zone for the current thread.
The ``timezone`` argument must be an instance of a tzinfo subclass or a The ``timezone`` argument must be an instance of a tzinfo subclass or a
time zone name. time zone name.
@ -138,7 +128,7 @@ def activate(timezone):
def deactivate(): def deactivate():
""" """
Unsets the time zone for the current thread. Unset the time zone for the current thread.
Django will then use the time zone defined by settings.TIME_ZONE. Django will then use the time zone defined by settings.TIME_ZONE.
""" """
@ -150,8 +140,8 @@ class override(ContextDecorator):
""" """
Temporarily set the time zone for the current thread. Temporarily set the time zone for the current thread.
This is a context manager that uses ``~django.utils.timezone.activate()`` This is a context manager that uses django.utils.timezone.activate()
to set the timezone on entry, and restores the previously active timezone to set the timezone on entry and restores the previously active timezone
on exit. on exit.
The ``timezone`` argument must be an instance of a ``tzinfo`` subclass, a The ``timezone`` argument must be an instance of a ``tzinfo`` subclass, a
@ -179,7 +169,7 @@ class override(ContextDecorator):
def template_localtime(value, use_tz=None): def template_localtime(value, use_tz=None):
""" """
Checks if value is a datetime and converts it to local time if necessary. Check if value is a datetime and converts it to local time if necessary.
If use_tz is provided and is not None, that will force the value to If use_tz is provided and is not None, that will force the value to
be converted (or not), overriding the value of settings.USE_TZ. be converted (or not), overriding the value of settings.USE_TZ.
@ -199,7 +189,7 @@ def template_localtime(value, use_tz=None):
def localtime(value=None, timezone=None): def localtime(value=None, timezone=None):
""" """
Converts an aware datetime.datetime to local time. Convert an aware datetime.datetime to local time.
Only aware datetimes are allowed. When value is omitted, it defaults to Only aware datetimes are allowed. When value is omitted, it defaults to
now(). now().
@ -236,7 +226,7 @@ def localdate(value=None, timezone=None):
def now(): def now():
""" """
Returns an aware or naive datetime.datetime, depending on settings.USE_TZ. Return an aware or naive datetime.datetime, depending on settings.USE_TZ.
""" """
if settings.USE_TZ: if settings.USE_TZ:
# timeit shows that datetime.now(tz=utc) is 24% slower # timeit shows that datetime.now(tz=utc) is 24% slower
@ -250,7 +240,7 @@ def now():
def is_aware(value): def is_aware(value):
""" """
Determines if a given datetime.datetime is aware. Determine if a given datetime.datetime is aware.
The concept is defined in Python's docs: The concept is defined in Python's docs:
http://docs.python.org/library/datetime.html#datetime.tzinfo http://docs.python.org/library/datetime.html#datetime.tzinfo
@ -263,7 +253,7 @@ def is_aware(value):
def is_naive(value): def is_naive(value):
""" """
Determines if a given datetime.datetime is naive. Determine if a given datetime.datetime is naive.
The concept is defined in Python's docs: The concept is defined in Python's docs:
http://docs.python.org/library/datetime.html#datetime.tzinfo http://docs.python.org/library/datetime.html#datetime.tzinfo
@ -275,9 +265,7 @@ def is_naive(value):
def make_aware(value, timezone=None, is_dst=None): def make_aware(value, timezone=None, is_dst=None):
""" """Make a naive datetime.datetime in a given time zone aware."""
Makes a naive datetime.datetime in a given time zone aware.
"""
if timezone is None: if timezone is None:
timezone = get_current_timezone() timezone = get_current_timezone()
if hasattr(timezone, 'localize'): if hasattr(timezone, 'localize'):
@ -293,9 +281,7 @@ def make_aware(value, timezone=None, is_dst=None):
def make_naive(value, timezone=None): def make_naive(value, timezone=None):
""" """Make an aware datetime.datetime naive in a given time zone."""
Makes an aware datetime.datetime naive in a given time zone.
"""
if timezone is None: if timezone is None:
timezone = get_current_timezone() timezone = get_current_timezone()
# Emulate the behavior of astimezone() on Python < 3.6. # Emulate the behavior of astimezone() on Python < 3.6.

View File

@ -59,7 +59,7 @@ def reset_cache(**kwargs):
def to_locale(language, to_lower=False): def to_locale(language, to_lower=False):
""" """
Turns a language name (en-us) into a locale name (en_US). If 'to_lower' is Turn a language name (en-us) into a locale name (en_US). If 'to_lower' is
True, the last component is lower-cased (en_us). True, the last component is lower-cased (en_us).
""" """
p = language.find('-') p = language.find('-')
@ -76,7 +76,7 @@ def to_locale(language, to_lower=False):
def to_language(locale): def to_language(locale):
"""Turns a locale name (en_US) into a language name (en-us).""" """Turn a locale name (en_US) into a language name (en-us)."""
p = locale.find('_') p = locale.find('_')
if p >= 0: if p >= 0:
return locale[:p].lower() + '-' + locale[p + 1:].lower() return locale[:p].lower() + '-' + locale[p + 1:].lower()
@ -86,8 +86,7 @@ def to_language(locale):
class DjangoTranslation(gettext_module.GNUTranslations): class DjangoTranslation(gettext_module.GNUTranslations):
""" """
This class sets up the GNUTranslations context with regard to output Set up the GNUTranslations context with regard to output charset.
charset.
This translation object will be constructed out of multiple GNUTranslations This translation object will be constructed out of multiple GNUTranslations
objects by merging their catalogs. It will construct an object for the objects by merging their catalogs. It will construct an object for the
@ -138,7 +137,7 @@ class DjangoTranslation(gettext_module.GNUTranslations):
def _new_gnu_trans(self, localedir, use_null_fallback=True): def _new_gnu_trans(self, localedir, use_null_fallback=True):
""" """
Returns a mergeable gettext.GNUTranslations instance. Return a mergeable gettext.GNUTranslations instance.
A convenience wrapper. By default gettext uses 'fallback=False'. A convenience wrapper. By default gettext uses 'fallback=False'.
Using param `use_null_fallback` to avoid confusion with any other Using param `use_null_fallback` to avoid confusion with any other
@ -152,14 +151,14 @@ class DjangoTranslation(gettext_module.GNUTranslations):
fallback=use_null_fallback) fallback=use_null_fallback)
def _init_translation_catalog(self): def _init_translation_catalog(self):
"""Creates a base catalog using global django translations.""" """Create a base catalog using global django translations."""
settingsfile = sys.modules[settings.__module__].__file__ settingsfile = sys.modules[settings.__module__].__file__
localedir = os.path.join(os.path.dirname(settingsfile), 'locale') localedir = os.path.join(os.path.dirname(settingsfile), 'locale')
translation = self._new_gnu_trans(localedir) translation = self._new_gnu_trans(localedir)
self.merge(translation) self.merge(translation)
def _add_installed_apps_translations(self): def _add_installed_apps_translations(self):
"""Merges translations from each installed app.""" """Merge translations from each installed app."""
try: try:
app_configs = reversed(list(apps.get_app_configs())) app_configs = reversed(list(apps.get_app_configs()))
except AppRegistryNotReady: except AppRegistryNotReady:
@ -174,13 +173,13 @@ class DjangoTranslation(gettext_module.GNUTranslations):
self.merge(translation) self.merge(translation)
def _add_local_translations(self): def _add_local_translations(self):
"""Merges translations defined in LOCALE_PATHS.""" """Merge translations defined in LOCALE_PATHS."""
for localedir in reversed(settings.LOCALE_PATHS): for localedir in reversed(settings.LOCALE_PATHS):
translation = self._new_gnu_trans(localedir) translation = self._new_gnu_trans(localedir)
self.merge(translation) self.merge(translation)
def _add_fallback(self, localedirs=None): def _add_fallback(self, localedirs=None):
"""Sets the GNUTranslations() fallback with the default language.""" """Set the GNUTranslations() fallback with the default language."""
# Don't set a fallback for the default language or any English variant # Don't set a fallback for the default language or any English variant
# (as it's empty, so it'll ALWAYS fall back to the default language) # (as it's empty, so it'll ALWAYS fall back to the default language)
if self.__language == settings.LANGUAGE_CODE or self.__language.startswith('en'): if self.__language == settings.LANGUAGE_CODE or self.__language.startswith('en'):
@ -207,17 +206,17 @@ class DjangoTranslation(gettext_module.GNUTranslations):
self._catalog.update(other._catalog) self._catalog.update(other._catalog)
def language(self): def language(self):
"""Returns the translation language.""" """Return the translation language."""
return self.__language return self.__language
def to_language(self): def to_language(self):
"""Returns the translation language name.""" """Return the translation language name."""
return self.__to_language return self.__to_language
def translation(language): def translation(language):
""" """
Returns a translation object in the default 'django' domain. Return a translation object in the default 'django' domain.
""" """
global _translations global _translations
if language not in _translations: if language not in _translations:
@ -227,7 +226,7 @@ def translation(language):
def activate(language): def activate(language):
""" """
Fetches the translation object for a given language and installs it as the Fetch the translation object for a given language and install it as the
current translation object for the current thread. current translation object for the current thread.
""" """
if not language: if not language:
@ -237,8 +236,8 @@ def activate(language):
def deactivate(): def deactivate():
""" """
Deinstalls the currently active translation object so that further _ calls Uninstall the active translation object so that further _() calls resolve
will resolve against the default translation object, again. to the default translation object.
""" """
if hasattr(_active, "value"): if hasattr(_active, "value"):
del _active.value del _active.value
@ -246,7 +245,7 @@ def deactivate():
def deactivate_all(): def deactivate_all():
""" """
Makes the active translation object a NullTranslations() instance. This is Make the active translation object a NullTranslations() instance. This is
useful when we want delayed translations to appear as the original string useful when we want delayed translations to appear as the original string
for some reason. for some reason.
""" """
@ -255,7 +254,7 @@ def deactivate_all():
def get_language(): def get_language():
"""Returns the currently selected language.""" """Return the currently selected language."""
t = getattr(_active, "value", None) t = getattr(_active, "value", None)
if t is not None: if t is not None:
try: try:
@ -268,7 +267,7 @@ def get_language():
def get_language_bidi(): def get_language_bidi():
""" """
Returns selected language's BiDi layout. Return selected language's BiDi layout.
* False = left-to-right layout * False = left-to-right layout
* True = right-to-left layout * True = right-to-left layout
@ -283,7 +282,7 @@ def get_language_bidi():
def catalog(): def catalog():
""" """
Returns the current active catalog for further processing. Return the current active catalog for further processing.
This can be used if you need to modify the catalog or want to access the This can be used if you need to modify the catalog or want to access the
whole message catalog instead of just translating one string. whole message catalog instead of just translating one string.
""" """
@ -308,7 +307,7 @@ def gettext(message):
eol_message = message.replace('\r\n', '\n').replace('\r', '\n') eol_message = message.replace('\r\n', '\n').replace('\r', '\n')
if len(eol_message) == 0: if len(eol_message) == 0:
# Returns an empty value of the corresponding type if an empty message # Return an empty value of the corresponding type if an empty message
# is given, instead of metadata, which is the default gettext behavior. # is given, instead of metadata, which is the default gettext behavior.
result = type(message)("") result = type(message)("")
else: else:
@ -335,7 +334,7 @@ def pgettext(context, message):
def gettext_noop(message): def gettext_noop(message):
""" """
Marks strings for translation but doesn't translate them now. This can be Mark strings for translation but don't translate them now. This can be
used to store strings in global variables that should stay in the base used to store strings in global variables that should stay in the base
language (because they might be used externally) and will be translated language (because they might be used externally) and will be translated
later. later.
@ -356,7 +355,7 @@ def do_ntranslate(singular, plural, number, translation_function):
def ngettext(singular, plural, number): def ngettext(singular, plural, number):
""" """
Returns a string of the translation of either the singular or plural, Return a string of the translation of either the singular or plural,
based on the number. based on the number.
""" """
return do_ntranslate(singular, plural, number, 'ngettext') return do_ntranslate(singular, plural, number, 'ngettext')
@ -375,7 +374,7 @@ def npgettext(context, singular, plural, number):
def all_locale_paths(): def all_locale_paths():
""" """
Returns a list of paths to user-provides languages files. Return a list of paths to user-provides languages files.
""" """
globalpath = os.path.join( globalpath = os.path.join(
os.path.dirname(sys.modules[settings.__module__].__file__), 'locale') os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
@ -385,7 +384,7 @@ def all_locale_paths():
@functools.lru_cache(maxsize=1000) @functools.lru_cache(maxsize=1000)
def check_for_language(lang_code): def check_for_language(lang_code):
""" """
Checks whether there is a global language file for the given language Check whether there is a global language file for the given language
code. This is used to decide whether a user-provided language is code. This is used to decide whether a user-provided language is
available. available.
@ -413,10 +412,10 @@ def get_languages():
@functools.lru_cache(maxsize=1000) @functools.lru_cache(maxsize=1000)
def get_supported_language_variant(lang_code, strict=False): def get_supported_language_variant(lang_code, strict=False):
""" """
Returns the language-code that's listed in supported languages, possibly Return the language-code that's listed in supported languages, possibly
selecting a more generic variant. Raises LookupError if nothing found. selecting a more generic variant. Raise LookupError if nothing is found.
If `strict` is False (the default), the function will look for an alternative If `strict` is False (the default), look for an alternative
country-specific variant when the currently checked is not found. country-specific variant when the currently checked is not found.
lru_cache should have a maxsize to prevent from memory exhaustion attacks, lru_cache should have a maxsize to prevent from memory exhaustion attacks,
@ -447,7 +446,7 @@ def get_supported_language_variant(lang_code, strict=False):
def get_language_from_path(path, strict=False): def get_language_from_path(path, strict=False):
""" """
Returns the language-code if there is a valid language-code Return the language-code if there is a valid language-code
found in the `path`. found in the `path`.
If `strict` is False (the default), the function will look for an alternative If `strict` is False (the default), the function will look for an alternative
@ -465,7 +464,7 @@ def get_language_from_path(path, strict=False):
def get_language_from_request(request, check_path=False): def get_language_from_request(request, check_path=False):
""" """
Analyzes the request to find what language the user wants the system to Analyze the request to find what language the user wants the system to
show. Only languages listed in settings.LANGUAGES are taken into account. show. Only languages listed in settings.LANGUAGES are taken into account.
If the user requests a sublanguage where we have a main language, we send If the user requests a sublanguage where we have a main language, we send
out the main language. out the main language.
@ -513,10 +512,10 @@ def get_language_from_request(request, check_path=False):
def parse_accept_lang_header(lang_string): def parse_accept_lang_header(lang_string):
""" """
Parses the lang_string, which is the body of an HTTP Accept-Language Parse the lang_string, which is the body of an HTTP Accept-Language
header, and returns a list of (lang, q-value), ordered by 'q' values. header, and return a list of (lang, q-value), ordered by 'q' values.
Any format errors in lang_string results in an empty list being returned. Return an empty list if there are any format errors in lang_string.
""" """
result = [] result = []
pieces = accept_language_re.split(lang_string.lower()) pieces = accept_language_re.split(lang_string.lower())

View File

@ -17,25 +17,22 @@ class Node:
default = 'DEFAULT' default = 'DEFAULT'
def __init__(self, children=None, connector=None, negated=False): def __init__(self, children=None, connector=None, negated=False):
""" """Construct a new Node. If no connector is given, use the default."""
Constructs a new Node. If no connector is given, the default will be
used.
"""
self.children = children[:] if children else [] self.children = children[:] if children else []
self.connector = connector or self.default self.connector = connector or self.default
self.negated = negated self.negated = negated
# We need this because of django.db.models.query_utils.Q. Q. __init__() is # Required because django.db.models.query_utils.Q. Q. __init__() is
# problematic, but it is a natural Node subclass in all other respects. # problematic, but it is a natural Node subclass in all other respects.
@classmethod @classmethod
def _new_instance(cls, children=None, connector=None, negated=False): def _new_instance(cls, children=None, connector=None, negated=False):
""" """
This is called to create a new instance of this class when we need new Create a new instance of this class when new Nodes (or subclasses) are
Nodes (or subclasses) in the internal code in this class. Normally, it needed in the internal code in this class. Normally, it just shadows
just shadows __init__(). However, subclasses with an __init__ signature __init__(). However, subclasses with an __init__ signature that aren't
that is not an extension of Node.__init__ might need to implement this an extension of Node.__init__ might need to implement this method to
method to allow a Node to create a new instance of them (if they have allow a Node to create a new instance of them (if they have any extra
any extra setting up to do). setting up to do).
""" """
obj = Node(children, connector, negated) obj = Node(children, connector, negated)
obj.__class__ = cls obj.__class__ = cls
@ -49,43 +46,34 @@ class Node:
return "<%s: %s>" % (self.__class__.__name__, self) return "<%s: %s>" % (self.__class__.__name__, self)
def __deepcopy__(self, memodict): def __deepcopy__(self, memodict):
"""
Utility method used by copy.deepcopy().
"""
obj = Node(connector=self.connector, negated=self.negated) obj = Node(connector=self.connector, negated=self.negated)
obj.__class__ = self.__class__ obj.__class__ = self.__class__
obj.children = copy.deepcopy(self.children, memodict) obj.children = copy.deepcopy(self.children, memodict)
return obj return obj
def __len__(self): def __len__(self):
""" """Return the the number of children this node has."""
The size of a node if the number of children it has.
"""
return len(self.children) return len(self.children)
def __bool__(self): def __bool__(self):
""" """Return whether or not this node has children."""
For truth value testing.
"""
return bool(self.children) return bool(self.children)
def __contains__(self, other): def __contains__(self, other):
""" """Return True if 'other' is a direct child of this instance."""
Returns True is 'other' is a direct child of this instance.
"""
return other in self.children return other in self.children
def add(self, data, conn_type, squash=True): def add(self, data, conn_type, squash=True):
""" """
Combines this tree and the data represented by data using the Combine this tree and the data represented by data using the
connector conn_type. The combine is done by squashing the node other connector conn_type. The combine is done by squashing the node other
away if possible. away if possible.
This tree (self) will never be pushed to a child node of the This tree (self) will never be pushed to a child node of the
combined tree, nor will the connector or negated properties change. combined tree, nor will the connector or negated properties change.
The function returns a node which can be used in place of data Return a node which can be used in place of data regardless if the
regardless if the node other got squashed or not. node other got squashed or not.
If `squash` is False the data is prepared and added as a child to If `squash` is False the data is prepared and added as a child to
this tree without further logic. this tree without further logic.
@ -120,7 +108,5 @@ class Node:
return data return data
def negate(self): def negate(self):
""" """Negate the sense of the root connector."""
Negate the sense of the root connector.
"""
self.negated = not self.negated self.negated = not self.negated

View File

@ -5,7 +5,7 @@ import subprocess
def get_version(version=None): def get_version(version=None):
"Returns a PEP 440-compliant version number from VERSION." """Return a PEP 440-compliant version number from VERSION."""
version = get_complete_version(version) version = get_complete_version(version)
# Now build the two parts of the version number: # Now build the two parts of the version number:
@ -29,15 +29,16 @@ def get_version(version=None):
def get_main_version(version=None): def get_main_version(version=None):
"Returns main version (X.Y[.Z]) from VERSION." """Return main version (X.Y[.Z]) from VERSION."""
version = get_complete_version(version) version = get_complete_version(version)
parts = 2 if version[2] == 0 else 3 parts = 2 if version[2] == 0 else 3
return '.'.join(str(x) for x in version[:parts]) return '.'.join(str(x) for x in version[:parts])
def get_complete_version(version=None): def get_complete_version(version=None):
"""Returns a tuple of the django version. If version argument is non-empty, """
then checks for correctness of the tuple provided. Return a tuple of the django version. If version argument is non-empty,
check for correctness of the tuple provided.
""" """
if version is None: if version is None:
from django import VERSION as version from django import VERSION as version
@ -58,7 +59,7 @@ def get_docs_version(version=None):
@functools.lru_cache() @functools.lru_cache()
def get_git_changeset(): def get_git_changeset():
"""Returns a numeric identifier of the latest git changeset. """Return a numeric identifier of the latest git changeset.
The result is the UTC timestamp of the changeset in YYYYMMDDHHMMSS format. The result is the UTC timestamp of the changeset in YYYYMMDDHHMMSS format.
This value isn't guaranteed to be unique, but collisions are very unlikely, This value isn't guaranteed to be unique, but collisions are very unlikely,