diff -Nru configparser-3.3.0r2/configparser.egg-info/dependency_links.txt configparser-3.5.0/configparser.egg-info/dependency_links.txt --- configparser-3.3.0r2/configparser.egg-info/dependency_links.txt 2013-01-02 00:58:18.000000000 +0000 +++ configparser-3.5.0/configparser.egg-info/dependency_links.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - diff -Nru configparser-3.3.0r2/configparser.egg-info/PKG-INFO configparser-3.5.0/configparser.egg-info/PKG-INFO --- configparser-3.3.0r2/configparser.egg-info/PKG-INFO 2013-01-02 00:58:18.000000000 +0000 +++ configparser-3.5.0/configparser.egg-info/PKG-INFO 1970-01-01 00:00:00.000000000 +0000 @@ -1,298 +0,0 @@ -Metadata-Version: 1.0 -Name: configparser -Version: 3.3.0r2 -Summary: This library brings the updated configparser from Python 3.2+ to Python 2.6-2.7. -Home-page: http://docs.python.org/3/library/configparser.html -Author: Łukasz Langa -Author-email: lukasz@langa.pl -License: MIT -Description: ============ - configparser - ============ - - The ancient ``ConfigParser`` module available in the standard library 2.x has - seen a major update in Python 3.2. This is a backport of those changes so that - they can be used directly in Python 2.6 - 2.7. - - To use ``configparser`` instead of ``ConfigParser``, simply replace:: - - import ConfigParser - - with:: - - import configparser - - For detailed documentation consult the vanilla version at - http://docs.python.org/3/library/configparser.html. - - Why you'll love ``configparser`` - -------------------------------- - - Whereas almost completely compatible with its older brother, ``configparser`` - sports a bunch of interesting new features: - - * full mapping protocol access (`more info - `_):: - - >>> parser = ConfigParser() - >>> parser.read_string(""" - [DEFAULT] - location = upper left - visible = yes - editable = no - color = blue - - [main] - title = Main Menu - color = green - - [options] - title = Options - """) - >>> parser['main']['color'] - 'green' - >>> parser['main']['editable'] - 'no' - >>> section = parser['options'] - >>> section['title'] - 'Options' - >>> section['title'] = 'Options (editable: %(editable)s)' - >>> section['title'] - 'Options (editable: no)' - - * there's now one default ``ConfigParser`` class, which basically is the old - ``SafeConfigParser`` with a bunch of tweaks which make it more predictable for - users. Don't need interpolation? Simply use - ``ConfigParser(interpolation=None)``, no need to use a distinct - ``RawConfigParser`` anymore. - - * the parser is highly `customizable upon instantiation - `__ - supporting things like changing option delimiters, comment characters, the - name of the DEFAULT section, the interpolation syntax, etc. - - * you can easily create your own interpolation syntax but there are two powerful - implementations built-in (`more info - `__): - - * the classic ``%(string-like)s`` syntax (called ``BasicInterpolation``) - - * a new ``${buildout:like}`` syntax (called ``ExtendedInterpolation``) - - * fallback values may be specified in getters (`more info - `__):: - - >>> config.get('closet', 'monster', - ... fallback='No such things as monsters') - 'No such things as monsters' - - * ``ConfigParser`` objects can now read data directly `from strings - `__ - and `from dictionaries - `__. - That means importing configuration from JSON or specifying default values for - the whole configuration (multiple sections) is now a single line of code. Same - goes for copying data from another ``ConfigParser`` instance, thanks to its - mapping protocol support. - - * many smaller tweaks, updates and fixes - - A few words about Unicode - ------------------------- - - ``configparser`` comes from Python 3 and as such it works well with Unicode. - The library is generally cleaned up in terms of internal data storage and - reading/writing files. There are a couple of incompatibilities with the old - ``ConfigParser`` due to that. However, the work required to migrate is well - worth it as it shows the issues that would likely come up during migration of - your project to Python 3. - - The design assumes that Unicode strings are used whenever possible [1]_. That - gives you the certainty that what's stored in a configuration object is text. - Once your configuration is read, the rest of your application doesn't have to - deal with encoding issues. All you have is text [2]_. The only two phases when - you should explicitly state encoding is when you either read from an external - source (e.g. a file) or write back. - - Versioning - ---------- - - This backport is intended to keep 100% compatibility with the vanilla release in - Python 3.2+. To help maintaining a version you want and expect, a versioning - scheme is used where: - - * the first three numbers indicate the version of Python 3.x from which the - backport is done - - * a backport release number is provided after the ``r`` letter - - For example, ``3.3.0r1`` is the **first** release of ``configparser`` compatible - with the library found in Python **3.3.0**. - - A single exception from the 100% compatibility principle is that bugs fixed - before releasing another minor Python 3.x.y version **will be included** in the - backport releases done in the mean time. This rule applies to bugs only. - - Maintenance - ----------- - - This backport is maintained on BitBucket by Łukasz Langa, the current vanilla - ``configparser`` maintainer for CPython: - - * `configparser Mercurial repository `_ - - * `configparser issue tracker `_ - - Change Log - ---------- - - 3.3.0r2 - ~~~~~~~ - - * updated the fix for `#16820 `_: parsers - now preserve section order when using ``__setitem__`` and ``update`` - - 3.3.0r1 - ~~~~~~~ - - * compatible with 3.3.0 + fixes for `#15803 - `_ and `#16820 - `_ - - * fixes `BitBucket issue #4 - `_: ``read()`` properly - treats a bytestring argument as a filename - - * `ordereddict `_ dependency required - only for Python 2.6 - - * `unittest2 `_ explicit dependency - dropped. If you want to test the release, add ``unittest2`` on your own. - - 3.2.0r3 - ~~~~~~~ - - * proper Python 2.6 support - - * explicitly stated the dependency on `ordereddict - `_ - - * numbered all formatting braces in strings - - * explicitly says that Python 2.5 support won't happen (too much work necessary - without abstract base classes, string formatters, the ``io`` library, etc.) - - * some healthy advertising in the README - - 3.2.0r2 - ~~~~~~~ - - * a backport-specific change: for convenience and basic compatibility with the - old ConfigParser, bytestrings are now accepted as section names, options and - values. Those strings are still converted to Unicode for internal storage so - in any case when such conversion is not possible (using the 'ascii' codec), - UnicodeDecodeError is raised. - - 3.2.0r1 - ~~~~~~~ - - * the first public release compatible with 3.2.0 + fixes for `#11324 - `_, `#11670 - `_ and `#11858 - `_. - - Conversion Process - ------------------ - - This section is technical and should bother you only if you are wondering how - this backport is produced. If the implementation details of this backport are - not important for you, feel free to ignore the following content. - - ``configparser`` is converted using `3to2 `_. - Because a fully automatic conversion was not doable, I took the following - branching approach: - - * the ``3.x`` branch holds unchanged files synchronized from the upstream - CPython repository. The synchronization is currently done by manually copying - the required files and stating from which CPython changeset they come from. - - * the ``3.x-clean`` branch holds a version of the ``3.x`` code with some tweaks - that make it independent from libraries and constructions unavailable on 2.x. - Code on this branch still *must* work on the corresponding Python 3.x. You - can check this running the supplied unit tests. - - * the ``default`` branch holds necessary changes which break unit tests on - Python 3.2. Additional files which are used by the backport are also stored - here. - - The process works like this: - - 1. I update the ``3.x`` branch with new versions of files. Commit. - - 2. I merge the new commit to ``3.x-clean``. Check unit tests. Commit. - - 3. If there are necessary changes that can be made in a 3.x compatible manner, - I do them now (still on ``3.x-clean``), check unit tests and commit. If I'm - not yet aware of any, no problem. - - 4. I merge the changes from ``3.x-clean`` to ``default``. Commit. - - 5. If there are necessary changes that *cannot* be made in a 3.x compatible - manner, I do them now (on ``default``). Note that the changes should still - be written using 3.x syntax. If I'm not yet aware of any required changes, - no problem. - - 6. I run ``./convert.py`` which is a custom ``3to2`` runner for this project. - - 7. I run the unit tests with ``unittest2`` on Python 2.x. If the tests are OK, - I can prepare a new release. Otherwise, I revert the ``default`` branch to - its previous state (``hg revert .``) and go back to Step 3. - - **NOTE:** the ``default`` branch holds unconverted code. This is because keeping - the conversion step as the last (after any custom changes) helps managing the - history better. Plus, the merges are nicer and updates of the converter software - don't create nasty conflicts in the repository. - - This process works well but if you have any tips on how to make it simpler and - faster, do enlighten me :) - - Footnotes - --------- - - .. [1] To somewhat ease migration, passing bytestrings is still supported but - they are converted to Unicode for internal storage anyway. This means - that for the vast majority of strings used in configuration files, it - won't matter if you pass them as bytestrings or Unicode. However, if you - pass a bytestring that cannot be converted to Unicode using the naive - ASCII codec, a ``UnicodeDecodeError`` will be raised. This is purposeful - and helps you manage proper encoding for all content you store in - memory, read from various sources and write back. - - .. [2] Life gets much easier when you understand that you basically manage - **text** in your application. You don't care about bytes but about - letters. In that regard the concept of content encoding is meaningless. - The only time when you deal with raw bytes is when you write the data to - a file. Then you have to specify how your text should be encoded. On - the other end, to get meaningful text from a file, the application - reading it has to know which encoding was used during its creation. But - once the bytes are read and properly decoded, all you have is text. This - is especially powerful when you start interacting with multiple data - sources. Even if each of them uses a different encoding, inside your - application data is held in abstract text form. You can program your - business logic without worrying about which data came from which source. - You can freely exchange the data you store between sources. Only - reading/writing files requires encoding your text to bytes. - -Keywords: configparser ini parsing conf cfg configuration file -Platform: any -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Natural Language :: English -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Topic :: Software Development :: Libraries -Classifier: Topic :: Software Development :: Libraries :: Python Modules diff -Nru configparser-3.3.0r2/configparser.egg-info/requires.txt configparser-3.5.0/configparser.egg-info/requires.txt --- configparser-3.3.0r2/configparser.egg-info/requires.txt 2013-01-02 00:58:18.000000000 +0000 +++ configparser-3.5.0/configparser.egg-info/requires.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -ordereddict \ No newline at end of file diff -Nru configparser-3.3.0r2/configparser.egg-info/SOURCES.txt configparser-3.5.0/configparser.egg-info/SOURCES.txt --- configparser-3.3.0r2/configparser.egg-info/SOURCES.txt 2013-01-02 00:58:18.000000000 +0000 +++ configparser-3.5.0/configparser.egg-info/SOURCES.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -MANIFEST.in -README.rst -configparser.py -configparser.rst -configparser_helpers.py -setup.py -configparser.egg-info/PKG-INFO -configparser.egg-info/SOURCES.txt -configparser.egg-info/dependency_links.txt -configparser.egg-info/requires.txt -configparser.egg-info/top_level.txt -configparser.egg-info/zip-safe \ No newline at end of file diff -Nru configparser-3.3.0r2/configparser.egg-info/top_level.txt configparser-3.5.0/configparser.egg-info/top_level.txt --- configparser-3.3.0r2/configparser.egg-info/top_level.txt 2013-01-02 00:58:18.000000000 +0000 +++ configparser-3.5.0/configparser.egg-info/top_level.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -configparser_helpers -configparser diff -Nru configparser-3.3.0r2/configparser.egg-info/zip-safe configparser-3.5.0/configparser.egg-info/zip-safe --- configparser-3.3.0r2/configparser.egg-info/zip-safe 2012-12-31 15:01:03.000000000 +0000 +++ configparser-3.5.0/configparser.egg-info/zip-safe 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - diff -Nru configparser-3.3.0r2/configparser_helpers.py configparser-3.5.0/configparser_helpers.py --- configparser-3.3.0r2/configparser_helpers.py 2013-01-02 00:57:10.000000000 +0000 +++ configparser-3.5.0/configparser_helpers.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from collections import MutableMapping -try: - from thread import get_ident -except ImportError: - try: - from _thread import get_ident - except ImportError: - from _dummy_thread import get_ident - -# from reprlib 3.2.1 -def recursive_repr(fillvalue=u'...'): - u'Decorator to make a repr function return fillvalue for a recursive call' - - def decorating_function(user_function): - repr_running = set() - - def wrapper(self): - key = id(self), get_ident() - if key in repr_running: - return fillvalue - repr_running.add(key) - try: - result = user_function(self) - finally: - repr_running.discard(key) - return result - - # Can't use functools.wraps() here because of bootstrap issues - wrapper.__module__ = getattr(user_function, u'__module__') - wrapper.__doc__ = getattr(user_function, u'__doc__') - wrapper.__name__ = getattr(user_function, u'__name__') - wrapper.__annotations__ = getattr(user_function, u'__annotations__', {}) - return wrapper - - return decorating_function - -# from collections 3.2.1 -class _ChainMap(MutableMapping): - u''' A ChainMap groups multiple dicts (or other mappings) together - to create a single, updateable view. - - The underlying mappings are stored in a list. That list is public and can - accessed or updated using the *maps* attribute. There is no other state. - - Lookups search the underlying mappings successively until a key is found. - In contrast, writes, updates, and deletions only operate on the first - mapping. - - ''' - - def __init__(self, *maps): - u'''Initialize a ChainMap by setting *maps* to the given mappings. - If no mappings are provided, a single empty dictionary is used. - - ''' - self.maps = list(maps) or [{}] # always at least one map - - def __missing__(self, key): - raise KeyError(key) - - def __getitem__(self, key): - for mapping in self.maps: - try: - return mapping[key] # can't use 'key in mapping' with defaultdict - except KeyError: - pass - return self.__missing__(key) # support subclasses that define __missing__ - - def get(self, key, default=None): - return self[key] if key in self else default - - def __len__(self): - return len(set().union(*self.maps)) # reuses stored hash values if possible - - def __iter__(self): - return iter(set().union(*self.maps)) - - def __contains__(self, key): - return any(key in m for m in self.maps) - - @recursive_repr() - def __repr__(self): - return u'{0.__class__.__name__}({1})'.format( - self, u', '.join(map(repr, self.maps))) - - @classmethod - def fromkeys(cls, iterable, *args): - u'Create a ChainMap with a single dict created from the iterable.' - return cls(dict.fromkeys(iterable, *args)) - - def copy(self): - u'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]' - return self.__class__(self.maps[0].copy(), *self.maps[1:]) - - __copy__ = copy - - def new_child(self): # like Django's Context.push() - u'New ChainMap with a new dict followed by all previous maps.' - return self.__class__({}, *self.maps) - - @property - def parents(self): # like Django's Context.pop() - u'New ChainMap from maps[1:].' - return self.__class__(*self.maps[1:]) - - def __setitem__(self, key, value): - self.maps[0][key] = value - - def __delitem__(self, key): - try: - del self.maps[0][key] - except KeyError: - raise KeyError(u'Key not found in the first mapping: {!r}'.format(key)) - - def popitem(self): - u'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.' - try: - return self.maps[0].popitem() - except KeyError: - raise KeyError(u'No keys found in the first mapping.') - - def pop(self, key, *args): - u'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].' - try: - return self.maps[0].pop(key, *args) - except KeyError: - raise KeyError(u'Key not found in the first mapping: {!r}'.format(key)) - - def clear(self): - u'Clear maps[0], leaving maps[1:] intact.' - self.maps[0].clear() diff -Nru configparser-3.3.0r2/configparser.py configparser-3.5.0/configparser.py --- configparser-3.3.0r2/configparser.py 2013-01-02 00:57:10.000000000 +0000 +++ configparser-3.5.0/configparser.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,1336 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -u"""Configuration file parser. - -A configuration file consists of sections, lead by a "[section]" header, -and followed by "name: value" entries, with continuations and such in -the style of RFC 822. - -Intrinsic defaults can be specified by passing them into the -ConfigParser constructor as a dictionary. - -class: - -ConfigParser -- responsible for parsing a list of - configuration files, and managing the parsed database. - - methods: - - __init__(defaults=None, dict_type=_default_dict, allow_no_value=False, - delimiters=('=', ':'), comment_prefixes=('#', ';'), - inline_comment_prefixes=None, strict=True, - empty_lines_in_values=True): - Create the parser. When `defaults' is given, it is initialized into the - dictionary or intrinsic defaults. The keys must be strings, the values - must be appropriate for %()s string interpolation. - - When `dict_type' is given, it will be used to create the dictionary - objects for the list of sections, for the options within a section, and - for the default values. - - When `delimiters' is given, it will be used as the set of substrings - that divide keys from values. - - When `comment_prefixes' is given, it will be used as the set of - substrings that prefix comments in empty lines. Comments can be - indented. - - When `inline_comment_prefixes' is given, it will be used as the set of - substrings that prefix comments in non-empty lines. - - When `strict` is True, the parser won't allow for any section or option - duplicates while reading from a single source (file, string or - dictionary). Default is True. - - When `empty_lines_in_values' is False (default: True), each empty line - marks the end of an option. Otherwise, internal empty lines of - a multiline option are kept as part of the value. - - When `allow_no_value' is True (default: False), options without - values are accepted; the value presented for these is None. - - sections() - Return all the configuration section names, sans DEFAULT. - - has_section(section) - Return whether the given section exists. - - has_option(section, option) - Return whether the given option exists in the given section. - - options(section) - Return list of configuration options for the named section. - - read(filenames, encoding=None) - Read and parse the list of named configuration files, given by - name. A single filename is also allowed. Non-existing files - are ignored. Return list of successfully read files. - - read_file(f, filename=None) - Read and parse one configuration file, given as a file object. - The filename defaults to f.name; it is only used in error - messages (if f has no `name' attribute, the string `' is used). - - read_string(string) - Read configuration from a given string. - - read_dict(dictionary) - Read configuration from a dictionary. Keys are section names, - values are dictionaries with keys and values that should be present - in the section. If the used dictionary type preserves order, sections - and their keys will be added in order. Values are automatically - converted to strings. - - get(section, option, raw=False, vars=None, fallback=_UNSET) - Return a string value for the named option. All % interpolations are - expanded in the return values, based on the defaults passed into the - constructor and the DEFAULT section. Additional substitutions may be - provided using the `vars' argument, which must be a dictionary whose - contents override any pre-existing defaults. If `option' is a key in - `vars', the value from `vars' is used. - - getint(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to an integer. - - getfloat(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to a float. - - getboolean(section, options, raw=False, vars=None, fallback=_UNSET) - Like get(), but convert value to a boolean (currently case - insensitively defined as 0, false, no, off for False, and 1, true, - yes, on for True). Returns False or True. - - items(section=_UNSET, raw=False, vars=None) - If section is given, return a list of tuples with (name, value) for - each option in the section. Otherwise, return a list of tuples with - (section_name, section_proxy) for each section, including DEFAULTSECT. - - remove_section(section) - Remove the given file section and all its options. - - remove_option(section, option) - Remove the given option from the given section. - - set(section, option, value) - Set the given option. - - write(fp, space_around_delimiters=True) - Write the configuration state in .ini format. If - `space_around_delimiters' is True (the default), delimiters - between keys and values are surrounded by spaces. -""" - -from __future__ import with_statement -from collections import MutableMapping -from io import open -try: - from collections import OrderedDict as _default_dict -except ImportError: - from ordereddict import OrderedDict as _default_dict -import functools -import io -import itertools -import re -import sys -import warnings - -from configparser_helpers import _ChainMap - -__all__ = [u"NoSectionError", u"DuplicateOptionError", u"DuplicateSectionError", - u"NoOptionError", u"InterpolationError", u"InterpolationDepthError", - u"InterpolationSyntaxError", u"ParsingError", - u"MissingSectionHeaderError", - u"ConfigParser", u"SafeConfigParser", u"RawConfigParser", - u"DEFAULTSECT", u"MAX_INTERPOLATION_DEPTH"] - -DEFAULTSECT = u"DEFAULT" - -MAX_INTERPOLATION_DEPTH = 10 - - - -# exception classes -class Error(Exception): - u"""Base class for ConfigParser exceptions.""" - - def _get_message(self): - u"""Getter for 'message'; needed only to override deprecation in - BaseException. - """ - return self.__message - - def _set_message(self, value): - u"""Setter for 'message'; needed only to override deprecation in - BaseException. - """ - self.__message = value - - # BaseException.message has been deprecated since Python 2.6. To prevent - # DeprecationWarning from popping up over this pre-existing attribute, use - # a new property that takes lookup precedence. - message = property(_get_message, _set_message) - - def __init__(self, msg=u''): - self.message = msg - Exception.__init__(self, msg) - - def __repr__(self): - return self.message - - __str__ = __repr__ - - -class NoSectionError(Error): - u"""Raised when no section matches a requested option.""" - - def __init__(self, section): - Error.__init__(self, u'No section: %r' % (section,)) - self.section = section - self.args = (section, ) - - -class DuplicateSectionError(Error): - u"""Raised when a section is repeated in an input source. - - Possible repetitions that raise this exception are: multiple creation - using the API or in strict parsers when a section is found more than once - in a single input file, string or dictionary. - """ - - def __init__(self, section, source=None, lineno=None): - msg = [repr(section), u" already exists"] - if source is not None: - message = [u"While reading from ", source] - if lineno is not None: - message.append(u" [line {0:2d}]".format(lineno)) - message.append(u": section ") - message.extend(msg) - msg = message - else: - msg.insert(0, u"Section ") - Error.__init__(self, u"".join(msg)) - self.section = section - self.source = source - self.lineno = lineno - self.args = (section, source, lineno) - - -class DuplicateOptionError(Error): - u"""Raised by strict parsers when an option is repeated in an input source. - - Current implementation raises this exception only when an option is found - more than once in a single file, string or dictionary. - """ - - def __init__(self, section, option, source=None, lineno=None): - msg = [repr(option), u" in section ", repr(section), - u" already exists"] - if source is not None: - message = [u"While reading from ", source] - if lineno is not None: - message.append(u" [line {0:2d}]".format(lineno)) - message.append(u": option ") - message.extend(msg) - msg = message - else: - msg.insert(0, u"Option ") - Error.__init__(self, u"".join(msg)) - self.section = section - self.option = option - self.source = source - self.lineno = lineno - self.args = (section, option, source, lineno) - - -class NoOptionError(Error): - u"""A requested option was not found.""" - - def __init__(self, option, section): - Error.__init__(self, u"No option %r in section: %r" % - (option, section)) - self.option = option - self.section = section - self.args = (option, section) - - -class InterpolationError(Error): - u"""Base class for interpolation-related exceptions.""" - - def __init__(self, option, section, msg): - Error.__init__(self, msg) - self.option = option - self.section = section - self.args = (option, section, msg) - - -class InterpolationMissingOptionError(InterpolationError): - u"""A string substitution required a setting which was not available.""" - - def __init__(self, option, section, rawval, reference): - msg = (u"Bad value substitution:\n" - u"\tsection: [%s]\n" - u"\toption : %s\n" - u"\tkey : %s\n" - u"\trawval : %s\n" - % (section, option, reference, rawval)) - InterpolationError.__init__(self, option, section, msg) - self.reference = reference - self.args = (option, section, rawval, reference) - - -class InterpolationSyntaxError(InterpolationError): - u"""Raised when the source text contains invalid syntax. - - Current implementation raises this exception when the source text into - which substitutions are made does not conform to the required syntax. - """ - - -class InterpolationDepthError(InterpolationError): - u"""Raised when substitutions are nested too deeply.""" - - def __init__(self, option, section, rawval): - msg = (u"Value interpolation too deeply recursive:\n" - u"\tsection: [%s]\n" - u"\toption : %s\n" - u"\trawval : %s\n" - % (section, option, rawval)) - InterpolationError.__init__(self, option, section, msg) - self.args = (option, section, rawval) - - -class ParsingError(Error): - u"""Raised when a configuration file does not follow legal syntax.""" - - def __init__(self, source=None, filename=None): - # Exactly one of `source'/`filename' arguments has to be given. - # `filename' kept for compatibility. - if filename and source: - raise ValueError(u"Cannot specify both `filename' and `source'. " - u"Use `source'.") - elif not filename and not source: - raise ValueError(u"Required argument `source' not given.") - elif filename: - source = filename - Error.__init__(self, u'Source contains parsing errors: %s' % source) - self.source = source - self.errors = [] - self.args = (source, ) - - @property - def filename(self): - u"""Deprecated, use `source'.""" - warnings.warn( - u"The 'filename' attribute will be removed in future versions. " - u"Use 'source' instead.", - DeprecationWarning, stacklevel=2 - ) - return self.source - - @filename.setter - def filename(self, value): - u"""Deprecated, user `source'.""" - warnings.warn( - u"The 'filename' attribute will be removed in future versions. " - u"Use 'source' instead.", - DeprecationWarning, stacklevel=2 - ) - self.source = value - - def append(self, lineno, line): - self.errors.append((lineno, line)) - self.message += u'\n\t[line %2d]: %s' % (lineno, line) - - -class MissingSectionHeaderError(ParsingError): - u"""Raised when a key-value pair is found before any section header.""" - - def __init__(self, filename, lineno, line): - Error.__init__( - self, - u'File contains no section headers.\nfile: %s, line: %d\n%r' % - (filename, lineno, line)) - self.source = filename - self.lineno = lineno - self.line = line - self.args = (filename, lineno, line) - - -# Used in parser getters to indicate the default behaviour when a specific -# option is not found it to raise an exception. Created to enable `None' as -# a valid fallback value. -_UNSET = object() - - -class Interpolation(object): - u"""Dummy interpolation that passes the value through with no changes.""" - - def before_get(self, parser, section, option, value, defaults): - return value - - def before_set(self, parser, section, option, value): - return value - - def before_read(self, parser, section, option, value): - return value - - def before_write(self, parser, section, option, value): - return value - - -class BasicInterpolation(Interpolation): - u"""Interpolation as implemented in the classic ConfigParser. - - The option values can contain format strings which refer to other values in - the same section, or values in the special default section. - - For example: - - something: %(dir)s/whatever - - would resolve the "%(dir)s" to the value of dir. All reference - expansions are done late, on demand. If a user needs to use a bare % in - a configuration file, she can escape it by writing %%. Other other % usage - is considered a user error and raises `InterpolationSyntaxError'.""" - - _KEYCRE = re.compile(ur"%\(([^)]+)\)s") - - def before_get(self, parser, section, option, value, defaults): - L = [] - self._interpolate_some(parser, option, L, value, section, defaults, 1) - return u''.join(L) - - def before_set(self, parser, section, option, value): - tmp_value = value.replace(u'%%', u'') # escaped percent signs - tmp_value = self._KEYCRE.sub(u'', tmp_value) # valid syntax - if u'%' in tmp_value: - raise ValueError(u"invalid interpolation syntax in %r at " - u"position %d" % (value, tmp_value.find(u'%'))) - return value - - def _interpolate_some(self, parser, option, accum, rest, section, map, - depth): - if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rest) - while rest: - p = rest.find(u"%") - if p < 0: - accum.append(rest) - return - if p > 0: - accum.append(rest[:p]) - rest = rest[p:] - # p is no longer used - c = rest[1:2] - if c == u"%": - accum.append(u"%") - rest = rest[2:] - elif c == u"(": - m = self._KEYCRE.match(rest) - if m is None: - raise InterpolationSyntaxError(option, section, - u"bad interpolation variable reference %r" % rest) - var = parser.optionxform(m.group(1)) - rest = rest[m.end():] - try: - v = map[var] - except KeyError: - raise InterpolationMissingOptionError( - option, section, rest, var) - if u"%" in v: - self._interpolate_some(parser, option, accum, v, - section, map, depth + 1) - else: - accum.append(v) - else: - raise InterpolationSyntaxError( - option, section, - u"'%%' must be followed by '%%' or '(', " - u"found: %r" % (rest,)) - - -class ExtendedInterpolation(Interpolation): - u"""Advanced variant of interpolation, supports the syntax used by - `zc.buildout'. Enables interpolation between sections.""" - - _KEYCRE = re.compile(ur"\$\{([^}]+)\}") - - def before_get(self, parser, section, option, value, defaults): - L = [] - self._interpolate_some(parser, option, L, value, section, defaults, 1) - return u''.join(L) - - def before_set(self, parser, section, option, value): - tmp_value = value.replace(u'$$', u'') # escaped dollar signs - tmp_value = self._KEYCRE.sub(u'', tmp_value) # valid syntax - if u'$' in tmp_value: - raise ValueError(u"invalid interpolation syntax in %r at " - u"position %d" % (value, tmp_value.find(u'%'))) - return value - - def _interpolate_some(self, parser, option, accum, rest, section, map, - depth): - if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rest) - while rest: - p = rest.find(u"$") - if p < 0: - accum.append(rest) - return - if p > 0: - accum.append(rest[:p]) - rest = rest[p:] - # p is no longer used - c = rest[1:2] - if c == u"$": - accum.append(u"$") - rest = rest[2:] - elif c == u"{": - m = self._KEYCRE.match(rest) - if m is None: - raise InterpolationSyntaxError(option, section, - u"bad interpolation variable reference %r" % rest) - path = m.group(1).split(u':') - rest = rest[m.end():] - sect = section - opt = option - try: - if len(path) == 1: - opt = parser.optionxform(path[0]) - v = map[opt] - elif len(path) == 2: - sect = path[0] - opt = parser.optionxform(path[1]) - v = parser.get(sect, opt, raw=True) - else: - raise InterpolationSyntaxError( - option, section, - u"More than one ':' found: %r" % (rest,)) - except (KeyError, NoSectionError, NoOptionError): - raise InterpolationMissingOptionError( - option, section, rest, u":".join(path)) - if u"$" in v: - self._interpolate_some(parser, opt, accum, v, sect, - dict(parser.items(sect, raw=True)), - depth + 1) - else: - accum.append(v) - else: - raise InterpolationSyntaxError( - option, section, - u"'$' must be followed by '$' or '{', " - u"found: %r" % (rest,)) - - -class LegacyInterpolation(Interpolation): - u"""Deprecated interpolation used in old versions of ConfigParser. - Use BasicInterpolation or ExtendedInterpolation instead.""" - - _KEYCRE = re.compile(ur"%\(([^)]*)\)s|.") - - def before_get(self, parser, section, option, value, vars): - rawval = value - depth = MAX_INTERPOLATION_DEPTH - while depth: # Loop through this until it's done - depth -= 1 - if value and u"%(" in value: - replace = functools.partial(self._interpolation_replace, - parser=parser) - value = self._KEYCRE.sub(replace, value) - try: - value = value % vars - except KeyError, e: - raise InterpolationMissingOptionError( - option, section, rawval, e.args[0]) - else: - break - if value and u"%(" in value: - raise InterpolationDepthError(option, section, rawval) - return value - - def before_set(self, parser, section, option, value): - return value - - @staticmethod - def _interpolation_replace(match, parser): - s = match.group(1) - if s is None: - return match.group() - else: - return u"%%(%s)s" % parser.optionxform(s) - - -class RawConfigParser(MutableMapping): - u"""ConfigParser that does not do interpolation.""" - - # Regular expressions for parsing section headers and options - _SECT_TMPL = ur""" - \[ # [ - (?P
[^]]+) # very permissive! - \] # ] - """ - _OPT_TMPL = ur""" - (?P