diff --git a/django/test/_doctest.py b/django/test/_doctest.py index 048d886720..c5b94c83a0 100644 --- a/django/test/_doctest.py +++ b/django/test/_doctest.py @@ -144,6 +144,8 @@ if sys.platform.startswith('java'): # Option constants. OPTIONFLAGS_BY_NAME = {} + + def register_optionflag(name): # Create a new flag unless `name` is already known. return OPTIONFLAGS_BY_NAME.setdefault(name, 1 << len(OPTIONFLAGS_BY_NAME)) @@ -194,6 +196,7 @@ ELLIPSIS_MARKER = '...' ## 1. Utility Functions ###################################################################### + def _extract_future_flags(globs): """ Return the compiler-flags associated with the future features that @@ -206,6 +209,7 @@ def _extract_future_flags(globs): flags |= feature.compiler_flag return flags + def _normalize_module(module, depth=2): """ Return the module specified by `module`. In particular: @@ -225,6 +229,7 @@ def _normalize_module(module, depth=2): else: raise TypeError("Expected a module, string, or None") + def _load_testfile(filename, package, module_relative): if module_relative: package = _normalize_module(package, 3) @@ -238,6 +243,7 @@ def _load_testfile(filename, package, module_relative): with open(filename) as fp: return fp.read(), filename + def _indent(s, indent=4): """ Add the given number of space characters to the beginning every @@ -246,6 +252,7 @@ def _indent(s, indent=4): # This regexp matches the start of non-blank lines: return re.sub('(?m)^(?!$)', indent*' ', s) + def _exception_traceback(exc_info): """ Return a string containing a traceback message for the given @@ -257,6 +264,7 @@ def _exception_traceback(exc_info): traceback.print_exception(exc_type, exc_val, exc_tb, file=excout) return excout.getvalue() + # Override some StringIO methods. class _SpoofOut(StringIO): def getvalue(self): @@ -277,6 +285,7 @@ class _SpoofOut(StringIO): if hasattr(self, "softspace"): del self.softspace + # Worst-case linear-time ellipsis matching. def _ellipsis_match(want, got): """ @@ -327,6 +336,7 @@ def _ellipsis_match(want, got): return True + def _comment_line(line): "Return a commented form of the given line" line = line.rstrip() @@ -335,6 +345,7 @@ def _comment_line(line): else: return '#' + class _OutputRedirectingPdb(pdb.Pdb): """ A specialized version of the python debugger that redirects stdout @@ -368,6 +379,7 @@ class _OutputRedirectingPdb(pdb.Pdb): finally: sys.stdout = save_stdout + # [XX] Normalize with respect to os.path.pardir? def _module_relative_path(module, path): if not inspect.ismodule(module): @@ -405,6 +417,7 @@ def _module_relative_path(module, path): ## a string (such as an object's docstring). The DocTest class also ## includes information about where the string was extracted from. + class Example: """ A single doctest example, consisting of source code and expected @@ -458,6 +471,7 @@ class Example: self.options = options self.exc_msg = exc_msg + class DocTest: """ A collection of doctest examples that should be run in a single @@ -506,10 +520,10 @@ class DocTest: return ('' % (self.name, self.filename, self.lineno, examples)) - # This lets us sort tests by name: def _cmpkey(self): return (self.name, self.filename, self.lineno, id(self)) + def __cmp__(self, other): if not isinstance(other, DocTest): return -1 @@ -1054,6 +1068,7 @@ class DocTestFinder: ## 5. DocTest Runner ###################################################################### + class DocTestRunner: """ A class used to run DocTest test cases, and accumulate statistics. @@ -1408,6 +1423,7 @@ class DocTestRunner: __LINECACHE_FILENAME_RE = re.compile(r'[\w\.]+)' r'\[(?P\d+)\]>$') + def __patched_linecache_getlines(self, filename, module_globals=None): m = self.__LINECACHE_FILENAME_RE.match(filename) if m and m.group('name') == self.test.name: @@ -1541,6 +1557,7 @@ class DocTestRunner: t = t + t2 d[name] = f, t + class OutputChecker: """ A class used to check the whether the actual output from a doctest @@ -1674,6 +1691,7 @@ class OutputChecker: else: return 'Expected nothing\nGot nothing\n' + class DocTestFailure(Exception): """A DocTest example has failed in debugging mode. @@ -1693,6 +1711,7 @@ class DocTestFailure(Exception): def __str__(self): return str(self.test) + class UnexpectedException(Exception): """A DocTest example has encountered an unexpected exception @@ -1712,6 +1731,7 @@ class UnexpectedException(Exception): def __str__(self): return str(self.test) + class DebugRunner(DocTestRunner): r"""Run doc tests but raise an exception as soon as there is a failure. @@ -1824,6 +1844,7 @@ class DebugRunner(DocTestRunner): # class, updated by testmod. master = None + def testmod(m=None, name=None, globs=None, verbose=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, exclude_empty=False): @@ -1928,6 +1949,7 @@ def testmod(m=None, name=None, globs=None, verbose=None, return runner.failures, runner.tries + def testfile(filename, module_relative=True, name=None, package=None, globs=None, verbose=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, parser=DocTestParser(), @@ -2051,6 +2073,7 @@ def testfile(filename, module_relative=True, name=None, package=None, return runner.failures, runner.tries + def run_docstring_examples(f, globs, verbose=False, name="NoName", compileflags=None, optionflags=0): """ @@ -2080,6 +2103,7 @@ def run_docstring_examples(f, globs, verbose=False, name="NoName", # This is provided only for backwards compatibility. It's not # actually used in any way. + class Tester: def __init__(self, mod=None, globs=None, verbose=None, optionflags=0): @@ -2145,6 +2169,7 @@ class Tester: _unittest_reportflags = 0 + def set_unittest_reportflags(flags): """Sets the unittest option flags. @@ -2328,6 +2353,7 @@ class DocTestCase(unittest.TestCase): def shortDescription(self): return "Doctest: " + self._dt_test.name + def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None, test_class=DocTestCase, **options): """ @@ -2391,6 +2417,7 @@ def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None, return suite + class DocFileCase(DocTestCase): def id(self): @@ -2405,6 +2432,7 @@ class DocFileCase(DocTestCase): % (self._dt_test.name, self._dt_test.filename, err) ) + def DocFileTest(path, module_relative=True, package=None, globs=None, parser=DocTestParser(), encoding=None, **options): @@ -2434,6 +2462,7 @@ def DocFileTest(path, module_relative=True, package=None, test = parser.get_doctest(doc, globs, name, path, 0) return DocFileCase(test, **options) + def DocFileSuite(*paths, **kw): """A unittest suite for one or more doctest files. @@ -2507,6 +2536,7 @@ def DocFileSuite(*paths, **kw): ## 9. Debugging Support ###################################################################### + def script_from_examples(s): r"""Extract script from text with examples. @@ -2587,6 +2617,7 @@ def script_from_examples(s): # Combine the output, and return it. return '\n'.join(output) + def testsource(module, name): """Extract the test sources from a doctest docstring as a script. @@ -2603,11 +2634,13 @@ def testsource(module, name): testsrc = script_from_examples(test.docstring) return testsrc + def debug_src(src, pm=False, globs=None): """Debug a single doctest docstring, in argument `src`'""" testsrc = script_from_examples(src) debug_script(testsrc, pm, globs) + def debug_script(src, pm=False, globs=None): "Debug a test script. `src` is the script, as a string." import pdb @@ -2639,6 +2672,7 @@ def debug_script(src, pm=False, globs=None): finally: os.remove(srcfilename) + def debug(module, name, pm=False): """Debug a single doctest docstring. @@ -2653,6 +2687,8 @@ def debug(module, name, pm=False): ###################################################################### ## 10. Example Usage ###################################################################### + + class _TestClass: """ A pointless class, for sanity-checking of docstring testing. @@ -2747,6 +2783,7 @@ __test__ = {"_TestClass": _TestClass, """, } + def _test(): r = unittest.TextTestRunner() r.run(DocTestSuite()) diff --git a/django/test/testcases.py b/django/test/testcases.py index 3fed8c6aa7..fa044ba6ec 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -61,9 +61,11 @@ real_enter_transaction_management = transaction.enter_transaction_management real_leave_transaction_management = transaction.leave_transaction_management real_abort = transaction.abort + def nop(*args, **kwargs): return + def disable_transaction_methods(): transaction.commit = nop transaction.rollback = nop @@ -71,6 +73,7 @@ def disable_transaction_methods(): transaction.leave_transaction_management = nop transaction.abort = nop + def restore_transaction_methods(): transaction.commit = real_commit transaction.rollback = real_rollback diff --git a/django/utils/_os.py b/django/utils/_os.py index 40a8e278fc..11fc5afe49 100644 --- a/django/utils/_os.py +++ b/django/utils/_os.py @@ -53,6 +53,7 @@ def npath(path): return path.encode(fs_encoding) return path + def safe_join(base, *paths): """ Joins one or more path components to the base path component intelligently. diff --git a/django/utils/autoreload.py b/django/utils/autoreload.py index ca162d18d0..00f7ce160a 100644 --- a/django/utils/autoreload.py +++ b/django/utils/autoreload.py @@ -119,6 +119,7 @@ def gen_filenames(): if os.path.exists(filename): yield filename + def inotify_code_changed(): """ Checks for changed code using inotify. After being called @@ -149,6 +150,7 @@ def inotify_code_changed(): # If we are here the code must have changed. return True + def kqueue_code_changed(): """ Checks for changed code using kqueue. After being called @@ -193,6 +195,7 @@ def kqueue_code_changed(): return True + def code_changed(): global _mtimes, _win for filename in gen_filenames(): @@ -212,6 +215,7 @@ def code_changed(): return True return False + def check_errors(fn): def wrapper(*args, **kwargs): try: @@ -233,6 +237,7 @@ def check_errors(fn): return wrapper + def ensure_echo_on(): if termios: fd = sys.stdin @@ -248,6 +253,7 @@ def ensure_echo_on(): if old_handler is not None: signal.signal(signal.SIGTTOU, old_handler) + def reloader_thread(): ensure_echo_on() if USE_INOTIFY: @@ -273,6 +279,7 @@ def restart_with_reloader(): if exit_code != 3: return exit_code + def python_reloader(main_func, args, kwargs): if os.environ.get("RUN_MAIN") == "true": thread.start_new_thread(main_func, args, kwargs) @@ -290,6 +297,7 @@ def python_reloader(main_func, args, kwargs): except KeyboardInterrupt: pass + def jython_reloader(main_func, args, kwargs): from _systemrestart import SystemRestart thread.start_new_thread(main_func, args) diff --git a/django/utils/cache.py b/django/utils/cache.py index 0d664afdf4..7e38f7b021 100644 --- a/django/utils/cache.py +++ b/django/utils/cache.py @@ -31,6 +31,7 @@ from django.utils.translation import get_language cc_delim_re = re.compile(r'\s*,\s*') + def patch_cache_control(response, **kwargs): """ This function patches the Cache-Control header by adding all @@ -79,6 +80,7 @@ def patch_cache_control(response, **kwargs): cc = ', '.join(dictvalue(el) for el in cc.items()) response['Cache-Control'] = cc + def get_max_age(response): """ Returns the max-age from the response Cache-Control header as an integer @@ -94,11 +96,13 @@ def get_max_age(response): except (ValueError, TypeError): pass + def _set_response_etag(response): if not response.streaming: response['ETag'] = '"%s"' % hashlib.md5(response.content).hexdigest() return response + def patch_response_headers(response, cache_timeout=None): """ Adds some useful headers to the given HttpResponse object: @@ -124,12 +128,14 @@ def patch_response_headers(response, cache_timeout=None): response['Expires'] = http_date(time.time() + cache_timeout) patch_cache_control(response, max_age=cache_timeout) + def add_never_cache_headers(response): """ Adds headers to a response to indicate that a page should never be cached. """ patch_response_headers(response, cache_timeout=-1) + def patch_vary_headers(response, newheaders): """ Adds (or updates) the "Vary" header in the given HttpResponse object. @@ -149,6 +155,7 @@ def patch_vary_headers(response, newheaders): if newheader.lower() not in existing_headers] response['Vary'] = ', '.join(vary_headers + additional_headers) + def has_vary_header(response, header_query): """ Checks to see if the response has a given header name in its Vary header. @@ -159,6 +166,7 @@ def has_vary_header(response, header_query): existing_headers = set(header.lower() for header in vary_headers) return header_query.lower() in existing_headers + def _i18n_cache_key_suffix(request, cache_key): """If necessary, adds the current locale or time zone to the cache key.""" if settings.USE_I18N or settings.USE_L10N: @@ -175,6 +183,7 @@ def _i18n_cache_key_suffix(request, cache_key): cache_key += '.%s' % tz_name.encode('ascii', 'ignore').decode('ascii').replace(' ', '_') return cache_key + def _generate_cache_key(request, method, headerlist, key_prefix): """Returns a cache key from the headers given in the header list.""" ctx = hashlib.md5() @@ -187,6 +196,7 @@ def _generate_cache_key(request, method, headerlist, key_prefix): key_prefix, method, path.hexdigest(), ctx.hexdigest()) return _i18n_cache_key_suffix(request, cache_key) + def _generate_cache_header_key(key_prefix, request): """Returns a cache key for the header cache.""" path = hashlib.md5(force_bytes(iri_to_uri(request.get_full_path()))) @@ -194,6 +204,7 @@ def _generate_cache_header_key(key_prefix, request): key_prefix, path.hexdigest()) return _i18n_cache_key_suffix(request, cache_key) + def get_cache_key(request, key_prefix=None, method='GET', cache=None): """ Returns a cache key based on the request path and query. It can be used @@ -215,6 +226,7 @@ def get_cache_key(request, key_prefix=None, method='GET', cache=None): else: return 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 path from the diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py index e5fe4a776a..49855dd33b 100644 --- a/django/utils/datastructures.py +++ b/django/utils/datastructures.py @@ -3,6 +3,7 @@ import warnings from collections import OrderedDict from django.utils import six + class MergeDict(object): """ A simple class for creating new "virtual" dictionaries that actually look @@ -117,6 +118,7 @@ class MergeDict(object): dictreprs = ', '.join(repr(d) for d in self.dicts) return '%s(%s)' % (self.__class__.__name__, dictreprs) + class SortedDict(dict): """ A dictionary that keeps its keys in the order in which they're inserted. @@ -239,6 +241,7 @@ class SortedDict(dict): super(SortedDict, self).clear() self.keyOrder = [] + class OrderedSet(object): """ A set which keeps the ordering of the inserted items. @@ -269,9 +272,11 @@ class OrderedSet(object): def __nonzero__(self): return bool(self.dict) + class MultiValueDictKeyError(KeyError): pass + class MultiValueDict(dict): """ A subclass of dictionary customized to handle multiple values for the @@ -504,6 +509,7 @@ class ImmutableList(tuple): sort = complain reverse = complain + class DictWrapper(dict): """ Wraps accesses to a dictionary so that certain values (those starting with diff --git a/django/utils/dateformat.py b/django/utils/dateformat.py index 27413a2e67..78483f2d4c 100644 --- a/django/utils/dateformat.py +++ b/django/utils/dateformat.py @@ -26,6 +26,7 @@ from django.utils.timezone import get_default_timezone, is_aware, is_naive re_formatchars = re.compile(r'(?= 1900: return super(type(dt), dt).strftime(fmt) diff --git a/django/utils/dictconfig.py b/django/utils/dictconfig.py index 773b703497..e79dc041ef 100644 --- a/django/utils/dictconfig.py +++ b/django/utils/dictconfig.py @@ -32,6 +32,7 @@ from django.utils import six IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) + def valid_ident(s): m = IDENTIFIER.match(s) if not m: @@ -65,6 +66,7 @@ except ImportError: # Each wrapper should have a configurator attribute holding the actual # configurator to use for conversion. + class ConvertingDict(dict): """A converting dictionary wrapper.""" @@ -102,6 +104,7 @@ class ConvertingDict(dict): result.key = key return result + class ConvertingList(list): """A converting list wrapper.""" def __getitem__(self, key): @@ -125,6 +128,7 @@ class ConvertingList(list): result.parent = self return result + class ConvertingTuple(tuple): """A converting tuple wrapper.""" def __getitem__(self, key): @@ -137,6 +141,7 @@ class ConvertingTuple(tuple): result.key = key return result + class BaseConfigurator(object): """ The configurator base class which defines some useful defaults. @@ -270,6 +275,7 @@ class BaseConfigurator(object): value = tuple(value) return value + class DictConfigurator(BaseConfigurator): """ Configure logging using a dictionary-like object to describe the @@ -555,6 +561,7 @@ class DictConfigurator(BaseConfigurator): dictConfigClass = DictConfigurator + def dictConfig(config): """Configure logging using a dictionary.""" dictConfigClass(config).configure() diff --git a/django/utils/encoding.py b/django/utils/encoding.py index ad4473df6a..ee67df30ea 100644 --- a/django/utils/encoding.py +++ b/django/utils/encoding.py @@ -38,6 +38,7 @@ def python_2_unicode_compatible(klass): klass.__str__ = lambda self: self.__unicode__().encode('utf-8') return klass + def smart_text(s, encoding='utf-8', strings_only=False, errors='strict'): """ Returns a text object representing 's' -- unicode on Python 2 and str on @@ -50,6 +51,7 @@ def smart_text(s, encoding='utf-8', strings_only=False, errors='strict'): return s return force_text(s, encoding, strings_only, errors) + def is_protected_type(obj): """Determine if the object instance is of a protected type. @@ -59,6 +61,7 @@ def is_protected_type(obj): return isinstance(obj, six.integer_types + (type(None), float, Decimal, datetime.datetime, datetime.date, datetime.time)) + def force_text(s, encoding='utf-8', strings_only=False, errors='strict'): """ Similar to smart_text, except that lazy instances are resolved to @@ -100,6 +103,7 @@ def force_text(s, encoding='utf-8', strings_only=False, errors='strict'): errors) for arg in s]) return s + def smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict'): """ Returns a bytestring version of 's', encoded as specified in 'encoding'. @@ -168,6 +172,7 @@ force_str.__doc__ = """ Apply force_text in Python 3 and force_bytes in Python 2. """ + def iri_to_uri(iri): """ Convert an Internationalized Resource Identifier (IRI) portion to a URI @@ -195,6 +200,7 @@ def iri_to_uri(iri): return iri return quote(force_bytes(iri), safe=b"/#%[]=:;$&()+,!?*@'~") + def filepath_to_uri(path): """Convert a file system path to a URI portion that is suitable for inclusion in a URL. @@ -214,6 +220,7 @@ def filepath_to_uri(path): # some flexibility for hardcoding separators. return quote(force_bytes(path).replace(b"\\", b"/"), safe=b"/~!*()'") + def get_system_encoding(): """ The encoding of the default system locale but falls back to the given diff --git a/django/utils/feedgenerator.py b/django/utils/feedgenerator.py index 416234521f..00d982025a 100644 --- a/django/utils/feedgenerator.py +++ b/django/utils/feedgenerator.py @@ -54,6 +54,7 @@ def rfc2822_date(date): else: return time_str + '-0000' + def rfc3339_date(date): # Support datetime objects older than 1900 date = datetime_safe.new_datetime(date) @@ -68,6 +69,7 @@ def rfc3339_date(date): else: return time_str + 'Z' + def get_tag_uri(url, date): """ Creates a TagURI. @@ -80,6 +82,7 @@ def get_tag_uri(url, date): d = ',%s' % datetime_safe.new_datetime(date).strftime('%Y-%m-%d') return 'tag:%s%s:%s/%s' % (bits.hostname, d, bits.path, bits.fragment) + class SyndicationFeed(object): "Base class for all syndication feeds. Subclasses should provide write()" def __init__(self, title, link, description, language=None, author_email=None, @@ -205,6 +208,7 @@ class SyndicationFeed(object): return latest_date or datetime.datetime.now() + class Enclosure(object): "Represents an RSS enclosure" def __init__(self, url, length, mime_type): @@ -212,6 +216,7 @@ class Enclosure(object): self.length, self.mime_type = length, mime_type self.url = iri_to_uri(url) + class RssFeed(SyndicationFeed): mime_type = 'application/rss+xml; charset=utf-8' @@ -255,6 +260,7 @@ class RssFeed(SyndicationFeed): def endChannelElement(self, handler): handler.endElement("channel") + class RssUserland091Feed(RssFeed): _version = "0.91" @@ -264,6 +270,7 @@ class RssUserland091Feed(RssFeed): if item['description'] is not None: handler.addQuickElement("description", item['description']) + class Rss201rev2Feed(RssFeed): # Spec: http://blogs.law.harvard.edu/tech/rss _version = "2.0" @@ -306,6 +313,7 @@ class Rss201rev2Feed(RssFeed): for cat in item['categories']: handler.addQuickElement("category", cat) + class Atom1Feed(SyndicationFeed): # Spec: http://atompub.org/2005/07/11/draft-ietf-atompub-format-10.html mime_type = 'application/atom+xml; charset=utf-8' diff --git a/django/utils/formats.py b/django/utils/formats.py index 0c59e2c04a..fc68179f3a 100644 --- a/django/utils/formats.py +++ b/django/utils/formats.py @@ -30,6 +30,7 @@ ISO_INPUT_FORMATS = { ), } + def reset_format_cache(): """Clear any cached formats. @@ -40,6 +41,7 @@ def reset_format_cache(): _format_cache = {} _format_modules_cache = {} + def iter_format_modules(lang, format_module_path=None): """ Does the heavy lifting of finding format modules. @@ -60,6 +62,7 @@ def iter_format_modules(lang, format_module_path=None): except ImportError: pass + def get_format_modules(lang=None, reverse=False): """ Returns a list of the format modules found @@ -71,6 +74,7 @@ def get_format_modules(lang=None, reverse=False): return list(reversed(modules)) return modules + def get_format(format_type, lang=None, use_l10n=None): """ For a specific format type, returns the format for the current @@ -110,6 +114,7 @@ def get_format(format_type, lang=None, use_l10n=None): get_format_lazy = lazy(get_format, six.text_type, list, tuple) + def date_format(value, format=None, use_l10n=None): """ Formats a datetime.date or datetime.datetime object using a @@ -120,6 +125,7 @@ def date_format(value, format=None, use_l10n=None): """ return dateformat.format(value, get_format(format or 'DATE_FORMAT', use_l10n=use_l10n)) + def time_format(value, format=None, use_l10n=None): """ Formats a datetime.time object using a localizable format @@ -129,6 +135,7 @@ def time_format(value, format=None, use_l10n=None): """ return dateformat.time_format(value, get_format(format or 'TIME_FORMAT', use_l10n=use_l10n)) + def number_format(value, decimal_pos=None, use_l10n=None, force_grouping=False): """ Formats a numeric value using localization settings @@ -149,6 +156,7 @@ def number_format(value, decimal_pos=None, use_l10n=None, force_grouping=False): force_grouping=force_grouping ) + def localize(value, use_l10n=None): """ Checks if value is a localizable type (date, number...) and returns it @@ -170,6 +178,7 @@ def localize(value, use_l10n=None): else: return value + def localize_input(value, default=None): """ Checks if an input value is a localizable type and returns it @@ -190,6 +199,7 @@ def localize_input(value, default=None): return value.strftime(format) return value + def sanitize_separators(value): """ Sanitizes a value according to the current decimal and diff --git a/django/utils/html.py b/django/utils/html.py index 6d04ae5205..3ad549de19 100644 --- a/django/utils/html.py +++ b/django/utils/html.py @@ -72,6 +72,7 @@ def conditional_escape(text): else: return escape(text) + def format_html(format_string, *args, **kwargs): """ Similar to str.format, but passes all arguments through conditional_escape, @@ -83,6 +84,7 @@ def format_html(format_string, *args, **kwargs): six.iteritems(kwargs)) return mark_safe(format_string.format(*args_safe, **kwargs_safe)) + def format_html_join(sep, format_string, args_generator): """ A wrapper of format_html, for the common case of a group of arguments that @@ -133,6 +135,7 @@ class MLStripper(HTMLParser): def get_data(self): return ''.join(self.fed) + def strip_tags(value): """Returns the given HTML with all tags stripped.""" s = MLStripper() @@ -145,6 +148,7 @@ def strip_tags(value): return s.get_data() strip_tags = allow_lazy(strip_tags) + def remove_tags(html, tags): """Returns the given HTML with given tags removed.""" tags = [re.escape(tag) for tag in tags.split()] @@ -156,21 +160,25 @@ def remove_tags(html, tags): return html remove_tags = allow_lazy(remove_tags, six.text_type) + def strip_spaces_between_tags(value): """Returns the given HTML with spaces between tags removed.""" return re.sub(r'>\s+<', '><', force_text(value)) strip_spaces_between_tags = allow_lazy(strip_spaces_between_tags, six.text_type) + def strip_entities(value): """Returns the given HTML with all entities (&something;) stripped.""" return re.sub(r'&(?:\w+|#\d+);', '', force_text(value)) strip_entities = allow_lazy(strip_entities, six.text_type) + def fix_ampersands(value): """Returns the given HTML with all unencoded ampersands encoded correctly.""" return unencoded_ampersands_re.sub('&', force_text(value)) fix_ampersands = allow_lazy(fix_ampersands, six.text_type) + def smart_urlquote(url): "Quotes a URL if it isn't already quoted." # Handle IDN before quoting. @@ -192,6 +200,7 @@ def smart_urlquote(url): return force_text(url) + def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False): """ Converts any URLs in text into clickable links. @@ -269,6 +278,7 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False): return ''.join(words) urlize = allow_lazy(urlize, six.text_type) + def clean_html(text): """ Clean the given HTML. Specifically, do the following: @@ -304,6 +314,7 @@ def clean_html(text): return text clean_html = allow_lazy(clean_html, six.text_type) + def avoid_wrapping(value): """ Avoid text wrapping in the middle of a phrase by adding non-breaking diff --git a/django/utils/http.py b/django/utils/http.py index 413ac72a08..e3365776f3 100644 --- a/django/utils/http.py +++ b/django/utils/http.py @@ -30,6 +30,7 @@ RFC1123_DATE = re.compile(r'^\w{3}, %s %s %s %s GMT$' % (__D, __M, __Y, __T)) RFC850_DATE = re.compile(r'^\w{6,9}, %s-%s-%s %s GMT$' % (__D, __M, __Y2, __T)) ASCTIME_DATE = re.compile(r'^\w{3} %s %s %s %s$' % (__M, __D2, __T, __Y)) + def urlquote(url, safe='/'): """ A version of Python's urllib.quote() function that can operate on unicode @@ -40,6 +41,7 @@ def urlquote(url, safe='/'): return force_text(quote(force_str(url), force_str(safe))) urlquote = allow_lazy(urlquote, six.text_type) + def urlquote_plus(url, safe=''): """ A version of Python's urllib.quote_plus() function that can operate on @@ -50,6 +52,7 @@ def urlquote_plus(url, safe=''): return force_text(quote_plus(force_str(url), force_str(safe))) urlquote_plus = allow_lazy(urlquote_plus, six.text_type) + def urlunquote(quoted_url): """ A wrapper for Python's urllib.unquote() function that can operate on @@ -58,6 +61,7 @@ def urlunquote(quoted_url): return force_text(unquote(force_str(quoted_url))) urlunquote = allow_lazy(urlunquote, six.text_type) + def urlunquote_plus(quoted_url): """ A wrapper for Python's urllib.unquote_plus() function that can operate on @@ -66,6 +70,7 @@ def urlunquote_plus(quoted_url): return force_text(unquote_plus(force_str(quoted_url))) urlunquote_plus = allow_lazy(urlunquote_plus, six.text_type) + def urlencode(query, doseq=0): """ A version of Python's urllib.urlencode() function that can operate on @@ -82,6 +87,7 @@ def urlencode(query, doseq=0): for k, v in query], doseq) + def cookie_date(epoch_seconds=None): """ Formats the time to ensure compatibility with Netscape's cookie standard. @@ -95,6 +101,7 @@ def cookie_date(epoch_seconds=None): rfcdate = formatdate(epoch_seconds) return '%s-%s-%s GMT' % (rfcdate[:7], rfcdate[8:11], rfcdate[12:25]) + def http_date(epoch_seconds=None): """ Formats the time to match the RFC1123 date format as specified by HTTP @@ -108,6 +115,7 @@ def http_date(epoch_seconds=None): """ return formatdate(epoch_seconds, usegmt=True) + def parse_http_date(date): """ Parses a date format as specified by HTTP RFC2616 section 3.3.1. @@ -143,6 +151,7 @@ def parse_http_date(date): except Exception: six.reraise(ValueError, ValueError("%r is not a valid date" % date), sys.exc_info()[2]) + def parse_http_date_safe(date): """ Same as parse_http_date, but returns None if the input is invalid. @@ -152,6 +161,7 @@ def parse_http_date_safe(date): except Exception: pass + # Base 36 functions: useful for generating compact URLs def base36_to_int(s): @@ -171,6 +181,7 @@ def base36_to_int(s): raise ValueError("Base36 input too large") return value + def int_to_base36(i): """ Converts an integer to a base36 string @@ -199,6 +210,7 @@ def int_to_base36(i): factor -= 1 return ''.join(base36) + def urlsafe_base64_encode(s): """ Encodes a bytestring in base64 for use in URLs, stripping any trailing @@ -206,6 +218,7 @@ def urlsafe_base64_encode(s): """ return base64.urlsafe_b64encode(s).rstrip(b'\n=') + def urlsafe_base64_decode(s): """ Decodes a base64 encoded string, adding back any trailing equal signs that @@ -217,6 +230,7 @@ def urlsafe_base64_decode(s): except (LookupError, BinasciiError) as e: raise ValueError(e) + def parse_etags(etag_str): """ Parses a string with one or several etags passed in If-None-Match and @@ -230,12 +244,14 @@ def parse_etags(etag_str): etags = [e.encode('ascii').decode('unicode_escape') for e in etags] return etags + def quote_etag(etag): """ Wraps a string in double quotes escaping contents as necessary. """ return '"%s"' % etag.replace('\\', '\\\\').replace('"', '\\"') + def same_origin(url1, url2): """ Checks if two URLs are 'same-origin' @@ -246,6 +262,7 @@ def same_origin(url1, url2): except ValueError: return False + def is_safe_url(url, host=None): """ Return ``True`` if the url is a safe redirection (i.e. it doesn't point to diff --git a/django/utils/regex_helper.py b/django/utils/regex_helper.py index c8390cc7eb..199b4ea87d 100644 --- a/django/utils/regex_helper.py +++ b/django/utils/regex_helper.py @@ -202,6 +202,7 @@ def normalize(pattern): return list(zip(*flatten_result(result))) + def next_char(input_iter): """ An iterator that yields the next character from "pattern_iter", respecting @@ -222,6 +223,7 @@ def next_char(input_iter): continue yield representative, True + def walk_to_end(ch, input_iter): """ The iterator is currently inside a capturing group. We want to walk to the @@ -242,6 +244,7 @@ def walk_to_end(ch, input_iter): return nesting -= 1 + def get_quantifier(ch, input_iter): """ Parse a quantifier from the input, where "ch" is the first character in the @@ -278,6 +281,7 @@ def get_quantifier(ch, input_iter): ch = None return int(values[0]), ch + def contains(source, inst): """ Returns True if the "source" contains an instance of "inst". False, @@ -291,6 +295,7 @@ def contains(source, inst): return True return False + def flatten_result(source): """ Turns the given source sequence into a list of reg-exp possibilities and diff --git a/django/utils/safestring.py b/django/utils/safestring.py index c44726090f..097d31dd0f 100644 --- a/django/utils/safestring.py +++ b/django/utils/safestring.py @@ -32,6 +32,7 @@ else: # backwards compatibility for Python 2 EscapeUnicode = EscapeText + class SafeData(object): def __html__(self): """ @@ -41,6 +42,7 @@ class SafeData(object): """ return self + class SafeBytes(bytes, SafeData): """ A bytes subclass that has been specifically marked as "safe" (requires no @@ -75,6 +77,7 @@ class SafeBytes(bytes, SafeData): decode = curry(_proxy_method, method=bytes.decode) + class SafeText(six.text_type, SafeData): """ A unicode (Python 2) / str (Python 3) subclass that has been specifically @@ -114,6 +117,7 @@ else: # backwards compatibility for Python 2 SafeUnicode = SafeText + def mark_safe(s): """ Explicitly mark a string as safe for (HTML) output purposes. The returned @@ -129,6 +133,7 @@ def mark_safe(s): return SafeText(s) return SafeString(str(s)) + def mark_for_escaping(s): """ Explicitly mark a string as requiring HTML escaping upon output. Has no diff --git a/django/utils/six.py b/django/utils/six.py index 7abefb2258..b9d311499b 100644 --- a/django/utils/six.py +++ b/django/utils/six.py @@ -428,14 +428,17 @@ def iterkeys(d, **kw): """Return an iterator over the keys of a dictionary.""" return iter(getattr(d, _iterkeys)(**kw)) + def itervalues(d, **kw): """Return an iterator over the values of a dictionary.""" return iter(getattr(d, _itervalues)(**kw)) + def iteritems(d, **kw): """Return an iterator over the (key, value) pairs of a dictionary.""" return iter(getattr(d, _iteritems)(**kw)) + def iterlists(d, **kw): """Return an iterator over the (key, [values]) pairs of a dictionary.""" return iter(getattr(d, _iterlists)(**kw)) @@ -565,6 +568,7 @@ def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" return meta("NewBase", bases, {}) + def add_metaclass(metaclass): """Class decorator for creating a class with a metaclass.""" def wrapper(cls): diff --git a/django/utils/text.py b/django/utils/text.py index 8f20e8ed88..bb05afefc4 100644 --- a/django/utils/text.py +++ b/django/utils/text.py @@ -209,6 +209,7 @@ class Truncator(SimpleLazyObject): # Return string return out + def get_valid_filename(s): """ Returns the given string converted to a string that can be used for a clean @@ -222,6 +223,7 @@ def get_valid_filename(s): return re.sub(r'(?u)[^-\w.]', '', s) get_valid_filename = allow_lazy(get_valid_filename, six.text_type) + def get_text_list(list_, last_word=ugettext_lazy('or')): """ >>> get_text_list(['a', 'b', 'c', 'd']) @@ -245,10 +247,12 @@ def get_text_list(list_, last_word=ugettext_lazy('or')): force_text(last_word), force_text(list_[-1])) get_text_list = allow_lazy(get_text_list, six.text_type) + def normalize_newlines(text): return force_text(re.sub(r'\r\n|\r|\n', '\n', text)) normalize_newlines = allow_lazy(normalize_newlines, six.text_type) + def recapitalize(text): "Recapitalizes text, placing caps after end-of-sentence punctuation." text = force_text(text).lower() @@ -257,6 +261,7 @@ def recapitalize(text): return text recapitalize = allow_lazy(recapitalize) + def phone2numeric(phone): "Converts a phone number with letters into its numeric equivalent." char2number = {'a': '2', 'b': '2', 'c': '2', 'd': '3', 'e': '3', 'f': '3', @@ -267,6 +272,7 @@ def phone2numeric(phone): return ''.join(char2number.get(c, c) for c in phone.lower()) phone2numeric = allow_lazy(phone2numeric) + # From http://www.xhaus.com/alan/python/httpcomp.html#gzip # Used with permission. def compress_string(s): @@ -276,6 +282,7 @@ def compress_string(s): zfile.close() return zbuf.getvalue() + class StreamingBuffer(object): def __init__(self): self.vals = [] @@ -294,6 +301,7 @@ class StreamingBuffer(object): def close(self): return + # Like compress_string, but for iterators of strings. def compress_sequence(sequence): buf = StreamingBuffer() @@ -309,6 +317,7 @@ def compress_sequence(sequence): ustring_re = re.compile("([\u0080-\uffff])") + def javascript_quote(s, quote_double_quotes=False): def fix(match): @@ -340,6 +349,7 @@ smart_split_re = re.compile(r""" ) | \S+) """, re.VERBOSE) + def smart_split(text): r""" Generator that splits a string by spaces, leaving quoted phrases together. @@ -359,6 +369,7 @@ def smart_split(text): for bit in smart_split_re.finditer(text): yield bit.group(0) + def _replace_entity(match): text = match.group(1) if text[0] == '#': @@ -379,10 +390,12 @@ def _replace_entity(match): _entity_re = re.compile(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));") + def unescape_entities(text): return _entity_re.sub(_replace_entity, text) unescape_entities = allow_lazy(unescape_entities, six.text_type) + def unescape_string_literal(s): r""" Convert quoted string literals to unquoted strings with escaped quotes and @@ -403,6 +416,7 @@ def unescape_string_literal(s): return s[1:-1].replace(r'\%s' % quote, quote).replace(r'\\', '\\') unescape_string_literal = allow_lazy(unescape_string_literal) + def slugify(value): """ Converts to lowercase, removes non-word characters (alphanumerics and diff --git a/django/utils/timesince.py b/django/utils/timesince.py index 8fb0f64e09..b39ab203a7 100644 --- a/django/utils/timesince.py +++ b/django/utils/timesince.py @@ -6,6 +6,7 @@ from django.utils.html import avoid_wrapping from django.utils.timezone import is_aware, utc from django.utils.translation import ugettext, ungettext_lazy + def timesince(d, now=None, reversed=False): """ Takes two datetime objects and returns the time between d and now @@ -56,6 +57,7 @@ def timesince(d, now=None, reversed=False): result += ugettext(', ') + avoid_wrapping(name2 % count2) return result + def timeuntil(d, now=None): """ Like timesince, but returns a string measuring the time until diff --git a/django/utils/timezone.py b/django/utils/timezone.py index 951c3efcf9..eec554a1ef 100644 --- a/django/utils/timezone.py +++ b/django/utils/timezone.py @@ -29,6 +29,7 @@ __all__ = [ ZERO = timedelta(0) + class UTC(tzinfo): """ UTC implementation taken from Python's docs. @@ -48,6 +49,7 @@ class UTC(tzinfo): def dst(self, dt): return ZERO + class FixedOffset(tzinfo): """ Fixed offset in minutes east from UTC. Taken from Python's docs. @@ -72,6 +74,7 @@ class FixedOffset(tzinfo): def dst(self, dt): return ZERO + class ReferenceLocalTimezone(tzinfo): """ Local time. Taken from Python's docs. @@ -118,6 +121,7 @@ class ReferenceLocalTimezone(tzinfo): tt = _time.localtime(stamp) return tt.tm_isdst > 0 + class LocalTimezone(ReferenceLocalTimezone): """ Slightly improved local time implementation focusing on correctness. @@ -143,6 +147,7 @@ class LocalTimezone(ReferenceLocalTimezone): utc = pytz.utc if pytz else UTC() """UTC time zone as a tzinfo instance.""" + def get_fixed_timezone(offset): """ Returns a tzinfo instance with a fixed offset from UTC. @@ -158,6 +163,7 @@ def get_fixed_timezone(offset): # wrap the expression in a function and cache the result. _localtime = None + def get_default_timezone(): """ Returns the default time zone as a tzinfo instance. @@ -173,6 +179,7 @@ def get_default_timezone(): _localtime = LocalTimezone() return _localtime + # This function exists for consistency with get_current_timezone_name def get_default_timezone_name(): """ @@ -182,18 +189,21 @@ def get_default_timezone_name(): _active = local() + def get_current_timezone(): """ Returns the currently active time zone as a tzinfo instance. """ return getattr(_active, "value", get_default_timezone()) + def get_current_timezone_name(): """ Returns the name of the currently active time zone. """ return _get_timezone_name(get_current_timezone()) + def _get_timezone_name(timezone): """ Returns the name of ``timezone``. @@ -210,6 +220,7 @@ def _get_timezone_name(timezone): # These functions don't change os.environ['TZ'] and call time.tzset() # because it isn't thread safe. + def activate(timezone): """ Sets the time zone for the current thread. @@ -224,6 +235,7 @@ def activate(timezone): else: raise ValueError("Invalid timezone: %r" % timezone) + def deactivate(): """ Unsets the time zone for the current thread. @@ -233,6 +245,7 @@ def deactivate(): if hasattr(_active, "value"): del _active.value + class override(object): """ Temporarily set the time zone for the current thread. @@ -297,6 +310,7 @@ def localtime(value, timezone=None): value = timezone.normalize(value) return value + def now(): """ Returns an aware or naive datetime.datetime, depending on settings.USE_TZ. @@ -307,6 +321,7 @@ def now(): else: return datetime.now() + # By design, these four functions don't perform any checks on their arguments. # The caller should ensure that they don't receive an invalid value like None. @@ -319,6 +334,7 @@ def is_aware(value): """ return value.tzinfo is not None and value.tzinfo.utcoffset(value) is not None + def is_naive(value): """ Determines if a given datetime.datetime is naive. @@ -328,6 +344,7 @@ def is_naive(value): """ return value.tzinfo is None or value.tzinfo.utcoffset(value) is None + def make_aware(value, timezone): """ Makes a naive datetime.datetime in a given time zone aware. @@ -339,6 +356,7 @@ def make_aware(value, timezone): # may be wrong around DST changes return value.replace(tzinfo=timezone) + def make_naive(value, timezone): """ Makes an aware datetime.datetime naive in a given time zone. diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py index d99c8bbd78..e4e8c6e1be 100644 --- a/django/utils/translation/__init__.py +++ b/django/utils/translation/__init__.py @@ -61,26 +61,33 @@ _trans = Trans() # The Trans class is no more needed, so remove it from the namespace. del Trans + def gettext_noop(message): return _trans.gettext_noop(message) ugettext_noop = gettext_noop + def gettext(message): return _trans.gettext(message) + def ngettext(singular, plural, number): return _trans.ngettext(singular, plural, number) + def ugettext(message): return _trans.ugettext(message) + def ungettext(singular, plural, number): return _trans.ungettext(singular, plural, number) + def pgettext(context, message): return _trans.pgettext(context, message) + def npgettext(context, singular, plural, number): return _trans.npgettext(context, singular, plural, number) @@ -88,6 +95,7 @@ gettext_lazy = lazy(gettext, str) ugettext_lazy = lazy(ugettext, six.text_type) pgettext_lazy = lazy(pgettext, six.text_type) + def lazy_number(func, resultclass, number=None, **kwargs): if isinstance(number, int): kwargs['number'] = number @@ -117,21 +125,27 @@ def lazy_number(func, resultclass, number=None, **kwargs): proxy = lazy(lambda **kwargs: NumberAwareString(), NumberAwareString)(**kwargs) return proxy + def ngettext_lazy(singular, plural, number=None): return lazy_number(ngettext, str, singular=singular, plural=plural, number=number) + def ungettext_lazy(singular, plural, number=None): return lazy_number(ungettext, six.text_type, singular=singular, plural=plural, number=number) + def npgettext_lazy(context, singular, plural, number=None): return lazy_number(npgettext, six.text_type, context=context, singular=singular, plural=plural, number=number) + def activate(language): return _trans.activate(language) + def deactivate(): return _trans.deactivate() + class override(object): def __init__(self, language, deactivate=False): self.language = language @@ -150,30 +164,39 @@ class override(object): else: activate(self.old_language) + def get_language(): return _trans.get_language() + def get_language_bidi(): return _trans.get_language_bidi() + def check_for_language(lang_code): return _trans.check_for_language(lang_code) + def to_locale(language): return _trans.to_locale(language) + def get_language_from_request(request, check_path=False): return _trans.get_language_from_request(request, check_path) + def get_language_from_path(path, supported=None): return _trans.get_language_from_path(path, supported=supported) + def templatize(src, origin=None): return _trans.templatize(src, origin) + def deactivate_all(): return _trans.deactivate_all() + def _string_concat(*strings): """ Lazy variant of string concatenation, needed for translations that are @@ -182,6 +205,7 @@ def _string_concat(*strings): return ''.join(force_text(s) for s in strings) string_concat = lazy(_string_concat, six.text_type) + def get_language_info(lang_code): from django.conf.locale import LANG_INFO try: diff --git a/django/utils/translation/trans_null.py b/django/utils/translation/trans_null.py index 88c77a5110..9e3beb0f7d 100644 --- a/django/utils/translation/trans_null.py +++ b/django/utils/translation/trans_null.py @@ -6,18 +6,22 @@ from django.conf import settings from django.utils.encoding import force_text from django.utils.safestring import mark_safe, SafeData + def ngettext(singular, plural, number): if number == 1: return singular return plural ngettext_lazy = ngettext + def ungettext(singular, plural, number): return force_text(ngettext(singular, plural, number)) + def pgettext(context, message): return ugettext(message) + def npgettext(context, singular, plural, number): return ungettext(singular, plural, number) @@ -38,17 +42,20 @@ TECHNICAL_ID_MAP = { "MONTH_DAY_FORMAT": settings.MONTH_DAY_FORMAT, } + def gettext(message): result = TECHNICAL_ID_MAP.get(message, message) if isinstance(message, SafeData): return mark_safe(result) return result + def ugettext(message): return force_text(gettext(message)) gettext_noop = gettext_lazy = _ = gettext + def to_locale(language): p = language.find('-') if p >= 0: @@ -56,8 +63,10 @@ def to_locale(language): else: return language.lower() + def get_language_from_request(request, check_path=False): return settings.LANGUAGE_CODE + def get_language_from_path(request, supported=None): return None diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index b79af80dd1..d78b6d6412 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -64,6 +64,7 @@ def to_locale(language, to_lower=False): else: return language.lower() + def to_language(locale): """Turns a locale name (en_US) into a language name (en-us).""" p = locale.find('_') @@ -72,6 +73,7 @@ def to_language(locale): else: return locale.lower() + class DjangoTranslation(gettext_module.GNUTranslations): """ This class sets up the GNUTranslations context with regard to output @@ -98,6 +100,7 @@ class DjangoTranslation(gettext_module.GNUTranslations): def __repr__(self): return "" % self.__language + def translation(language): """ Returns a translation object. @@ -179,6 +182,7 @@ def translation(language): return current_translation + def activate(language): """ Fetches the translation object for a given tuple of application name and @@ -187,6 +191,7 @@ def activate(language): """ _active.value = translation(language) + def deactivate(): """ Deinstalls the currently active translation object so that further _ calls @@ -195,6 +200,7 @@ def deactivate(): if hasattr(_active, "value"): del _active.value + def deactivate_all(): """ Makes the active translation object a NullTranslations() instance. This is @@ -203,6 +209,7 @@ def deactivate_all(): """ _active.value = gettext_module.NullTranslations() + def get_language(): """Returns the currently selected language.""" t = getattr(_active, "value", None) @@ -215,6 +222,7 @@ def get_language(): from django.conf import settings return settings.LANGUAGE_CODE + def get_language_bidi(): """ Returns selected language's BiDi layout. @@ -227,6 +235,7 @@ def get_language_bidi(): base_lang = get_language().split('-')[0] return base_lang in settings.LANGUAGES_BIDI + def catalog(): """ Returns the current active catalog for further processing. @@ -243,6 +252,7 @@ def catalog(): _default = translation(settings.LANGUAGE_CODE) return _default + def do_translate(message, translation_function): """ Translates 'message' using the given 'translation_function' name -- which @@ -266,6 +276,7 @@ def do_translate(message, translation_function): return mark_safe(result) return result + def gettext(message): """ Returns a string of the translation of the message. @@ -280,6 +291,7 @@ else: def ugettext(message): return do_translate(message, 'ugettext') + def pgettext(context, message): msg_with_ctxt = "%s%s%s" % (context, CONTEXT_SEPARATOR, message) result = ugettext(msg_with_ctxt) @@ -288,6 +300,7 @@ def pgettext(context, message): result = message return result + def gettext_noop(message): """ Marks strings for translation but doesn't translate them now. This can be @@ -297,6 +310,7 @@ def gettext_noop(message): """ return message + def do_ntranslate(singular, plural, number, translation_function): global _default @@ -308,6 +322,7 @@ def do_ntranslate(singular, plural, number, translation_function): _default = translation(settings.LANGUAGE_CODE) return getattr(_default, translation_function)(singular, plural, number) + def ngettext(singular, plural, number): """ Returns a string of the translation of either the singular or plural, @@ -327,6 +342,7 @@ else: """ return do_ntranslate(singular, plural, number, 'ungettext') + def npgettext(context, singular, plural, number): msgs_with_ctxt = ("%s%s%s" % (context, CONTEXT_SEPARATOR, singular), "%s%s%s" % (context, CONTEXT_SEPARATOR, plural), @@ -337,6 +353,7 @@ def npgettext(context, singular, plural, number): result = ungettext(singular, plural, number) return result + def all_locale_paths(): """ Returns a list of paths to user-provides languages files. @@ -346,6 +363,7 @@ def all_locale_paths(): os.path.dirname(upath(sys.modules[settings.__module__].__file__)), 'locale') return [globalpath] + list(settings.LOCALE_PATHS) + def check_for_language(lang_code): """ Checks whether there is a global language file for the given language @@ -359,6 +377,7 @@ def check_for_language(lang_code): return False check_for_language = memoize(check_for_language, _checked_languages, 1) + def get_supported_language_variant(lang_code, supported=None, strict=False): """ Returns the language-code that's listed in supported languages, possibly @@ -386,6 +405,7 @@ def get_supported_language_variant(lang_code, supported=None, strict=False): return supported_code raise LookupError(lang_code) + def get_language_from_path(path, supported=None, strict=False): """ Returns the language-code if there is a valid language-code @@ -406,6 +426,7 @@ def get_language_from_path(path, supported=None, strict=False): except LookupError: return None + def get_language_from_request(request, check_path=False): """ Analyzes the request to find what language the user wants the system to @@ -470,6 +491,8 @@ def get_language_from_request(request, check_path=False): return settings.LANGUAGE_CODE dot_re = re.compile(r'\S') + + def blankout(src, char): """ Changes every non-whitespace character to the given char. @@ -653,6 +676,7 @@ def templatize(src, origin=None): out.write(blankout(t.contents, 'X')) return force_str(out.getvalue()) + def parse_accept_lang_header(lang_string): """ Parses the lang_string, which is the body of an HTTP Accept-Language diff --git a/django/views/debug.py b/django/views/debug.py index 2829ca1443..0ee5d588c7 100644 --- a/django/views/debug.py +++ b/django/views/debug.py @@ -21,6 +21,7 @@ HIDDEN_SETTINGS = re.compile('API|TOKEN|KEY|SECRET|PASS|PROFANITIES_LIST|SIGNATU CLEANSED_SUBSTITUTE = '********************' + def linebreak_iter(template_source): yield 0 p = template_source.find('\n') @@ -29,6 +30,7 @@ def linebreak_iter(template_source): p = template_source.find('\n', p+1) yield len(template_source) + 1 + def cleanse_setting(key, value): """Cleanse an individual setting key/value of sensitive content. @@ -52,6 +54,7 @@ def cleanse_setting(key, value): return cleansed + def get_safe_settings(): "Returns a dictionary of the settings module, with sensitive settings blurred out." settings_dict = {} @@ -60,6 +63,7 @@ def get_safe_settings(): settings_dict[k] = cleanse_setting(k, getattr(settings, k)) return settings_dict + def technical_500_response(request, exc_type, exc_value, tb): """ Create a technical server error response. The last three arguments are @@ -76,6 +80,7 @@ def technical_500_response(request, exc_type, exc_value, tb): # Cache for the default exception reporter filter instance. default_exception_reporter_filter = None + def get_exception_reporter_filter(request): global default_exception_reporter_filter if default_exception_reporter_filter is None: @@ -87,6 +92,7 @@ def get_exception_reporter_filter(request): else: return default_exception_reporter_filter + class ExceptionReporterFilter(object): """ Base for all exception reporter filter classes. All overridable hooks @@ -108,6 +114,7 @@ class ExceptionReporterFilter(object): def get_traceback_frame_variables(self, request, tb_frame): return list(six.iteritems(tb_frame.f_locals)) + class SafeExceptionReporterFilter(ExceptionReporterFilter): """ Use annotations made by the sensitive_post_parameters and @@ -221,6 +228,7 @@ class SafeExceptionReporterFilter(ExceptionReporterFilter): return cleansed.items() + class ExceptionReporter(object): """ A class to organize and coordinate reporting on exceptions. @@ -491,6 +499,7 @@ def technical_404_response(request, exception): }) return HttpResponseNotFound(t.render(c), content_type='text/html') + def default_urlconf(request): "Create an empty URLconf 404 error response." t = Template(DEFAULT_URLCONF_TEMPLATE, name='Default URLconf template') diff --git a/django/views/decorators/http.py b/django/views/decorators/http.py index a0da002dc9..df4e165066 100644 --- a/django/views/decorators/http.py +++ b/django/views/decorators/http.py @@ -51,6 +51,7 @@ require_POST.__doc__ = "Decorator to require that a view only accept the POST me require_safe = require_http_methods(["GET", "HEAD"]) require_safe.__doc__ = "Decorator to require that a view only accept safe methods: GET and HEAD." + def condition(etag_func=None, last_modified_func=None): """ Decorator to support conditional retrieval (or change) for a view @@ -157,9 +158,11 @@ def condition(etag_func=None, last_modified_func=None): return inner return decorator + # Shortcut decorators for common cases based on ETag or Last-Modified only def etag(etag_func): return condition(etag_func=etag_func) + def last_modified(last_modified_func): return condition(last_modified_func=last_modified_func) diff --git a/django/views/decorators/vary.py b/django/views/decorators/vary.py index cd2f9c0f55..056669278b 100644 --- a/django/views/decorators/vary.py +++ b/django/views/decorators/vary.py @@ -2,6 +2,7 @@ from functools import wraps from django.utils.cache import patch_vary_headers from django.utils.decorators import available_attrs + def vary_on_headers(*headers): """ A view decorator that adds the specified headers to the Vary header of the @@ -22,6 +23,7 @@ def vary_on_headers(*headers): return inner_func return decorator + def vary_on_cookie(func): """ A view decorator that adds "Cookie" to the Vary header of a response. This diff --git a/django/views/generic/dates.py b/django/views/generic/dates.py index 370cb32ce7..d221c2c087 100644 --- a/django/views/generic/dates.py +++ b/django/views/generic/dates.py @@ -13,6 +13,7 @@ from django.views.generic.base import View from django.views.generic.detail import BaseDetailView, SingleObjectTemplateResponseMixin from django.views.generic.list import MultipleObjectMixin, MultipleObjectTemplateResponseMixin + class YearMixin(object): """ Mixin for views manipulating year-based data. diff --git a/django/views/i18n.py b/django/views/i18n.py index 9ede1ed49f..751905efaf 100644 --- a/django/views/i18n.py +++ b/django/views/i18n.py @@ -13,6 +13,7 @@ from django.utils._os import upath from django.utils.http import is_safe_url from django.utils import six + def set_language(request): """ Redirect to a given url while setting the chosen language in the diff --git a/django/views/static.py b/django/views/static.py index e55f6a1234..11c8734eec 100644 --- a/django/views/static.py +++ b/django/views/static.py @@ -17,6 +17,7 @@ from django.utils.http import http_date, parse_http_date from django.utils.six.moves.urllib.parse import unquote from django.utils.translation import ugettext as _, ugettext_noop + def serve(request, path, document_root=None, show_indexes=False): """ Serve static files below a given point in the directory structure. @@ -95,6 +96,7 @@ DEFAULT_DIRECTORY_INDEX_TEMPLATE = """ """ template_translatable = ugettext_noop("Index of %(directory)s") + def directory_index(path, fullpath): try: t = loader.select_template(['static/directory_index.html', @@ -113,6 +115,7 @@ def directory_index(path, fullpath): }) return HttpResponse(t.render(c)) + def was_modified_since(header=None, mtime=0, size=0): """ Was something modified since the user last downloaded it?