From 5e1121e7aff4b5b05f22241ff76d20bedc88e5ea Mon Sep 17 00:00:00 2001 From: Hong Xu Date: Fri, 9 Nov 2018 14:48:27 -0800 Subject: [PATCH] Revert "Update to 0.11.1 EditorConfig Python Core library" This reverts commit 35c063e9fd078889f1d3dbfb4b6a8a0e6b5f4779. --- editorconfig-core-py/.editorconfig | 12 +- editorconfig-core-py/.travis.yml | 43 +- editorconfig-core-py/MANIFEST.in | 1 - editorconfig-core-py/README.rst | 13 +- editorconfig-core-py/docs/conf.py | 9 +- editorconfig-core-py/docs/plugins.rst | 72 -- editorconfig-core-py/docs/usage.rst | 8 +- editorconfig-core-py/editorconfig/__init__.py | 8 +- editorconfig-core-py/editorconfig/compat.py | 18 - .../editorconfig/exceptions.py | 5 +- editorconfig-core-py/editorconfig/fnmatch.py | 52 +- editorconfig-core-py/editorconfig/handler.py | 8 +- editorconfig-core-py/editorconfig/ini.py | 7 +- editorconfig-core-py/editorconfig/main.py | 45 +- editorconfig-core-py/editorconfig/odict.py | 658 ++++++++++++++++-- .../editorconfig/versiontools.py | 4 +- .../java-binding/.editorconfig | 9 - editorconfig-core-py/java-binding/.gitignore | 5 - editorconfig-core-py/java-binding/LICENSE.txt | 192 ----- editorconfig-core-py/java-binding/README.md | 60 -- editorconfig-core-py/java-binding/build.xml | 78 --- .../example/TestEditorConfig.java | 23 - .../java-binding/example/test-example.bat | 9 - .../java-binding/example/test-example.sh | 5 - .../org/editorconfig/core/EditorConfig.java | 155 ----- .../core/EditorConfigException.java | 11 - .../editorconfig/core/ParsingException.java | 12 - .../org/editorconfig/core/PathException.java | 13 - .../editorconfig/core/PythonException.java | 13 - .../editorconfig/core/VersionException.java | 12 - .../org/editorconfig/core/package-info.java | 8 - editorconfig-core-py/setup.py | 1 + editorconfig-core-py/tests | 2 +- 33 files changed, 666 insertions(+), 905 deletions(-) delete mode 100644 editorconfig-core-py/MANIFEST.in delete mode 100644 editorconfig-core-py/docs/plugins.rst delete mode 100644 editorconfig-core-py/editorconfig/compat.py delete mode 100644 editorconfig-core-py/java-binding/.editorconfig delete mode 100644 editorconfig-core-py/java-binding/.gitignore delete mode 100644 editorconfig-core-py/java-binding/LICENSE.txt delete mode 100644 editorconfig-core-py/java-binding/README.md delete mode 100644 editorconfig-core-py/java-binding/build.xml delete mode 100644 editorconfig-core-py/java-binding/example/TestEditorConfig.java delete mode 100644 editorconfig-core-py/java-binding/example/test-example.bat delete mode 100755 editorconfig-core-py/java-binding/example/test-example.sh delete mode 100644 editorconfig-core-py/java-binding/src/org/editorconfig/core/EditorConfig.java delete mode 100644 editorconfig-core-py/java-binding/src/org/editorconfig/core/EditorConfigException.java delete mode 100644 editorconfig-core-py/java-binding/src/org/editorconfig/core/ParsingException.java delete mode 100644 editorconfig-core-py/java-binding/src/org/editorconfig/core/PathException.java delete mode 100644 editorconfig-core-py/java-binding/src/org/editorconfig/core/PythonException.java delete mode 100644 editorconfig-core-py/java-binding/src/org/editorconfig/core/VersionException.java delete mode 100644 editorconfig-core-py/java-binding/src/org/editorconfig/core/package-info.java diff --git a/editorconfig-core-py/.editorconfig b/editorconfig-core-py/.editorconfig index 794bb51..b34c9d7 100644 --- a/editorconfig-core-py/.editorconfig +++ b/editorconfig-core-py/.editorconfig @@ -1,12 +1,16 @@ root = true -[*.{py,rst,txt}] +[*.py] indent_style = space -trim_trailing_whitespace = true indent_size = 4 end_of_line = LF -[*.yml] +[*.rst] indent_style = space -indent_size = 2 +indent_size = 4 +end_of_line = LF + +[*.txt] +indent_style = space +indent_size = 4 end_of_line = LF diff --git a/editorconfig-core-py/.travis.yml b/editorconfig-core-py/.travis.yml index 263824d..ca6bdb1 100644 --- a/editorconfig-core-py/.travis.yml +++ b/editorconfig-core-py/.travis.yml @@ -6,46 +6,27 @@ python: - "2.5" - "2.6" - "2.7" - - "3.2" - - "3.3" + - "jython" -# For testing with JYTHON=true, we will use Jython 2.2 instead of the python -# version provided by Travis CI -env: - - JYTHON=true - - JYTHON=false - -matrix: - exclude: - - python: "2.5" - env: JYTHON=true - - python: "2.6" - env: JYTHON=true - - python: "3.2" - env: JYTHON=true - - python: "3.3" - env: JYTHON=true - -# we need cmake, and jython if JYTHON=true +# we need cmake, and jython if the python version is "jython" install: - - sudo apt-get install cmake ant + - sudo apt-get install cmake - export JYTHON_URL='http://downloads.sourceforge.net/project/jython/jython/2.2.1/jython_installer-2.2.1.jar?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fjython%2Ffiles%2Fjython%2F2.2.1%2F&ts=1338180153&use_mirror=iweb' - - if [ "$JYTHON" == "true" ]; then wget $JYTHON_URL -O jython_installer.jar; java -jar jython_installer.jar -s -d $HOME/jython; export PATH=$HOME/jython:$PATH;jython --version; fi + - if [ "$TRAVIS_PYTHON_VERSION" == "jython" ]; then wget $JYTHON_URL -O jython_installer.jar; java -jar jython_installer.jar -s -d $HOME/jython; export PATH=$HOME/jython:$PATH;jython --version; fi -# Before run the test case, we need to make jython run some code +# Before run the test case, we need to make jython run some other code before_script: - - if [ "$JYTHON" == "true" ]; then jython -c "print ''"; fi + - if [ "$TRAVIS_PYTHON_VERSION" == "jython" ]; then jython -c "print ''"; fi # test script script: - - if [ "$JYTHON" == "true" ]; then cmake -DPYTHON_EXECUTABLE="$(which jython)" . ; else cmake . ; fi + - if [ "$TRAVIS_PYTHON_VERSION" == "jython" ]; then cmake -DPYTHON_EXECUTABLE="$(which jython)" . ; else cmake . ; fi - ctest -V --output-on-failure . - - cd java-binding - - ant -v - - ant -v doc # Notify the mailing list notifications: - email: - on_success: change - on_failure: always + recipients: + - editorconfig@googlegroups.com + email: + on_success: change + on_failure: always diff --git a/editorconfig-core-py/MANIFEST.in b/editorconfig-core-py/MANIFEST.in deleted file mode 100644 index 88629c9..0000000 --- a/editorconfig-core-py/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -include README.rst LICENSE.txt diff --git a/editorconfig-core-py/README.rst b/editorconfig-core-py/README.rst index f3cccf5..00c6bb3 100644 --- a/editorconfig-core-py/README.rst +++ b/editorconfig-core-py/README.rst @@ -40,9 +40,7 @@ may want to import and use the EditorConfig Python Core directly. Using as a Library ================== -Basic example use of EditorConfig Python Core as a library: - -.. code-block:: python +Basic example use of EditorConfig Python Core as a library:: from editorconfig import get_properties, EditorConfigError @@ -56,9 +54,6 @@ Basic example use of EditorConfig Python Core as a library: for key, value in options.items(): print "%s=%s" % (key, value) -For details, please take a look at the `online documentation -`_. - Running Test Cases ================== @@ -68,12 +63,6 @@ using the following commands:: cmake . ctest . -Use ``-DPYTHON_EXECUTABLE`` to run the tests using an alternative versions of -Python (Python 3, Jython, etc.):: - - cmake -DPYTHON_EXECUTABLE=/usr/bin/python3 . - ctest . - License ======= diff --git a/editorconfig-core-py/docs/conf.py b/editorconfig-core-py/docs/conf.py index bd060da..25faee2 100644 --- a/editorconfig-core-py/docs/conf.py +++ b/editorconfig-core-py/docs/conf.py @@ -16,10 +16,7 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('..')) - -import editorconfig -from editorconfig import __version__ +#sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- @@ -51,9 +48,9 @@ # built documents. # # The short X.Y version. -version = __version__ +version = '0.9.0' # The full version, including alpha/beta/rc tags. -release = __version__ +release = '0.9.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/editorconfig-core-py/docs/plugins.rst b/editorconfig-core-py/docs/plugins.rst deleted file mode 100644 index e22922a..0000000 --- a/editorconfig-core-py/docs/plugins.rst +++ /dev/null @@ -1,72 +0,0 @@ -=============== -Writing Plugins -=============== - -The EditorConfig Python Core can be easily used by text editor plugins written in Python or plugins that can call an external Python interpreter. The EditorConfig Python Core supports Python versions 2.2 to 2.7. Check out the `Vim`_ and `Gedit`_ plugins for example usages of the EditorConfig Python Core. - -.. _`Vim`: https://github.com/editorconfig/editorconfig-vim -.. _`Gedit`: https://github.com/editorconfig/editorconfig-gedit - - -Use as a library ----------------- - -For instructions on using the EditorConfig Python Core as a Python library see :doc:`usage`. - - -Using with an external Python interpreter ------------------------------------------ - -The EditorConfig Python Core can be used with an external Python interpreter by executing the ``main.py`` file. The ``main.py`` file can be executed like so:: - - python editorconfig-core-py/main.py /home/zoidberg/humans/anatomy.md - -For more information on command line usage of the EditorConfig Python Core see :doc:`command_line_usage`. - - -Bundling EditorConfig Python Core with Plugin ---------------------------------------------- - -A text editor or IDE plugin will either need to bundle the EditorConfig Python -Core with the plugin installation package or the will need to assist the user -in installing the EditorConfig Python Core. Below are instructions for -bundling the EditorConfig Python Core with plugins. - -Bundling as a Submodule in Git -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Git submodules allow one repository to be included inside another. A submodule -stores a remote repositry and commit to use for fetching the embedded -repository. Submodules take up very little space in the repository since they -do not actually include the code of the embedded repository directly. - -To add EditorConfig Python Core as a submodule in the ``editorconfig-core-py`` -directory of your repository:: - - git submodule add git://github.com/editorconfig/editorconfig-core-py.git editorconfig-core-py - -Then every time the code is checked out the submodule directory should be -initialized and updated:: - - git submodule update --init - -Bundling as a Subtree in Git -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Git subtrees are convenient because, unlike submodules, they do not require any -extra work to be performed when cloning the git repository. Git subtrees -include one git codebase as a subdirectory of another. - -Example of using a subtree for the ``editorconfig`` directory from the -EditorConfig Python Core repository:: - - git remote add -f editorconfig-core-py git://github.com/editorconfig/editorconfig-core-py.git - git merge -s ours --no-commit editorconfig-core-py/master - git read-tree --prefix=editorconfig -u editorconfig-core-py/master:editorconfig - git commit - -For more information on subtrees consult the `subtree merge guide`_ on Github -and `Chapter 6.7`_ in the book Pro Git. - -.. _`subtree merge guide`: http://help.github.com/subtree-merge/ -.. _`Chapter 6.7`: http://git-scm.com/book/ch6-7.html diff --git a/editorconfig-core-py/docs/usage.rst b/editorconfig-core-py/docs/usage.rst index 993ffdf..cbd030e 100644 --- a/editorconfig-core-py/docs/usage.rst +++ b/editorconfig-core-py/docs/usage.rst @@ -15,9 +15,7 @@ Discovering EditorConfig properties ----------------------------------- The ``get_properties`` function can be used to discover EditorConfig properties -for a given file. Example: - -.. code-block:: python +for a given file. Example:: import logging from editorconfig import get_properties, EditorConfigError @@ -61,9 +59,7 @@ the current exception types: Exception handling example ~~~~~~~~~~~~~~~~~~~~~~~~~~ -An example of custom exception handling: - -.. code-block:: python +An example of custom exception handling:: import logging from editorconfig import get_properties diff --git a/editorconfig-core-py/editorconfig/__init__.py b/editorconfig-core-py/editorconfig/__init__.py index e3a577a..0b842f8 100644 --- a/editorconfig-core-py/editorconfig/__init__.py +++ b/editorconfig-core-py/editorconfig/__init__.py @@ -1,8 +1,8 @@ """EditorConfig Python Core""" -from editorconfig.versiontools import join_version +from versiontools import join_version -VERSION = (0, 11, 1, "final") +VERSION = (0, 9, 0, "final") __all__ = ['get_properties', 'EditorConfigError', 'exceptions'] @@ -15,5 +15,5 @@ def get_properties(filename): return handler.get_configurations() -from editorconfig.handler import EditorConfigHandler -from editorconfig.exceptions import * +from handler import EditorConfigHandler +from exceptions import * diff --git a/editorconfig-core-py/editorconfig/compat.py b/editorconfig-core-py/editorconfig/compat.py deleted file mode 100644 index ebd0405..0000000 --- a/editorconfig-core-py/editorconfig/compat.py +++ /dev/null @@ -1,18 +0,0 @@ -"""EditorConfig Python2/Python3/Jython compatibility utilities""" -import sys -import types - -__all__ = ['slice', 'u'] - - -if sys.version_info[0] == 2: - slice = types.SliceType -else: - slice = slice - - -if sys.version_info[0] == 2: - import codecs - u = lambda s: codecs.unicode_escape_decode(s)[0] -else: - u = lambda s: s diff --git a/editorconfig-core-py/editorconfig/exceptions.py b/editorconfig-core-py/editorconfig/exceptions.py index 545732b..c93e914 100644 --- a/editorconfig-core-py/editorconfig/exceptions.py +++ b/editorconfig-core-py/editorconfig/exceptions.py @@ -9,10 +9,7 @@ class EditorConfigError(Exception): """Parent class of all exceptions raised by EditorConfig""" -try: - from ConfigParser import ParsingError as _ParsingError -except: - from configparser import ParsingError as _ParsingError +from ConfigParser import ParsingError as _ParsingError class ParsingError(_ParsingError, EditorConfigError): diff --git a/editorconfig-core-py/editorconfig/fnmatch.py b/editorconfig-core-py/editorconfig/fnmatch.py index a1d5f10..e27fe42 100644 --- a/editorconfig-core-py/editorconfig/fnmatch.py +++ b/editorconfig-core-py/editorconfig/fnmatch.py @@ -24,18 +24,16 @@ _cache = {} - def fnmatch(name, pat): """Test whether FILENAME matches PATTERN. Patterns are Unix shell style: - - ``*`` matches everything except path separator - - ``**`` matches everything - - ``?`` matches any single character - - ``[seq]`` matches any character in seq - - ``[!seq]`` matches any char not in seq - - ``{s1,s2,s3}`` matches any of the strings given (separated by commas) + - ``*`` matches everything except path separator + - ``**`` matches everything + - ``?`` matches any single character + - ``[seq]`` matches any character in seq + - ``[!seq]`` matches any char not in seq An initial period in FILENAME is not special. Both FILENAME and PATTERN are first case-normalized @@ -46,7 +44,6 @@ def fnmatch(name, pat): name = os.path.normcase(name).replace(os.sep, "/") return fnmatchcase(name, pat) - def fnmatchcase(name, pat): """Test whether FILENAME matches PATTERN, including case. @@ -59,7 +56,6 @@ def fnmatchcase(name, pat): _cache[pat] = re.compile(res) return _cache[pat].match(name) is not None - def translate(pat): """Translate a shell PATTERN to a regular expression. @@ -68,10 +64,9 @@ def translate(pat): i, n = 0, len(pat) res = '' - escaped = False while i < n: c = pat[i] - i = i + 1 + i = i+1 if c == '*': j = i if j < n and pat[j] == '*': @@ -83,44 +78,21 @@ def translate(pat): elif c == '[': j = i if j < n and pat[j] == '!': - j = j + 1 + j = j+1 if j < n and pat[j] == ']': - j = j + 1 - while j < n and (pat[j] != ']' or escaped): - escaped = pat[j] == '\\' and not escaped - j = j + 1 + j = j+1 + while j < n and pat[j] != ']': + j = j+1 if j >= n: res = res + '\\[' else: - stuff = pat[i:j] - i = j + 1 + stuff = pat[i:j].replace('\\','\\\\') + i = j+1 if stuff[0] == '!': stuff = '^' + stuff[1:] elif stuff[0] == '^': stuff = '\\' + stuff res = '%s[%s]' % (res, stuff) - elif c == '{': - j = i - groups = [] - while j < n and pat[j] != '}': - k = j - while k < n and (pat[k] not in (',', '}') or escaped): - escaped = pat[k] == '\\' and not escaped - k = k + 1 - group = pat[j:k] - for char in (',', '}', '\\'): - group = group.replace('\\' + char, char) - groups.append(group) - j = k - if j < n and pat[j] == ',': - j = j + 1 - if j < n and pat[j] == '}': - groups.append('') - if j >= n or len(groups) < 2: - res = res + '\\{' - else: - res = '%s(%s)' % (res, '|'.join(map(re.escape, groups))) - i = j + 1 else: res = res + re.escape(c) return res + '\Z(?ms)' diff --git a/editorconfig-core-py/editorconfig/handler.py b/editorconfig-core-py/editorconfig/handler.py index 6bab2be..10a55b1 100644 --- a/editorconfig-core-py/editorconfig/handler.py +++ b/editorconfig-core-py/editorconfig/handler.py @@ -102,8 +102,7 @@ def preprocess_values(self): opts = self.options # Lowercase option value for certain options - for name in ["end_of_line", "indent_style", "indent_size", - "insert_final_newline", "trim_trailing_whitespace", "charset"]: + for name in ["end_of_line", "indent_style", "indent_size"]: if name in opts: opts[name] = opts[name].lower() @@ -118,8 +117,3 @@ def preprocess_values(self): if ("indent_size" in opts and "tab_width" not in opts and opts["indent_size"] != "tab"): opts["tab_width"] = opts["indent_size"] - - # Set indent_size to tab_width if indent_size is "tab" - if ("indent_size" in opts and "tab_width" in opts and - opts["indent_size"] == "tab"): - opts["indent_size"] = opts["tab_width"] diff --git a/editorconfig-core-py/editorconfig/ini.py b/editorconfig-core-py/editorconfig/ini.py index 3f58fed..a457c54 100644 --- a/editorconfig-core-py/editorconfig/ini.py +++ b/editorconfig-core-py/editorconfig/ini.py @@ -14,15 +14,12 @@ """ import re -from codecs import open import posixpath from os import sep from os.path import normcase, dirname - from editorconfig.exceptions import ParsingError from editorconfig.fnmatch import fnmatch from editorconfig.odict import OrderedDict -from editorconfig.compat import u __all__ = ["ParsingError", "EditorConfigParser"] @@ -73,7 +70,7 @@ def matches_filename(self, config_filename, glob): def read(self, filename): """Read and parse single EditorConfig file""" try: - fp = open(filename, encoding='utf-8') + fp = open(filename) except IOError: return self._read(fp, filename) @@ -98,8 +95,6 @@ def _read(self, fp, fpname): line = fp.readline() if not line: break - if lineno == 0 and line.startswith(u('\ufeff')): - line = line[1:] # Strip UTF-8 BOM lineno = lineno + 1 # comment or blank line? if line.strip() == '' or line[0] in '#;': diff --git a/editorconfig-core-py/editorconfig/main.py b/editorconfig-core-py/editorconfig/main.py index cff8e24..ed6ddb4 100644 --- a/editorconfig-core-py/editorconfig/main.py +++ b/editorconfig-core-py/editorconfig/main.py @@ -14,7 +14,7 @@ def version(): - print("Version %s" % __version__) + print "Version %s" % __version__ def usage(command, error=False): @@ -22,21 +22,24 @@ def usage(command, error=False): out = sys.stderr else: out = sys.stdout - out.write("%s [OPTIONS] FILENAME\n" % command) - out.write('-f ' - 'Specify conf filename other than ".editorconfig".\n') - out.write("-b " - "Specify version (used by devs to test compatibility).\n") - out.write("-h OR --help Print this help message.\n") - out.write("-v OR --version Display version information.\n") + print >> out, "%s [OPTIONS] FILENAME" % command + print >> out, ('-f ' + 'Specify conf filename other than ".editorconfig".') + print >> out, ("-b " + "Specify version (used by devs to test compatibility).") + print >> out, "-h OR --help Print this help message." + print >> out, "-v OR --version Display version information." def main(): command_name = sys.argv[0] try: opts, args = getopt.getopt(sys.argv[1:], "vhb:f:", ["version", "help"]) - except getopt.GetoptError: - print(str(sys.exc_info()[1])) # For Python 2/3 compatibility + except getopt.GetoptError, err: + print str(err) + usage(command_name, error=True) + sys.exit(2) + if len(args) > 1: usage(command_name, error=True) sys.exit(2) @@ -60,17 +63,13 @@ def main(): if len(args) < 1: usage(command_name, error=True) sys.exit(2) - filenames = args - multiple_files = len(args) > 1 + filename = args[0] - for filename in filenames: - handler = EditorConfigHandler(filename, conf_filename, version_tuple) - try: - options = handler.get_configurations() - except (ParsingError, PathError, VersionError): - print(str(sys.exc_info()[1])) # For Python 2/3 compatibility - sys.exit(2) - if multiple_files: - print("[%s]" % filename) - for key, value in options.items(): - print("%s=%s" % (key, value)) + handler = EditorConfigHandler(filename, conf_filename, version_tuple) + try: + options = handler.get_configurations() + except (ParsingError, PathError, VersionError), e: + print >> sys.stderr, str(e) + sys.exit(2) + for key, value in options.items(): + print "%s=%s" % (key, value) diff --git a/editorconfig-core-py/editorconfig/odict.py b/editorconfig-core-py/editorconfig/odict.py index 949e585..41ce074 100644 --- a/editorconfig-core-py/editorconfig/odict.py +++ b/editorconfig-core-py/editorconfig/odict.py @@ -1,26 +1,40 @@ -"""odict.py: An Ordered Dictionary object""" +# odict.py +# An Ordered Dictionary object # Copyright (C) 2005 Nicola Larosa, Michael Foord # E-mail: nico AT tekNico DOT net, fuzzyman AT voidspace DOT org DOT uk + +# Documentation at http://www.voidspace.org.uk/python/odict.html +# For information about bugfixes, updates and support, please join the +# Pythonutils mailing list: +# http://groups.google.com/group/pythonutils/ +# Comments, suggestions and bug reports welcome. + +# This software is licensed under the terms of the BSD license. +# http://www.voidspace.org.uk/python/license.shtml +# Basically you're free to copy, modify, distribute and relicense it, +# So long as you keep a copy of the license with it. + # Copyright (c) 2003-2010, Michael Foord +# All rights reserved. # E-mail : fuzzyman AT voidspace DOT org DOT uk -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: -# -# +# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. -# +# # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. -# +# # * Neither the name of Michael Foord nor the name of Voidspace # may be used to endorse or promote products derived from this # software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,60 +47,64 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +"""A dict that keeps keys in insertion order""" from __future__ import generators -import sys -import warnings - -from editorconfig.compat import slice +__author__ = ('Nicola Larosa ,' + 'Michael Foord ') __docformat__ = "restructuredtext en" -__all__ = ['OrderedDict'] +__revision__ = '$Id: odict.py 129 2005-09-12 18:15:28Z teknico $' + +__version__ = '0.2.2' +__all__ = ['OrderedDict', 'SequenceOrderedDict'] + +import sys INTP_VER = sys.version_info[:2] if INTP_VER < (2, 2): raise RuntimeError("Python v.2.2 or later required") +import types, warnings class OrderedDict(dict): """ A class of dictionary that keeps the insertion order of keys. - + All appropriate methods return keys, items, or values in an ordered way. - + All normal dictionary methods are available. Update and comparison is restricted to other OrderedDict objects. - + Various sequence methods are available, including the ability to explicitly mutate the key ordering. - + __contains__ tests: - + >>> d = OrderedDict(((1, 3),)) >>> 1 in d 1 >>> 4 in d 0 - + __getitem__ tests: - + >>> OrderedDict(((1, 3), (3, 2), (2, 1)))[2] 1 >>> OrderedDict(((1, 3), (3, 2), (2, 1)))[4] Traceback (most recent call last): KeyError: 4 - + __len__ tests: - + >>> len(OrderedDict()) 0 >>> len(OrderedDict(((1, 3), (3, 2), (2, 1)))) 3 - + get tests: - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.get(1) 3 @@ -96,9 +114,9 @@ class OrderedDict(dict): 5 >>> d OrderedDict([(1, 3), (3, 2), (2, 1)]) - + has_key tests: - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.has_key(1) 1 @@ -110,11 +128,11 @@ def __init__(self, init_val=(), strict=False): """ Create a new ordered dictionary. Cannot init from a normal dict, nor from kwargs, since items order is undefined in those cases. - + If the ``strict`` keyword argument is ``True`` (``False`` is the default) then when doing slice assignment - the ``OrderedDict`` you are assigning from *must not* contain any keys in the remaining dict. - + >>> OrderedDict() OrderedDict([]) >>> OrderedDict({1: 1}) @@ -158,7 +176,7 @@ def __delitem__(self, key): >>> d OrderedDict([(2, 1), (3, 2)]) """ - if isinstance(key, slice): + if isinstance(key, types.SliceType): # FIXME: efficiency? keys = self._sequence[key] for entry in keys: @@ -297,7 +315,7 @@ def __ge__(self, other): def __repr__(self): """ Used for __repr__ and __str__ - + >>> r1 = repr(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f')))) >>> r1 "OrderedDict([('a', 'b'), ('c', 'd'), ('e', 'f')])" @@ -335,7 +353,7 @@ def __setitem__(self, key, val): >>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8))) >>> d OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)]) - + >>> a = OrderedDict(((0, 1), (1, 2), (2, 3)), strict=True) >>> a[3] = 4 >>> a @@ -359,18 +377,18 @@ def __setitem__(self, key, val): >>> a[::-1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) >>> a OrderedDict([(3, 4), (2, 3), (1, 2), (0, 1)]) - + >>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) >>> d[:1] = 3 Traceback (most recent call last): TypeError: slice assignment requires an OrderedDict - + >>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) >>> d[:1] = OrderedDict([(9, 8)]) >>> d OrderedDict([(9, 8), (1, 2), (2, 3), (3, 4)]) """ - if isinstance(key, slice): + if isinstance(key, types.SliceType): if not isinstance(val, OrderedDict): # FIXME: allow a list of tuples? raise TypeError('slice assignment requires an OrderedDict') @@ -430,7 +448,7 @@ def __getitem__(self, key): >>> type(b[2:4]) """ - if isinstance(key, slice): + if isinstance(key, types.SliceType): # FIXME: does this raise the error we want? keys = self._sequence[key] # FIXME: efficiency? @@ -458,7 +476,7 @@ def __setattr__(self, name, value): def __getattr__(self, name): """ Implemented so that access to ``sequence`` raises a warning. - + >>> d = OrderedDict() >>> d.sequence [] @@ -477,7 +495,7 @@ def __getattr__(self, name): def __deepcopy__(self, memo): """ To allow deepcopy to work with OrderedDict. - + >>> from copy import deepcopy >>> a = OrderedDict([(1, 1), (2, 2), (3, 3)]) >>> a['test'] = {} @@ -492,6 +510,7 @@ def __deepcopy__(self, memo): from copy import deepcopy return self.__class__(deepcopy(self.items(), memo), self.strict) + ### Read-only methods ### def copy(self): @@ -503,9 +522,9 @@ def copy(self): def items(self): """ - ``items`` returns a list of tuples representing all the + ``items`` returns a list of tuples representing all the ``(key, value)`` pairs in the dictionary. - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.items() [(1, 3), (3, 2), (2, 1)] @@ -518,7 +537,7 @@ def items(self): def keys(self): """ Return a list of keys in the ``OrderedDict``. - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.keys() [1, 3, 2] @@ -528,10 +547,10 @@ def keys(self): def values(self, values=None): """ Return a list of all the values in the OrderedDict. - + Optionally you can pass in a list of values, which will replace the current list. The value list must be the same len as the OrderedDict. - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.values() [3, 2, 1] @@ -609,7 +628,7 @@ def clear(self): def pop(self, key, *args): """ No dict.pop in Python 2.2, gotta reimplement it - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.pop(3) 2 @@ -625,7 +644,7 @@ def pop(self, key, *args): TypeError: pop expected at most 2 arguments, got 3 """ if len(args) > 1: - raise TypeError('pop expected at most 2 arguments, got %s' % + raise TypeError, ('pop expected at most 2 arguments, got %s' % (len(args) + 1)) if key in self: val = self[key] @@ -641,7 +660,7 @@ def popitem(self, i=-1): """ Delete and return an item specified by index, not a random one as in dict. The index is -1 by default (the last item). - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.popitem() (2, 1) @@ -664,7 +683,7 @@ def popitem(self, i=-1): raise IndexError('popitem(): index %s not valid' % i) return (key, self.pop(key)) - def setdefault(self, key, defval=None): + def setdefault(self, key, defval = None): """ >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.setdefault(1) @@ -687,7 +706,7 @@ def setdefault(self, key, defval=None): def update(self, from_od): """ Update from another OrderedDict or sequence of (key, value) pairs - + >>> d = OrderedDict(((1, 0), (0, 1))) >>> d.update(OrderedDict(((1, 3), (3, 2), (2, 1)))) >>> d @@ -719,11 +738,11 @@ def update(self, from_od): def rename(self, old_key, new_key): """ Rename the key for a given value, without modifying sequence order. - + For the case where new_key already exists this raise an exception, since if new_key exists, it is ambiguous as to what happens to the associated values, and the position of new_key in the sequence. - + >>> od = OrderedDict() >>> od['a'] = 1 >>> od['b'] = 2 @@ -745,7 +764,7 @@ def rename(self, old_key, new_key): if new_key in self: raise ValueError("New key already exists: %r" % new_key) # rename sequence entry - value = self[old_key] + value = self[old_key] old_idx = self._sequence.index(old_key) self._sequence[old_idx] = new_key # rename internal dict entry @@ -755,10 +774,10 @@ def rename(self, old_key, new_key): def setitems(self, items): """ This method allows you to set the items in the dict. - + It takes a list of tuples - of the same sort returned by the ``items`` method. - + >>> d = OrderedDict() >>> d.setitems(((3, 1), (2, 3), (1, 2))) >>> d @@ -773,10 +792,10 @@ def setkeys(self, keys): ``setkeys`` all ows you to pass in a new list of keys which will replace the current set. This must contain the same set of keys, but need not be in the same order. - + If you pass in new keys that don't match, a ``KeyError`` will be raised. - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.keys() [1, 3, 2] @@ -804,9 +823,9 @@ def setvalues(self, values): """ You can pass in a list of values, which will replace the current list. The value list must be the same len as the OrderedDict. - + (Or a ``ValueError`` is raised.) - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.setvalues((1, 2, 3)) >>> d @@ -826,23 +845,23 @@ def setvalues(self, values): def index(self, key): """ Return the position of the specified key in the OrderedDict. - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.index(3) 1 >>> d.index(4) Traceback (most recent call last): - ValueError: 4 is not in list + ValueError: list.index(x): x not in list """ return self._sequence.index(key) def insert(self, index, key, value): """ Takes ``index``, ``key``, and ``value`` as arguments. - + Sets ``key`` to ``value``, so that ``key`` is at position ``index`` in the OrderedDict. - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.insert(0, 4, 0) >>> d @@ -863,7 +882,7 @@ def insert(self, index, key, value): def reverse(self): """ Reverse the order of the OrderedDict. - + >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) >>> d.reverse() >>> d @@ -874,10 +893,10 @@ def reverse(self): def sort(self, *args, **kwargs): """ Sort the key order in the OrderedDict. - + This method takes the same arguments as the ``list.sort`` method on your version of Python. - + >>> d = OrderedDict(((4, 1), (2, 2), (3, 3), (1, 4))) >>> d.sort() >>> d @@ -885,8 +904,521 @@ def sort(self, *args, **kwargs): """ self._sequence.sort(*args, **kwargs) +class Keys(object): + # FIXME: should this object be a subclass of list? + """ + Custom object for accessing the keys of an OrderedDict. + + Can be called like the normal ``OrderedDict.keys`` method, but also + supports indexing and sequence methods. + """ + + def __init__(self, main): + self._main = main + + def __call__(self): + """Pretend to be the keys method.""" + return self._main._keys() + + def __getitem__(self, index): + """Fetch the key at position i.""" + # NOTE: this automatically supports slicing :-) + return self._main._sequence[index] + + def __setitem__(self, index, name): + """ + You cannot assign to keys, but you can do slice assignment to re-order + them. + + You can only do slice assignment if the new set of keys is a reordering + of the original set. + """ + if isinstance(index, types.SliceType): + # FIXME: efficiency? + # check length is the same + indexes = range(len(self._main._sequence))[index] + if len(indexes) != len(name): + raise ValueError('attempt to assign sequence of size %s ' + 'to slice of size %s' % (len(name), len(indexes))) + # check they are the same keys + # FIXME: Use set + old_keys = self._main._sequence[index] + new_keys = list(name) + old_keys.sort() + new_keys.sort() + if old_keys != new_keys: + raise KeyError('Keylist is not the same as current keylist.') + orig_vals = [self._main[k] for k in name] + del self._main[index] + vals = zip(indexes, name, orig_vals) + vals.sort() + for i, k, v in vals: + if self._main.strict and k in self._main: + raise ValueError('slice assignment must be from ' + 'unique keys') + self._main.insert(i, k, v) + else: + raise ValueError('Cannot assign to keys') + + ### following methods pinched from UserList and adapted ### + def __repr__(self): return repr(self._main._sequence) + + # FIXME: do we need to check if we are comparing with another ``Keys`` + # object? (like the __cast method of UserList) + def __lt__(self, other): return self._main._sequence < other + def __le__(self, other): return self._main._sequence <= other + def __eq__(self, other): return self._main._sequence == other + def __ne__(self, other): return self._main._sequence != other + def __gt__(self, other): return self._main._sequence > other + def __ge__(self, other): return self._main._sequence >= other + # FIXME: do we need __cmp__ as well as rich comparisons? + def __cmp__(self, other): return cmp(self._main._sequence, other) + + def __contains__(self, item): return item in self._main._sequence + def __len__(self): return len(self._main._sequence) + def __iter__(self): return self._main.iterkeys() + def count(self, item): return self._main._sequence.count(item) + def index(self, item, *args): return self._main._sequence.index(item, *args) + def reverse(self): self._main._sequence.reverse() + def sort(self, *args, **kwds): self._main._sequence.sort(*args, **kwds) + def __mul__(self, n): return self._main._sequence*n + __rmul__ = __mul__ + def __add__(self, other): return self._main._sequence + other + def __radd__(self, other): return other + self._main._sequence + + ## following methods not implemented for keys ## + def __delitem__(self, i): raise TypeError('Can\'t delete items from keys') + def __iadd__(self, other): raise TypeError('Can\'t add in place to keys') + def __imul__(self, n): raise TypeError('Can\'t multiply keys in place') + def append(self, item): raise TypeError('Can\'t append items to keys') + def insert(self, i, item): raise TypeError('Can\'t insert items into keys') + def pop(self, i=-1): raise TypeError('Can\'t pop items from keys') + def remove(self, item): raise TypeError('Can\'t remove items from keys') + def extend(self, other): raise TypeError('Can\'t extend keys') + +class Items(object): + """ + Custom object for accessing the items of an OrderedDict. + + Can be called like the normal ``OrderedDict.items`` method, but also + supports indexing and sequence methods. + """ + + def __init__(self, main): + self._main = main + + def __call__(self): + """Pretend to be the items method.""" + return self._main._items() + + def __getitem__(self, index): + """Fetch the item at position i.""" + if isinstance(index, types.SliceType): + # fetching a slice returns an OrderedDict + return self._main[index].items() + key = self._main._sequence[index] + return (key, self._main[key]) + + def __setitem__(self, index, item): + """Set item at position i to item.""" + if isinstance(index, types.SliceType): + # NOTE: item must be an iterable (list of tuples) + self._main[index] = OrderedDict(item) + else: + # FIXME: Does this raise a sensible error? + orig = self._main.keys[index] + key, value = item + if self._main.strict and key in self and (key != orig): + raise ValueError('slice assignment must be from ' + 'unique keys') + # delete the current one + del self._main[self._main._sequence[index]] + self._main.insert(index, key, value) + + def __delitem__(self, i): + """Delete the item at position i.""" + key = self._main._sequence[i] + if isinstance(i, types.SliceType): + for k in key: + # FIXME: efficiency? + del self._main[k] + else: + del self._main[key] + + ### following methods pinched from UserList and adapted ### + def __repr__(self): return repr(self._main.items()) + + # FIXME: do we need to check if we are comparing with another ``Items`` + # object? (like the __cast method of UserList) + def __lt__(self, other): return self._main.items() < other + def __le__(self, other): return self._main.items() <= other + def __eq__(self, other): return self._main.items() == other + def __ne__(self, other): return self._main.items() != other + def __gt__(self, other): return self._main.items() > other + def __ge__(self, other): return self._main.items() >= other + def __cmp__(self, other): return cmp(self._main.items(), other) + + def __contains__(self, item): return item in self._main.items() + def __len__(self): return len(self._main._sequence) # easier :-) + def __iter__(self): return self._main.iteritems() + def count(self, item): return self._main.items().count(item) + def index(self, item, *args): return self._main.items().index(item, *args) + def reverse(self): self._main.reverse() + def sort(self, *args, **kwds): self._main.sort(*args, **kwds) + def __mul__(self, n): return self._main.items()*n + __rmul__ = __mul__ + def __add__(self, other): return self._main.items() + other + def __radd__(self, other): return other + self._main.items() + + def append(self, item): + """Add an item to the end.""" + # FIXME: this is only append if the key isn't already present + key, value = item + self._main[key] = value + + def insert(self, i, item): + key, value = item + self._main.insert(i, key, value) + + def pop(self, i=-1): + key = self._main._sequence[i] + return (key, self._main.pop(key)) + + def remove(self, item): + key, value = item + try: + assert value == self._main[key] + except (KeyError, AssertionError): + raise ValueError('ValueError: list.remove(x): x not in list') + else: + del self._main[key] + + def extend(self, other): + # FIXME: is only a true extend if none of the keys already present + for item in other: + key, value = item + self._main[key] = value + + def __iadd__(self, other): + self.extend(other) + + ## following methods not implemented for items ## + + def __imul__(self, n): raise TypeError('Can\'t multiply items in place') + +class Values(object): + """ + Custom object for accessing the values of an OrderedDict. + + Can be called like the normal ``OrderedDict.values`` method, but also + supports indexing and sequence methods. + """ + + def __init__(self, main): + self._main = main + + def __call__(self): + """Pretend to be the values method.""" + return self._main._values() + + def __getitem__(self, index): + """Fetch the value at position i.""" + if isinstance(index, types.SliceType): + return [self._main[key] for key in self._main._sequence[index]] + else: + return self._main[self._main._sequence[index]] + + def __setitem__(self, index, value): + """ + Set the value at position i to value. + + You can only do slice assignment to values if you supply a sequence of + equal length to the slice you are replacing. + """ + if isinstance(index, types.SliceType): + keys = self._main._sequence[index] + if len(keys) != len(value): + raise ValueError('attempt to assign sequence of size %s ' + 'to slice of size %s' % (len(name), len(keys))) + # FIXME: efficiency? Would be better to calculate the indexes + # directly from the slice object + # NOTE: the new keys can collide with existing keys (or even + # contain duplicates) - these will overwrite + for key, val in zip(keys, value): + self._main[key] = val + else: + self._main[self._main._sequence[index]] = value + + ### following methods pinched from UserList and adapted ### + def __repr__(self): return repr(self._main.values()) + + # FIXME: do we need to check if we are comparing with another ``Values`` + # object? (like the __cast method of UserList) + def __lt__(self, other): return self._main.values() < other + def __le__(self, other): return self._main.values() <= other + def __eq__(self, other): return self._main.values() == other + def __ne__(self, other): return self._main.values() != other + def __gt__(self, other): return self._main.values() > other + def __ge__(self, other): return self._main.values() >= other + def __cmp__(self, other): return cmp(self._main.values(), other) + + def __contains__(self, item): return item in self._main.values() + def __len__(self): return len(self._main._sequence) # easier :-) + def __iter__(self): return self._main.itervalues() + def count(self, item): return self._main.values().count(item) + def index(self, item, *args): return self._main.values().index(item, *args) + + def reverse(self): + """Reverse the values""" + vals = self._main.values() + vals.reverse() + # FIXME: efficiency + self[:] = vals + + def sort(self, *args, **kwds): + """Sort the values.""" + vals = self._main.values() + vals.sort(*args, **kwds) + self[:] = vals + + def __mul__(self, n): return self._main.values()*n + __rmul__ = __mul__ + def __add__(self, other): return self._main.values() + other + def __radd__(self, other): return other + self._main.values() + + ## following methods not implemented for values ## + def __delitem__(self, i): raise TypeError('Can\'t delete items from values') + def __iadd__(self, other): raise TypeError('Can\'t add in place to values') + def __imul__(self, n): raise TypeError('Can\'t multiply values in place') + def append(self, item): raise TypeError('Can\'t append items to values') + def insert(self, i, item): raise TypeError('Can\'t insert items into values') + def pop(self, i=-1): raise TypeError('Can\'t pop items from values') + def remove(self, item): raise TypeError('Can\'t remove items from values') + def extend(self, other): raise TypeError('Can\'t extend values') + +class SequenceOrderedDict(OrderedDict): + """ + Experimental version of OrderedDict that has a custom object for ``keys``, + ``values``, and ``items``. + + These are callable sequence objects that work as methods, or can be + manipulated directly as sequences. + + Test for ``keys``, ``items`` and ``values``. + + >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4))) + >>> d + SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) + >>> d.keys + [1, 2, 3] + >>> d.keys() + [1, 2, 3] + >>> d.setkeys((3, 2, 1)) + >>> d + SequenceOrderedDict([(3, 4), (2, 3), (1, 2)]) + >>> d.setkeys((1, 2, 3)) + >>> d.keys[0] + 1 + >>> d.keys[:] + [1, 2, 3] + >>> d.keys[-1] + 3 + >>> d.keys[-2] + 2 + >>> d.keys[0:2] = [2, 1] + >>> d + SequenceOrderedDict([(2, 3), (1, 2), (3, 4)]) + >>> d.keys.reverse() + >>> d.keys + [3, 1, 2] + >>> d.keys = [1, 2, 3] + >>> d + SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) + >>> d.keys = [3, 1, 2] + >>> d + SequenceOrderedDict([(3, 4), (1, 2), (2, 3)]) + >>> a = SequenceOrderedDict() + >>> b = SequenceOrderedDict() + >>> a.keys == b.keys + 1 + >>> a['a'] = 3 + >>> a.keys == b.keys + 0 + >>> b['a'] = 3 + >>> a.keys == b.keys + 1 + >>> b['b'] = 3 + >>> a.keys == b.keys + 0 + >>> a.keys > b.keys + 0 + >>> a.keys < b.keys + 1 + >>> 'a' in a.keys + 1 + >>> len(b.keys) + 2 + >>> 'c' in d.keys + 0 + >>> 1 in d.keys + 1 + >>> [v for v in d.keys] + [3, 1, 2] + >>> d.keys.sort() + >>> d.keys + [1, 2, 3] + >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4)), strict=True) + >>> d.keys[::-1] = [1, 2, 3] + >>> d + SequenceOrderedDict([(3, 4), (2, 3), (1, 2)]) + >>> d.keys[:2] + [3, 2] + >>> d.keys[:2] = [1, 3] + Traceback (most recent call last): + KeyError: 'Keylist is not the same as current keylist.' + + >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4))) + >>> d + SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) + >>> d.values + [2, 3, 4] + >>> d.values() + [2, 3, 4] + >>> d.setvalues((4, 3, 2)) + >>> d + SequenceOrderedDict([(1, 4), (2, 3), (3, 2)]) + >>> d.values[::-1] + [2, 3, 4] + >>> d.values[0] + 4 + >>> d.values[-2] + 3 + >>> del d.values[0] + Traceback (most recent call last): + TypeError: Can't delete items from values + >>> d.values[::2] = [2, 4] + >>> d + SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) + >>> 7 in d.values + 0 + >>> len(d.values) + 3 + >>> [val for val in d.values] + [2, 3, 4] + >>> d.values[-1] = 2 + >>> d.values.count(2) + 2 + >>> d.values.index(2) + 0 + >>> d.values[-1] = 7 + >>> d.values + [2, 3, 7] + >>> d.values.reverse() + >>> d.values + [7, 3, 2] + >>> d.values.sort() + >>> d.values + [2, 3, 7] + >>> d.values.append('anything') + Traceback (most recent call last): + TypeError: Can't append items to values + >>> d.values = (1, 2, 3) + >>> d + SequenceOrderedDict([(1, 1), (2, 2), (3, 3)]) + + >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4))) + >>> d + SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) + >>> d.items() + [(1, 2), (2, 3), (3, 4)] + >>> d.setitems([(3, 4), (2 ,3), (1, 2)]) + >>> d + SequenceOrderedDict([(3, 4), (2, 3), (1, 2)]) + >>> d.items[0] + (3, 4) + >>> d.items[:-1] + [(3, 4), (2, 3)] + >>> d.items[1] = (6, 3) + >>> d.items + [(3, 4), (6, 3), (1, 2)] + >>> d.items[1:2] = [(9, 9)] + >>> d + SequenceOrderedDict([(3, 4), (9, 9), (1, 2)]) + >>> del d.items[1:2] + >>> d + SequenceOrderedDict([(3, 4), (1, 2)]) + >>> (3, 4) in d.items + 1 + >>> (4, 3) in d.items + 0 + >>> len(d.items) + 2 + >>> [v for v in d.items] + [(3, 4), (1, 2)] + >>> d.items.count((3, 4)) + 1 + >>> d.items.index((1, 2)) + 1 + >>> d.items.index((2, 1)) + Traceback (most recent call last): + ValueError: list.index(x): x not in list + >>> d.items.reverse() + >>> d.items + [(1, 2), (3, 4)] + >>> d.items.reverse() + >>> d.items.sort() + >>> d.items + [(1, 2), (3, 4)] + >>> d.items.append((5, 6)) + >>> d.items + [(1, 2), (3, 4), (5, 6)] + >>> d.items.insert(0, (0, 0)) + >>> d.items + [(0, 0), (1, 2), (3, 4), (5, 6)] + >>> d.items.insert(-1, (7, 8)) + >>> d.items + [(0, 0), (1, 2), (3, 4), (7, 8), (5, 6)] + >>> d.items.pop() + (5, 6) + >>> d.items + [(0, 0), (1, 2), (3, 4), (7, 8)] + >>> d.items.remove((1, 2)) + >>> d.items + [(0, 0), (3, 4), (7, 8)] + >>> d.items.extend([(1, 2), (5, 6)]) + >>> d.items + [(0, 0), (3, 4), (7, 8), (1, 2), (5, 6)] + """ + + def __init__(self, init_val=(), strict=True): + OrderedDict.__init__(self, init_val, strict=strict) + self._keys = self.keys + self._values = self.values + self._items = self.items + self.keys = Keys(self) + self.values = Values(self) + self.items = Items(self) + self._att_dict = { + 'keys': self.setkeys, + 'items': self.setitems, + 'values': self.setvalues, + } + + def __setattr__(self, name, value): + """Protect keys, items, and values.""" + if not '_att_dict' in self.__dict__: + object.__setattr__(self, name, value) + else: + try: + fun = self._att_dict[name] + except KeyError: + OrderedDict.__setattr__(self, name, value) + else: + fun(value) if __name__ == '__main__': + if INTP_VER < (2, 3): + raise RuntimeError("Tests require Python v.2.3 or later") # turn off warnings for tests warnings.filterwarnings('ignore') # run the code tests in doctest format diff --git a/editorconfig-core-py/editorconfig/versiontools.py b/editorconfig-core-py/editorconfig/versiontools.py index 01744f8..ccfa388 100644 --- a/editorconfig-core-py/editorconfig/versiontools.py +++ b/editorconfig-core-py/editorconfig/versiontools.py @@ -18,7 +18,7 @@ def join_version(version_tuple): """Return a string representation of version from given VERSION tuple""" version = "%s.%s.%s" % version_tuple[:3] if version_tuple[3] != "final": - version += "-%s" % version_tuple[3] + version += ".%s" % version_tuple[3] return version @@ -31,5 +31,5 @@ def split_version(version): split_version = list(match.groups()) if split_version[3] is None: split_version[3] = "final" - split_version = list(map(int, split_version[:3])) + split_version[3:] + split_version = map(int, split_version[:3]) + split_version[3:] return tuple(split_version) diff --git a/editorconfig-core-py/java-binding/.editorconfig b/editorconfig-core-py/java-binding/.editorconfig deleted file mode 100644 index 7eb4e00..0000000 --- a/editorconfig-core-py/java-binding/.editorconfig +++ /dev/null @@ -1,9 +0,0 @@ -[*.java] -indent_style = space -indent_size = 4 -end_of_line = LF - -[*.xml] -indent_style = space -indent_size = 2 -end_of_line = LF diff --git a/editorconfig-core-py/java-binding/.gitignore b/editorconfig-core-py/java-binding/.gitignore deleted file mode 100644 index 43e4bfe..0000000 --- a/editorconfig-core-py/java-binding/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.class -/classes -/build -/tmp -/doc diff --git a/editorconfig-core-py/java-binding/LICENSE.txt b/editorconfig-core-py/java-binding/LICENSE.txt deleted file mode 100644 index e1f2cbd..0000000 --- a/editorconfig-core-py/java-binding/LICENSE.txt +++ /dev/null @@ -1,192 +0,0 @@ -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby -grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, -analyze, test, perform and/or display publicly, prepare derivative works, -distribute, and otherwise use Python alone or in any derivative version, -provided, however, that PSF's License Agreement and PSF's notice of copyright, -i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 -Python Software Foundation; All Rights Reserved" are retained in Python alone or -in any derivative version prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 -------------------------------------------- - -BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 - -1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an -office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the -Individual or Organization ("Licensee") accessing and otherwise using -this software in source or binary form and its associated -documentation ("the Software"). - -2. Subject to the terms and conditions of this BeOpen Python License -Agreement, BeOpen hereby grants Licensee a non-exclusive, -royalty-free, world-wide license to reproduce, analyze, test, perform -and/or display publicly, prepare derivative works, distribute, and -otherwise use the Software alone or in any derivative version, -provided, however, that the BeOpen Python License is retained in the -Software, alone or in any derivative version prepared by Licensee. - -3. BeOpen is making the Software available to Licensee on an "AS IS" -basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE -SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS -AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY -DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -5. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -6. This License Agreement shall be governed by and interpreted in all -respects by the law of the State of California, excluding conflict of -law provisions. Nothing in this License Agreement shall be deemed to -create any relationship of agency, partnership, or joint venture -between BeOpen and Licensee. This License Agreement does not grant -permission to use BeOpen trademarks or trade names in a trademark -sense to endorse or promote products or services of Licensee, or any -third party. As an exception, the "BeOpen Python" logos available at -http://www.pythonlabs.com/logos.html may be used according to the -permissions granted on that web page. - -7. By copying, installing or otherwise using the software, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 ---------------------------------------- - -1. This LICENSE AGREEMENT is between the Corporation for National -Research Initiatives, having an office at 1895 Preston White Drive, -Reston, VA 20191 ("CNRI"), and the Individual or Organization -("Licensee") accessing and otherwise using Python 1.6.1 software in -source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, CNRI -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use Python 1.6.1 -alone or in any derivative version, provided, however, that CNRI's -License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) -1995-2001 Corporation for National Research Initiatives; All Rights -Reserved" are retained in Python 1.6.1 alone or in any derivative -version prepared by Licensee. Alternately, in lieu of CNRI's License -Agreement, Licensee may substitute the following text (omitting the -quotes): "Python 1.6.1 is made available subject to the terms and -conditions in CNRI's License Agreement. This Agreement together with -Python 1.6.1 may be located on the Internet using the following -unique, persistent identifier (known as a handle): 1895.22/1013. This -Agreement may also be obtained from a proxy server on the Internet -using the following URL: http://hdl.handle.net/1895.22/1013". - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python 1.6.1 or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python 1.6.1. - -4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" -basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. This License Agreement shall be governed by the federal -intellectual property law of the United States, including without -limitation the federal copyright law, and, to the extent such -U.S. federal law does not apply, by the law of the Commonwealth of -Virginia, excluding Virginia's conflict of law provisions. -Notwithstanding the foregoing, with regard to derivative works based -on Python 1.6.1 that incorporate non-separable material that was -previously distributed under the GNU General Public License (GPL), the -law of the Commonwealth of Virginia shall govern this License -Agreement only as to issues arising under or with respect to -Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this -License Agreement shall be deemed to create any relationship of -agency, partnership, or joint venture between CNRI and Licensee. This -License Agreement does not grant permission to use CNRI trademarks or -trade name in a trademark sense to endorse or promote products or -services of Licensee, or any third party. - -8. By clicking on the "ACCEPT" button where indicated, or by copying, -installing or otherwise using Python 1.6.1, Licensee agrees to be -bound by the terms and conditions of this License Agreement. - - ACCEPT - - -CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 --------------------------------------------------- - -Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, -The Netherlands. All rights reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/editorconfig-core-py/java-binding/README.md b/editorconfig-core-py/java-binding/README.md deleted file mode 100644 index a6a82c0..0000000 --- a/editorconfig-core-py/java-binding/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# EditorConfig Java Binding - -This directory is for [EditorConfig][] Core Java Binding. This binding is a -Java wrapper for [EditorConfig Python Core][], made possible by [Jython][]. - -## EditorConfig Project - -EditorConfig makes it easy to maintain the correct coding style when switching -between different text editors and between different projects. The -EditorConfig project maintains a file format and plugins for various text -editors which allow this file format to be read and used by those editors. For -information on the file format and supported text editors, see the -[EditorConfig website][EditorConfig]. - -## Build the Library and Generate the Doc - -With [Ant][]: - - cd /path/to/editorconfig-core-py/java-binding - ant && ant doc - -The built jar file is in the `build` directory and the documentation is in the -`doc` directory. - -## Use as a Library - -A basic example: - -```java -EditorConfig ec = new EditorConfig(); -List l = null; -try { - l = ec.getProperties("/home/user/src/editorconfig-core-py/a.py"); -} catch(EditorConfigException e) { - System.out.println(e); - System.exit(1); -} - -for(int i = 0; i < l.size(); ++i) { - System.out.println(l.get(i).getKey() + "=" + l.get(i).getVal()); -} -``` - -A more complex example is in the `example` directory. There is an -[online documentation][] for API details, or you could run `ant doc` to -generate html documentation. The generated documentation will locate in `doc` -directory. - -## License - -All source files of the Java binding are distributed under the PSF license. See -LICENSE.txt for details. - -Copyright (C) 2012, EditorConfig Team - -[Ant]: http://ant.apache.org -[EditorConfig Python Core]: https://github.com/editorconfig/editorconfig-core-py -[EditorConfig]: http://editorconfig.org -[Jython]: http://www.jython.org -[online documentation]: http://javadocs.editorconfig.org diff --git a/editorconfig-core-py/java-binding/build.xml b/editorconfig-core-py/java-binding/build.xml deleted file mode 100644 index 148b643..0000000 --- a/editorconfig-core-py/java-binding/build.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/editorconfig-core-py/java-binding/example/TestEditorConfig.java b/editorconfig-core-py/java-binding/example/TestEditorConfig.java deleted file mode 100644 index 2a235f8..0000000 --- a/editorconfig-core-py/java-binding/example/TestEditorConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -import javax.script.ScriptEngine; -import javax.script.ScriptEngineFactory; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; -import java.util.List; -import org.editorconfig.core.*; - -public class TestEditorConfig { - public static void main(String[] args) throws EditorConfigException { - EditorConfig ec = new EditorConfig(); - List l = null; - try { - l = ec.getProperties(System.getProperty("user.dir") + "/a.py"); - } catch(EditorConfigException e) { - System.out.println(e); - System.exit(1); - } - - for(int i = 0; i < l.size(); ++i) { - System.out.println(l.get(i).getKey() + "=" + l.get(i).getVal()); - } - } -} diff --git a/editorconfig-core-py/java-binding/example/test-example.bat b/editorconfig-core-py/java-binding/example/test-example.bat deleted file mode 100644 index bba5993..0000000 --- a/editorconfig-core-py/java-binding/example/test-example.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off - -SETLOCAL - -set LOCAL_CLASSPATH="../build/editorconfig.jar;.;%CLASSPATH%" -javac -cp %LOCAL_CLASSPATH% TestEditorConfig.java -java -cp %LOCAL_CLASSPATH% TestEditorConfig - -ENDLOCAL diff --git a/editorconfig-core-py/java-binding/example/test-example.sh b/editorconfig-core-py/java-binding/example/test-example.sh deleted file mode 100755 index 25fbe95..0000000 --- a/editorconfig-core-py/java-binding/example/test-example.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -CLASSPATH="../build/editorconfig.jar:.:$CLASSPATH" -javac -cp $CLASSPATH TestEditorConfig.java -java -cp $CLASSPATH TestEditorConfig diff --git a/editorconfig-core-py/java-binding/src/org/editorconfig/core/EditorConfig.java b/editorconfig-core-py/java-binding/src/org/editorconfig/core/EditorConfig.java deleted file mode 100644 index 87870b0..0000000 --- a/editorconfig-core-py/java-binding/src/org/editorconfig/core/EditorConfig.java +++ /dev/null @@ -1,155 +0,0 @@ -package org.editorconfig.core; - -import java.util.LinkedList; -import java.util.List; -import org.python.core.Py; -import org.python.core.PyString; -import org.python.core.PySystemState; -import org.python.util.PythonInterpreter; - -/** - * EditorConfig handler - */ -public class EditorConfig { - - private PythonInterpreter pyInterp; - - /** - * String-String pair to store the parsing result. - */ - public class OutPair { - private String key; - private String val; - - /* - * Constructor - */ - OutPair(String key, String val) { - this.key = key; - this.val = val; - } - - /** - * Return the key of the current pair. - */ - public String getKey() { - return this.key; - } - - /** - * Return the value of the current pair. - */ - public String getVal() { - return this.val; - } - } - - /** - * EditorConfig constructor. - * - * @throws PythonException If a Jython exception happens. - * - * @see #EditorConfig(List) - */ - public EditorConfig() - throws PythonException { - - this(null); - - - } - - /** - * EditorConfig constructor. - * - * Same as {@link #EditorConfig()}, but with an additional parameter - * {@code jarLocations}. - * - * @param jarLocations The possible locations of {@code editorconfig.jar} - * file. This parameter is used in some cases, {@code editorconfig.jar} - * cannot locate itself (e.g. java program launched in GNOME desktop - * environment may have this kind of issue). However, some modules are - * packed in {@code editorconfig.jar} file, so this file must be located - * for this library to work correctly. - * - * @see #EditorConfig() - */ - public EditorConfig(List jarLocations) - throws PythonException { - pyInterp = new PythonInterpreter(null, new PySystemState()); - PySystemState pySysStat = Py.getSystemState(); - - // Add all "jarLocations/Lib" to sys.path - if(jarLocations != null) - for(String jarPath : jarLocations) - pySysStat.path.append(new PyString(jarPath + "/Lib")); - - pyInterp.exec("from editorconfig import get_properties"); - pyInterp.exec("from editorconfig import exceptions"); - } - - /** - * Parse editorconfig files corresponding to the file path given by - * filename, and return the parsing result. - * - * @param filename The full path to be parsed. The path is usually the path - * of the file which is currently edited by the editor. - * - * @return The parsing result stored in a list of {@link - * EditorConfig.OutPair}. - * - * @throws org.editorconfig.core.ParsingException If an - * {@code .editorconfig} file could not be parsed - * - * @throws org.editorconfig.core.PathException If an invalid file path is - * specified as {@code filename} - * - * @throws org.editorconfig.core.EditorConfigException If an EditorConfig - * exception occurs. Usually one of {@link ParsingException} or {@link - * PathException}. - * - * @throws org.editorconfig.core.PythonException If a Jython exception happens. - * - */ - public List getProperties(String filename) - throws EditorConfigException { - - pyInterp.exec("try:\n" + - "\toptions = get_properties(r\"\"\"" + filename + "\"\"\")\n" + - "except exceptions.ParsingError:\n" + - "\te = 'ParsingError'\n" + - "except exceptions.PathError:\n" + - "\te = 'PathError'\n" + - "except exceptions.VersionError:\n" + - "\te = 'VersionError'\n" + - "except exceptions.EditorConfigError:\n" + - "\te = 'EditorConfigError'\n" + - "else:\n" + - "\te = 'None'"); - - String except = pyInterp.get("e").toString(); - if(except.equals("ParsingError")) - throw new ParsingException("Failed to parse .editorconfig file."); - else if(except.equals("PathError")) - throw new PathException("Invalid file name specified. Must be absolute path."); - else if(except.equals("VersionError")) - throw new VersionException("Invalid Version Specified."); - - pyInterp.exec("option_count = len(options)"); - pyInterp.exec("option_items = options.items()"); - - LinkedList retList = new LinkedList(); - int count = Integer.parseInt(pyInterp.get("option_count").toString()); - for(int i = 0; i < count; ++i) { - pyInterp.exec("option_key = option_items[" + i + "][0]"); - pyInterp.exec("option_item = option_items[" + i + "][1]"); - OutPair op = new OutPair( - pyInterp.get("option_key").toString(), - pyInterp.get("option_item").toString()); - - retList.add(op); - } - - return retList; - } -} diff --git a/editorconfig-core-py/java-binding/src/org/editorconfig/core/EditorConfigException.java b/editorconfig-core-py/java-binding/src/org/editorconfig/core/EditorConfigException.java deleted file mode 100644 index b968ff7..0000000 --- a/editorconfig-core-py/java-binding/src/org/editorconfig/core/EditorConfigException.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.editorconfig.core; - - -/** - * The base class of all EditorConfig exceptions. - */ -abstract public class EditorConfigException extends Exception { - EditorConfigException(String msg) { - super(msg); - } -} diff --git a/editorconfig-core-py/java-binding/src/org/editorconfig/core/ParsingException.java b/editorconfig-core-py/java-binding/src/org/editorconfig/core/ParsingException.java deleted file mode 100644 index d44b81b..0000000 --- a/editorconfig-core-py/java-binding/src/org/editorconfig/core/ParsingException.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.editorconfig.core; - -/** - * Exception throwed by {@link EditorConfig#getProperties(String)} if an - * EditorConfig file could not be parsed - */ -public class ParsingException extends EditorConfigException { - - ParsingException(String msg) { - super(msg); - } -} diff --git a/editorconfig-core-py/java-binding/src/org/editorconfig/core/PathException.java b/editorconfig-core-py/java-binding/src/org/editorconfig/core/PathException.java deleted file mode 100644 index 13ba7c6..0000000 --- a/editorconfig-core-py/java-binding/src/org/editorconfig/core/PathException.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.editorconfig.core; - - -/** - * Exception throwed by {@link EditorConfig#getProperties(String)} if an - * invalid file path is specified - */ -public class PathException extends EditorConfigException { - - PathException(String msg) { - super(msg); - } -} diff --git a/editorconfig-core-py/java-binding/src/org/editorconfig/core/PythonException.java b/editorconfig-core-py/java-binding/src/org/editorconfig/core/PythonException.java deleted file mode 100644 index 737f7cb..0000000 --- a/editorconfig-core-py/java-binding/src/org/editorconfig/core/PythonException.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.editorconfig.core; - - -/** - * Exception throwed by {@link EditorConfig#EditorConfig()} if an exception - * from the internal Python interpreter (Jython) is thrown - */ -public class PythonException extends EditorConfigException { - - PythonException(String msg) { - super(msg); - } -} diff --git a/editorconfig-core-py/java-binding/src/org/editorconfig/core/VersionException.java b/editorconfig-core-py/java-binding/src/org/editorconfig/core/VersionException.java deleted file mode 100644 index 4905cc8..0000000 --- a/editorconfig-core-py/java-binding/src/org/editorconfig/core/VersionException.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.editorconfig.core; - -/** - * Exception throwed by {@link EditorConfig#getProperties(String)} if an - * invalid version number is specified - */ -public class VersionException extends EditorConfigException { - - VersionException(String msg) { - super(msg); - } -} diff --git a/editorconfig-core-py/java-binding/src/org/editorconfig/core/package-info.java b/editorconfig-core-py/java-binding/src/org/editorconfig/core/package-info.java deleted file mode 100644 index 9c2ae54..0000000 --- a/editorconfig-core-py/java-binding/src/org/editorconfig/core/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Provides the Java API for accessing - * EditorConfig Core - * (For the purpose and usage of EditorConfig, see - * EditorConfig homepage for details). - */ - -package org.editorconfig.core; diff --git a/editorconfig-core-py/setup.py b/editorconfig-core-py/setup.py index 9b34145..1d29c33 100644 --- a/editorconfig-core-py/setup.py +++ b/editorconfig-core-py/setup.py @@ -6,6 +6,7 @@ version=editorconfig.__version__, author='EditorConfig Team', packages=['editorconfig'], + namespace_packages=['editorconfig'], url='http://editorconfig.org/', license='LICENSE.txt', description='EditorConfig File Locator and Interpreter for Python', diff --git a/editorconfig-core-py/tests b/editorconfig-core-py/tests index abbd614..5dd1bf9 160000 --- a/editorconfig-core-py/tests +++ b/editorconfig-core-py/tests @@ -1 +1 @@ -Subproject commit abbd6142bb1f852fa654c477b067bee1f0f00330 +Subproject commit 5dd1bf93ef286aaf58f53cc6c8bbef495018275d