├── .editorconfig ├── .github └── workflows │ └── runtime.yml ├── .gitignore ├── .gitmodules ├── .travis.yml ├── CMakeLists.txt ├── COPYING ├── LICENSE.BSD ├── LICENSE.PSF ├── MANIFEST.in ├── README.rst ├── docs ├── Makefile ├── command_line_usage.rst ├── conf.py ├── index.rst ├── make.bat ├── plugins.rst └── usage.rst ├── editorconfig ├── __init__.py ├── __main__.py ├── compat.py ├── exceptions.py ├── fnmatch.py ├── handler.py ├── ini.py ├── version.py └── versiontools.py ├── pyproject.toml ├── renovate.json └── setup.py /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{py,rst,txt}] 4 | indent_style = space 5 | trim_trailing_whitespace = true 6 | indent_size = 4 7 | end_of_line = LF 8 | 9 | [*.yml] 10 | indent_style = space 11 | indent_size = 2 12 | end_of_line = LF 13 | -------------------------------------------------------------------------------- /.github/workflows/runtime.yml: -------------------------------------------------------------------------------- 1 | # Runtime tests 2 | 3 | name: Runtime 4 | 5 | on: 6 | push: 7 | branches: ["master"] 8 | pull_request: 9 | branches: ["master"] 10 | 11 | jobs: 12 | test: 13 | name: Runtime 14 | runs-on: ubuntu-latest 15 | container: python:3.13-alpine3.21 16 | 17 | steps: 18 | - name: Install Alpine Dependencies 19 | run: apk add cmake git make 20 | - name: Display Python version 21 | run: python -c "import sys; print(sys.version)" 22 | - name: Display CMake version 23 | run: cmake --version 24 | - name: Display Git version 25 | run: git --version 26 | 27 | - uses: actions/checkout@v4 28 | with: 29 | submodules: recursive 30 | 31 | - name: Install Dependencies 32 | run: pip install -e . 33 | - name: Test 34 | run: cmake . && ctest -VV . 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | *\$py.class 3 | *.egg-info 4 | dist 5 | build 6 | /Testing 7 | /Makefile 8 | /tests/Makefile 9 | *.cmake 10 | CMakeFiles 11 | CMakeCache.txt 12 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tests"] 2 | path = tests 3 | url = https://github.com/editorconfig/editorconfig-core-test.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - "3.8" 5 | - "3.9" 6 | - "3.10" 7 | - "3.11" 8 | - "3.12" 9 | - "pypy" 10 | 11 | 12 | # test script 13 | before_script: 14 | - cmake . 15 | script: 16 | - export PYTHONPATH=$(pwd) 17 | - ctest -VV --output-on-failure . 18 | 19 | addons: 20 | apt: 21 | packages: 22 | - cmake 23 | 24 | 25 | # Notify the mailing list 26 | notifications: 27 | email: 28 | on_success: change 29 | on_failure: always 30 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file is used for testing only 2 | 3 | # To perform the test, run `cmake .` at the root of the project tree followed 4 | # by ctest . 5 | 6 | cmake_minimum_required(VERSION 3.16.3) 7 | 8 | # Do not check any compiler 9 | project(editorconfig-core-py NONE) 10 | 11 | find_package(PythonInterp) 12 | 13 | if(NOT PYTHONINTERP_FOUND) 14 | message(FATAL_ERROR 15 | "Python interpreter is not found. If you have python installed, please run: 16 | cmake -DPYTHON_EXECUTABLE=/path/to/python .") 17 | endif() 18 | 19 | enable_testing() 20 | set(EDITORCONFIG_CMD ${PYTHON_EXECUTABLE} -m editorconfig) 21 | add_subdirectory(tests) 22 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2018 EditorConfig Team, including Hong Xu and Trey Hunner 2 | 3 | editorconfig-core-py is free software. You are free to copy, 4 | modify, and/or redistribute this work under the terms of the BSD 5 | 2-clause license. See the file "LICENSE.BSD" for details. 6 | 7 | Parts of this work – the files "fnmatch.py" and "ini.py" - 8 | are derived from work with copyright held by the Python Software 9 | Foundation. You are free to copy, modify, and/or redistribute 10 | those parts under the terms of the Python Software Foundation 11 | license. See the file "LICENSE.PSF" for details. 12 | -------------------------------------------------------------------------------- /LICENSE.BSD: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2018 EditorConfig Team, including Hong Xu and Trey Hunner 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright notice, 9 | this list of conditions and the following disclaimer in the documentation 10 | and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 13 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 16 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 18 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 19 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 20 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 21 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 22 | POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /LICENSE.PSF: -------------------------------------------------------------------------------- 1 | PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 2 | -------------------------------------------- 3 | 4 | 1. This LICENSE AGREEMENT is between the Python Software Foundation 5 | ("PSF"), and the Individual or Organization ("Licensee") accessing and 6 | otherwise using this software ("Python") in source or binary form and 7 | its associated documentation. 8 | 9 | 2. Subject to the terms and conditions of this License Agreement, PSF hereby 10 | grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, 11 | analyze, test, perform and/or display publicly, prepare derivative works, 12 | distribute, and otherwise use Python alone or in any derivative version, 13 | provided, however, that PSF's License Agreement and PSF's notice of copyright, 14 | i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 15 | Python Software Foundation; All Rights Reserved" are retained in Python alone or 16 | in any derivative version prepared by Licensee. 17 | 18 | 3. In the event Licensee prepares a derivative work that is based on 19 | or incorporates Python or any part thereof, and wants to make 20 | the derivative work available to others as provided herein, then 21 | Licensee hereby agrees to include in any such work a brief summary of 22 | the changes made to Python. 23 | 24 | 4. PSF is making Python available to Licensee on an "AS IS" 25 | basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR 26 | IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND 27 | DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS 28 | FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT 29 | INFRINGE ANY THIRD PARTY RIGHTS. 30 | 31 | 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 32 | FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS 33 | A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, 34 | OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 35 | 36 | 6. This License Agreement will automatically terminate upon a material 37 | breach of its terms and conditions. 38 | 39 | 7. Nothing in this License Agreement shall be deemed to create any 40 | relationship of agency, partnership, or joint venture between PSF and 41 | Licensee. This License Agreement does not grant permission to use PSF 42 | trademarks or trade name in a trademark sense to endorse or promote 43 | products or services of Licensee, or any third party. 44 | 45 | 8. By copying, installing or otherwise using Python, Licensee 46 | agrees to be bound by the terms and conditions of this License 47 | Agreement. 48 | 49 | 50 | BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 51 | ------------------------------------------- 52 | 53 | BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 54 | 55 | 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an 56 | office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the 57 | Individual or Organization ("Licensee") accessing and otherwise using 58 | this software in source or binary form and its associated 59 | documentation ("the Software"). 60 | 61 | 2. Subject to the terms and conditions of this BeOpen Python License 62 | Agreement, BeOpen hereby grants Licensee a non-exclusive, 63 | royalty-free, world-wide license to reproduce, analyze, test, perform 64 | and/or display publicly, prepare derivative works, distribute, and 65 | otherwise use the Software alone or in any derivative version, 66 | provided, however, that the BeOpen Python License is retained in the 67 | Software, alone or in any derivative version prepared by Licensee. 68 | 69 | 3. BeOpen is making the Software available to Licensee on an "AS IS" 70 | basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR 71 | IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND 72 | DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS 73 | FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT 74 | INFRINGE ANY THIRD PARTY RIGHTS. 75 | 76 | 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE 77 | SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS 78 | AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY 79 | DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 80 | 81 | 5. This License Agreement will automatically terminate upon a material 82 | breach of its terms and conditions. 83 | 84 | 6. This License Agreement shall be governed by and interpreted in all 85 | respects by the law of the State of California, excluding conflict of 86 | law provisions. Nothing in this License Agreement shall be deemed to 87 | create any relationship of agency, partnership, or joint venture 88 | between BeOpen and Licensee. This License Agreement does not grant 89 | permission to use BeOpen trademarks or trade names in a trademark 90 | sense to endorse or promote products or services of Licensee, or any 91 | third party. As an exception, the "BeOpen Python" logos available at 92 | http://www.pythonlabs.com/logos.html may be used according to the 93 | permissions granted on that web page. 94 | 95 | 7. By copying, installing or otherwise using the software, Licensee 96 | agrees to be bound by the terms and conditions of this License 97 | Agreement. 98 | 99 | 100 | CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 101 | --------------------------------------- 102 | 103 | 1. This LICENSE AGREEMENT is between the Corporation for National 104 | Research Initiatives, having an office at 1895 Preston White Drive, 105 | Reston, VA 20191 ("CNRI"), and the Individual or Organization 106 | ("Licensee") accessing and otherwise using Python 1.6.1 software in 107 | source or binary form and its associated documentation. 108 | 109 | 2. Subject to the terms and conditions of this License Agreement, CNRI 110 | hereby grants Licensee a nonexclusive, royalty-free, world-wide 111 | license to reproduce, analyze, test, perform and/or display publicly, 112 | prepare derivative works, distribute, and otherwise use Python 1.6.1 113 | alone or in any derivative version, provided, however, that CNRI's 114 | License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) 115 | 1995-2001 Corporation for National Research Initiatives; All Rights 116 | Reserved" are retained in Python 1.6.1 alone or in any derivative 117 | version prepared by Licensee. Alternately, in lieu of CNRI's License 118 | Agreement, Licensee may substitute the following text (omitting the 119 | quotes): "Python 1.6.1 is made available subject to the terms and 120 | conditions in CNRI's License Agreement. This Agreement together with 121 | Python 1.6.1 may be located on the Internet using the following 122 | unique, persistent identifier (known as a handle): 1895.22/1013. This 123 | Agreement may also be obtained from a proxy server on the Internet 124 | using the following URL: http://hdl.handle.net/1895.22/1013". 125 | 126 | 3. In the event Licensee prepares a derivative work that is based on 127 | or incorporates Python 1.6.1 or any part thereof, and wants to make 128 | the derivative work available to others as provided herein, then 129 | Licensee hereby agrees to include in any such work a brief summary of 130 | the changes made to Python 1.6.1. 131 | 132 | 4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" 133 | basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR 134 | IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND 135 | DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS 136 | FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT 137 | INFRINGE ANY THIRD PARTY RIGHTS. 138 | 139 | 5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 140 | 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS 141 | A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, 142 | OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 143 | 144 | 6. This License Agreement will automatically terminate upon a material 145 | breach of its terms and conditions. 146 | 147 | 7. This License Agreement shall be governed by the federal 148 | intellectual property law of the United States, including without 149 | limitation the federal copyright law, and, to the extent such 150 | U.S. federal law does not apply, by the law of the Commonwealth of 151 | Virginia, excluding Virginia's conflict of law provisions. 152 | Notwithstanding the foregoing, with regard to derivative works based 153 | on Python 1.6.1 that incorporate non-separable material that was 154 | previously distributed under the GNU General Public License (GPL), the 155 | law of the Commonwealth of Virginia shall govern this License 156 | Agreement only as to issues arising under or with respect to 157 | Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this 158 | License Agreement shall be deemed to create any relationship of 159 | agency, partnership, or joint venture between CNRI and Licensee. This 160 | License Agreement does not grant permission to use CNRI trademarks or 161 | trade name in a trademark sense to endorse or promote products or 162 | services of Licensee, or any third party. 163 | 164 | 8. By clicking on the "ACCEPT" button where indicated, or by copying, 165 | installing or otherwise using Python 1.6.1, Licensee agrees to be 166 | bound by the terms and conditions of this License Agreement. 167 | 168 | ACCEPT 169 | 170 | 171 | CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 172 | -------------------------------------------------- 173 | 174 | Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, 175 | The Netherlands. All rights reserved. 176 | 177 | Permission to use, copy, modify, and distribute this software and its 178 | documentation for any purpose and without fee is hereby granted, 179 | provided that the above copyright notice appear in all copies and that 180 | both that copyright notice and this permission notice appear in 181 | supporting documentation, and that the name of Stichting Mathematisch 182 | Centrum or CWI not be used in advertising or publicity pertaining to 183 | distribution of the software without specific, written prior 184 | permission. 185 | 186 | STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO 187 | THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 188 | FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE 189 | FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 190 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 191 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 192 | OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 193 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include COPYING README.rst LICENSE.BSD LICENSE.PSF 2 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | EditorConfig Python Core 3 | ======================== 4 | .. image:: https://img.shields.io/pypi/v/EditorConfig.svg 5 | :target: https://pypi.python.org/pypi/EditorConfig 6 | 7 | .. image:: https://img.shields.io/pypi/wheel/EditorConfig.svg 8 | :target: https://pypi.python.org/pypi/EditorConfig 9 | 10 | .. image:: https://img.shields.io/pypi/pyversions/EditorConfig.svg 11 | :target: https://pypi.python.org/pypi/EditorConfig 12 | 13 | .. image:: https://secure.travis-ci.org/editorconfig/editorconfig-core-py.svg?branch=master 14 | :target: http://travis-ci.org/editorconfig/editorconfig-core-py 15 | 16 | EditorConfig Python Core provides the same functionality as the 17 | `EditorConfig C Core `_. 18 | EditorConfig Python core can be used as a command line program or as an 19 | importable library. 20 | 21 | EditorConfig Project 22 | ==================== 23 | 24 | EditorConfig makes it easy to maintain the correct coding style when switching 25 | between different text editors and between different projects. The 26 | EditorConfig project maintains a file format and plugins for various text 27 | editors which allow this file format to be read and used by those editors. For 28 | information on the file format and supported text editors, see the 29 | `EditorConfig website `_. 30 | 31 | Installation 32 | ============ 33 | 34 | With setuptools:: 35 | 36 | sudo python setup.py install 37 | 38 | Getting Help 39 | ============ 40 | For help with the EditorConfig core code, please write to our `mailing list 41 | `_. Bugs and feature requests 42 | should be submitted to our `issue tracker 43 | `_. 44 | 45 | If you are writing a plugin a language that can import Python libraries, you 46 | may want to import and use the EditorConfig Python Core directly. 47 | 48 | Using as a Library 49 | ================== 50 | 51 | Basic example use of EditorConfig Python Core as a library: 52 | 53 | .. code-block:: python 54 | 55 | from editorconfig import get_properties, EditorConfigError 56 | 57 | filename = "/home/zoidberg/humans/anatomy.md" 58 | 59 | try: 60 | options = get_properties(filename) 61 | except EditorConfigError: 62 | print("Error occurred while getting EditorConfig properties") 63 | else: 64 | for key, value in options.items(): 65 | print(f"{key}={value}") 66 | 67 | For details, please take a look at the `online documentation 68 | `_. 69 | 70 | Running Test Cases 71 | ================== 72 | 73 | `Cmake `_ has to be installed first. Run the test cases 74 | using the following commands:: 75 | 76 | export PYTHONPATH=$(pwd) 77 | cmake . 78 | ctest . 79 | 80 | Use ``-DPYTHON_EXECUTABLE`` to run the tests using an alternative versions of 81 | Python (e.g. Python 3.12):: 82 | 83 | cmake -DPYTHON_EXECUTABLE=/usr/bin/python3.12 . 84 | ctest . 85 | 86 | License 87 | ======= 88 | 89 | See COPYING file for licensing details. 90 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | 15 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest 16 | 17 | help: 18 | @echo "Please use \`make ' where is one of" 19 | @echo " html to make standalone HTML files" 20 | @echo " dirhtml to make HTML files named index.html in directories" 21 | @echo " singlehtml to make a single large HTML file" 22 | @echo " pickle to make pickle files" 23 | @echo " json to make JSON files" 24 | @echo " htmlhelp to make HTML files and a HTML help project" 25 | @echo " qthelp to make HTML files and a qthelp project" 26 | @echo " devhelp to make HTML files and a Devhelp project" 27 | @echo " epub to make an epub" 28 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 29 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 30 | @echo " text to make text files" 31 | @echo " man to make manual pages" 32 | @echo " changes to make an overview of all changed/added/deprecated items" 33 | @echo " linkcheck to check all external links for integrity" 34 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 35 | 36 | clean: 37 | -rm -rf $(BUILDDIR)/* 38 | 39 | html: 40 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 41 | @echo 42 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 43 | 44 | dirhtml: 45 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 48 | 49 | singlehtml: 50 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 51 | @echo 52 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 53 | 54 | pickle: 55 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 56 | @echo 57 | @echo "Build finished; now you can process the pickle files." 58 | 59 | json: 60 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 61 | @echo 62 | @echo "Build finished; now you can process the JSON files." 63 | 64 | htmlhelp: 65 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 66 | @echo 67 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 68 | ".hhp project file in $(BUILDDIR)/htmlhelp." 69 | 70 | qthelp: 71 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 72 | @echo 73 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 74 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 75 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/EditorConfigPythonCore.qhcp" 76 | @echo "To view the help file:" 77 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/EditorConfigPythonCore.qhc" 78 | 79 | devhelp: 80 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 81 | @echo 82 | @echo "Build finished." 83 | @echo "To view the help file:" 84 | @echo "# mkdir -p $$HOME/.local/share/devhelp/EditorConfigPythonCore" 85 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/EditorConfigPythonCore" 86 | @echo "# devhelp" 87 | 88 | epub: 89 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 90 | @echo 91 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 92 | 93 | latex: 94 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 95 | @echo 96 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 97 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 98 | "(use \`make latexpdf' here to do that automatically)." 99 | 100 | latexpdf: 101 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 102 | @echo "Running LaTeX files through pdflatex..." 103 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 104 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 105 | 106 | text: 107 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 108 | @echo 109 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 110 | 111 | man: 112 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 113 | @echo 114 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 115 | 116 | changes: 117 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 118 | @echo 119 | @echo "The overview file is in $(BUILDDIR)/changes." 120 | 121 | linkcheck: 122 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 123 | @echo 124 | @echo "Link check complete; look for any errors in the above output " \ 125 | "or in $(BUILDDIR)/linkcheck/output.txt." 126 | 127 | doctest: 128 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 129 | @echo "Testing of doctests in the sources finished, look at the " \ 130 | "results in $(BUILDDIR)/doctest/output.txt." 131 | -------------------------------------------------------------------------------- /docs/command_line_usage.rst: -------------------------------------------------------------------------------- 1 | ================== 2 | Command Line Usage 3 | ================== 4 | 5 | The EditorConfig Python Core can be used from the command line in the same way 6 | as the EditorConfig C Core. 7 | 8 | Discovering EditorConfig properties 9 | ----------------------------------- 10 | 11 | Installing EditorConfig Python Core should add an ``editorconfig.py`` command 12 | to your path. This command can be used to locate and parse EditorConfig files 13 | for a given full filepath. For example:: 14 | 15 | editorconfig.py /home/zoidberg/humans/anatomy.md 16 | 17 | When used to retrieve EditorConfig file properties, ``editorconfig.py`` will 18 | return discovered properties in *key=value* pairs, one on each line. 19 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # EditorConfig Python Core documentation build configuration file, created by 4 | # sphinx-quickstart on Sat May 5 09:51:42 2012. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import os 15 | import sys 16 | 17 | # If extensions (or modules to document with autodoc) are in another directory, 18 | # add these directories to sys.path here. If the directory is relative to the 19 | # documentation root, use os.path.abspath to make it absolute, like shown here. 20 | sys.path.insert(0, os.path.abspath('..')) 21 | 22 | import editorconfig 23 | from editorconfig import __version__ 24 | 25 | 26 | # -- General configuration ----------------------------------------------------- 27 | 28 | # If your documentation needs a minimal Sphinx version, state it here. 29 | #needs_sphinx = '1.0' 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be extensions 32 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 33 | extensions = ['sphinx.ext.autodoc'] 34 | 35 | # Add any paths that contain templates here, relative to this directory. 36 | templates_path = ['_templates'] 37 | 38 | # The suffix of source filenames. 39 | source_suffix = '.rst' 40 | 41 | # The encoding of source files. 42 | #source_encoding = 'utf-8-sig' 43 | 44 | # The master toctree document. 45 | master_doc = 'index' 46 | 47 | # General information about the project. 48 | project = u'EditorConfig Python Core' 49 | copyright = u'2012, EditorConfig Team' 50 | 51 | # The version info for the project you're documenting, acts as replacement for 52 | # |version| and |release|, also used in various other places throughout the 53 | # built documents. 54 | # 55 | # The short X.Y version. 56 | version = __version__ 57 | # The full version, including alpha/beta/rc tags. 58 | release = __version__ 59 | 60 | # The language for content autogenerated by Sphinx. Refer to documentation 61 | # for a list of supported languages. 62 | #language = None 63 | 64 | # There are two options for replacing |today|: either, you set today to some 65 | # non-false value, then it is used: 66 | #today = '' 67 | # Else, today_fmt is used as the format for a strftime call. 68 | #today_fmt = '%B %d, %Y' 69 | 70 | # List of patterns, relative to source directory, that match files and 71 | # directories to ignore when looking for source files. 72 | exclude_patterns = ['_build'] 73 | 74 | # The reST default role (used for this markup: `text`) to use for all documents. 75 | #default_role = None 76 | 77 | # If true, '()' will be appended to :func: etc. cross-reference text. 78 | #add_function_parentheses = True 79 | 80 | # If true, the current module name will be prepended to all description 81 | # unit titles (such as .. function::). 82 | #add_module_names = True 83 | 84 | # If true, sectionauthor and moduleauthor directives will be shown in the 85 | # output. They are ignored by default. 86 | #show_authors = False 87 | 88 | # The name of the Pygments (syntax highlighting) style to use. 89 | pygments_style = 'sphinx' 90 | 91 | # A list of ignored prefixes for module index sorting. 92 | #modindex_common_prefix = [] 93 | 94 | 95 | # -- Options for HTML output --------------------------------------------------- 96 | 97 | # The theme to use for HTML and HTML Help pages. See the documentation for 98 | # a list of builtin themes. 99 | html_theme = 'agogo' 100 | 101 | # Theme options are theme-specific and customize the look and feel of a theme 102 | # further. For a list of options available for each theme, see the 103 | # documentation. 104 | #html_theme_options = {} 105 | 106 | # Add any paths that contain custom themes here, relative to this directory. 107 | #html_theme_path = [] 108 | 109 | # The name for this set of Sphinx documents. If None, it defaults to 110 | # " v documentation". 111 | #html_title = None 112 | 113 | # A shorter title for the navigation bar. Default is the same as html_title. 114 | #html_short_title = None 115 | 116 | # The name of an image file (relative to this directory) to place at the top 117 | # of the sidebar. 118 | #html_logo = None 119 | 120 | # The name of an image file (within the static path) to use as favicon of the 121 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 122 | # pixels large. 123 | #html_favicon = None 124 | 125 | # Add any paths that contain custom static files (such as style sheets) here, 126 | # relative to this directory. They are copied after the builtin static files, 127 | # so a file named "default.css" will overwrite the builtin "default.css". 128 | html_static_path = ['_static'] 129 | 130 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 131 | # using the given strftime format. 132 | #html_last_updated_fmt = '%b %d, %Y' 133 | 134 | # If true, SmartyPants will be used to convert quotes and dashes to 135 | # typographically correct entities. 136 | #html_use_smartypants = True 137 | 138 | # Custom sidebar templates, maps document names to template names. 139 | #html_sidebars = {} 140 | 141 | # Additional templates that should be rendered to pages, maps page names to 142 | # template names. 143 | #html_additional_pages = {} 144 | 145 | # If false, no module index is generated. 146 | #html_domain_indices = True 147 | 148 | # If false, no index is generated. 149 | #html_use_index = True 150 | 151 | # If true, the index is split into individual pages for each letter. 152 | #html_split_index = False 153 | 154 | # If true, links to the reST sources are added to the pages. 155 | #html_show_sourcelink = True 156 | 157 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 158 | #html_show_sphinx = True 159 | 160 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 161 | #html_show_copyright = True 162 | 163 | # If true, an OpenSearch description file will be output, and all pages will 164 | # contain a tag referring to it. The value of this option must be the 165 | # base URL from which the finished HTML is served. 166 | #html_use_opensearch = '' 167 | 168 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 169 | #html_file_suffix = None 170 | 171 | # Output file base name for HTML help builder. 172 | htmlhelp_basename = 'EditorConfigPythonCoredoc' 173 | 174 | 175 | # -- Options for LaTeX output -------------------------------------------------- 176 | 177 | # The paper size ('letter' or 'a4'). 178 | #latex_paper_size = 'letter' 179 | 180 | # The font size ('10pt', '11pt' or '12pt'). 181 | #latex_font_size = '10pt' 182 | 183 | # Grouping the document tree into LaTeX files. List of tuples 184 | # (source start file, target name, title, author, documentclass [howto/manual]). 185 | latex_documents = [ 186 | ('index', 'EditorConfigPythonCore.tex', u'EditorConfig Python Core Documentation', 187 | u'EditorConfig Team', 'manual'), 188 | ] 189 | 190 | # The name of an image file (relative to this directory) to place at the top of 191 | # the title page. 192 | #latex_logo = None 193 | 194 | # For "manual" documents, if this is true, then toplevel headings are parts, 195 | # not chapters. 196 | #latex_use_parts = False 197 | 198 | # If true, show page references after internal links. 199 | #latex_show_pagerefs = False 200 | 201 | # If true, show URL addresses after external links. 202 | #latex_show_urls = False 203 | 204 | # Additional stuff for the LaTeX preamble. 205 | #latex_preamble = '' 206 | 207 | # Documents to append as an appendix to all manuals. 208 | #latex_appendices = [] 209 | 210 | # If false, no module index is generated. 211 | #latex_domain_indices = True 212 | 213 | 214 | # -- Options for manual page output -------------------------------------------- 215 | 216 | # One entry per manual page. List of tuples 217 | # (source start file, name, description, authors, manual section). 218 | man_pages = [ 219 | ('index', 'editorconfigpythoncore', u'EditorConfig Python Core Documentation', 220 | [u'EditorConfig Team'], 1) 221 | ] 222 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ================================================================== 2 | EditorConfig Python Core -- Process EditorConfig Files With Python 3 | ================================================================== 4 | 5 | EditorConfig is a file format for defining file-specific coding styles and a 6 | set of plugins that allow text editors and IDEs to read this file format. For 7 | more information on the EditorConfig project visit the 8 | `EditorConfig Homepage`_. 9 | 10 | The EditorConfig Python Core is a Python package for locating and parsing 11 | EditorConfig files. This package can be used as an import by other Python code 12 | or as a stand-alone command line program. 13 | 14 | .. _`EditorConfig Homepage`: https://editorconfig.org 15 | 16 | Contents: 17 | 18 | .. toctree:: 19 | :maxdepth: 1 20 | 21 | usage 22 | command_line_usage 23 | plugins 24 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | if NOT "%PAPER%" == "" ( 11 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 12 | ) 13 | 14 | if "%1" == "" goto help 15 | 16 | if "%1" == "help" ( 17 | :help 18 | echo.Please use `make ^` where ^ is one of 19 | echo. html to make standalone HTML files 20 | echo. dirhtml to make HTML files named index.html in directories 21 | echo. singlehtml to make a single large HTML file 22 | echo. pickle to make pickle files 23 | echo. json to make JSON files 24 | echo. htmlhelp to make HTML files and a HTML help project 25 | echo. qthelp to make HTML files and a qthelp project 26 | echo. devhelp to make HTML files and a Devhelp project 27 | echo. epub to make an epub 28 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 29 | echo. text to make text files 30 | echo. man to make manual pages 31 | echo. changes to make an overview over all changed/added/deprecated items 32 | echo. linkcheck to check all external links for integrity 33 | echo. doctest to run all doctests embedded in the documentation if enabled 34 | goto end 35 | ) 36 | 37 | if "%1" == "clean" ( 38 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 39 | del /q /s %BUILDDIR%\* 40 | goto end 41 | ) 42 | 43 | if "%1" == "html" ( 44 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 45 | if errorlevel 1 exit /b 1 46 | echo. 47 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 48 | goto end 49 | ) 50 | 51 | if "%1" == "dirhtml" ( 52 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 53 | if errorlevel 1 exit /b 1 54 | echo. 55 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 56 | goto end 57 | ) 58 | 59 | if "%1" == "singlehtml" ( 60 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 61 | if errorlevel 1 exit /b 1 62 | echo. 63 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 64 | goto end 65 | ) 66 | 67 | if "%1" == "pickle" ( 68 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 69 | if errorlevel 1 exit /b 1 70 | echo. 71 | echo.Build finished; now you can process the pickle files. 72 | goto end 73 | ) 74 | 75 | if "%1" == "json" ( 76 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 77 | if errorlevel 1 exit /b 1 78 | echo. 79 | echo.Build finished; now you can process the JSON files. 80 | goto end 81 | ) 82 | 83 | if "%1" == "htmlhelp" ( 84 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 85 | if errorlevel 1 exit /b 1 86 | echo. 87 | echo.Build finished; now you can run HTML Help Workshop with the ^ 88 | .hhp project file in %BUILDDIR%/htmlhelp. 89 | goto end 90 | ) 91 | 92 | if "%1" == "qthelp" ( 93 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 94 | if errorlevel 1 exit /b 1 95 | echo. 96 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 97 | .qhcp project file in %BUILDDIR%/qthelp, like this: 98 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\EditorConfigPythonCore.qhcp 99 | echo.To view the help file: 100 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\EditorConfigPythonCore.ghc 101 | goto end 102 | ) 103 | 104 | if "%1" == "devhelp" ( 105 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 106 | if errorlevel 1 exit /b 1 107 | echo. 108 | echo.Build finished. 109 | goto end 110 | ) 111 | 112 | if "%1" == "epub" ( 113 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 114 | if errorlevel 1 exit /b 1 115 | echo. 116 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 117 | goto end 118 | ) 119 | 120 | if "%1" == "latex" ( 121 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 122 | if errorlevel 1 exit /b 1 123 | echo. 124 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 125 | goto end 126 | ) 127 | 128 | if "%1" == "text" ( 129 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 130 | if errorlevel 1 exit /b 1 131 | echo. 132 | echo.Build finished. The text files are in %BUILDDIR%/text. 133 | goto end 134 | ) 135 | 136 | if "%1" == "man" ( 137 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 138 | if errorlevel 1 exit /b 1 139 | echo. 140 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 141 | goto end 142 | ) 143 | 144 | if "%1" == "changes" ( 145 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 146 | if errorlevel 1 exit /b 1 147 | echo. 148 | echo.The overview file is in %BUILDDIR%/changes. 149 | goto end 150 | ) 151 | 152 | if "%1" == "linkcheck" ( 153 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 154 | if errorlevel 1 exit /b 1 155 | echo. 156 | echo.Link check complete; look for any errors in the above output ^ 157 | or in %BUILDDIR%/linkcheck/output.txt. 158 | goto end 159 | ) 160 | 161 | if "%1" == "doctest" ( 162 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 163 | if errorlevel 1 exit /b 1 164 | echo. 165 | echo.Testing of doctests in the sources finished, look at the ^ 166 | results in %BUILDDIR%/doctest/output.txt. 167 | goto end 168 | ) 169 | 170 | :end 171 | -------------------------------------------------------------------------------- /docs/plugins.rst: -------------------------------------------------------------------------------- 1 | =============== 2 | Writing Plugins 3 | =============== 4 | 5 | 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. 6 | 7 | .. _`Vim`: https://github.com/editorconfig/editorconfig-vim 8 | .. _`Gedit`: https://github.com/editorconfig/editorconfig-gedit 9 | 10 | 11 | Use as a library 12 | ---------------- 13 | 14 | For instructions on using the EditorConfig Python Core as a Python library see :doc:`usage`. 15 | 16 | 17 | Using with an external Python interpreter 18 | ----------------------------------------- 19 | 20 | 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:: 21 | 22 | python editorconfig-core-py/main.py /home/zoidberg/humans/anatomy.md 23 | 24 | For more information on command line usage of the EditorConfig Python Core see :doc:`command_line_usage`. 25 | 26 | 27 | Bundling EditorConfig Python Core with Plugin 28 | --------------------------------------------- 29 | 30 | A text editor or IDE plugin will either need to bundle the EditorConfig Python 31 | Core with the plugin installation package or the will need to assist the user 32 | in installing the EditorConfig Python Core. Below are instructions for 33 | bundling the EditorConfig Python Core with plugins. 34 | 35 | Bundling as a Submodule in Git 36 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 37 | 38 | Git submodules allow one repository to be included inside another. A submodule 39 | stores a remote repositry and commit to use for fetching the embedded 40 | repository. Submodules take up very little space in the repository since they 41 | do not actually include the code of the embedded repository directly. 42 | 43 | To add EditorConfig Python Core as a submodule in the ``editorconfig-core-py`` 44 | directory of your repository:: 45 | 46 | git submodule add git://github.com/editorconfig/editorconfig-core-py.git editorconfig-core-py 47 | 48 | Then every time the code is checked out the submodule directory should be 49 | initialized and updated:: 50 | 51 | git submodule update --init 52 | 53 | Bundling as a Subtree in Git 54 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 55 | 56 | Git subtrees are convenient because, unlike submodules, they do not require any 57 | extra work to be performed when cloning the git repository. Git subtrees 58 | include one git codebase as a subdirectory of another. 59 | 60 | Example of using a subtree for the ``editorconfig`` directory from the 61 | EditorConfig Python Core repository:: 62 | 63 | git remote add -f editorconfig-core-py git://github.com/editorconfig/editorconfig-core-py.git 64 | git merge -s ours --no-commit editorconfig-core-py/master 65 | git read-tree --prefix=editorconfig -u editorconfig-core-py/master:editorconfig 66 | git commit 67 | 68 | For more information on subtrees consult the `subtree merge guide`_ on Github 69 | and `Chapter 6.7`_ in the book Pro Git. 70 | 71 | .. _`subtree merge guide`: http://help.github.com/subtree-merge/ 72 | .. _`Chapter 6.7`: http://git-scm.com/book/ch6-7.html 73 | -------------------------------------------------------------------------------- /docs/usage.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | Usage 3 | ===== 4 | 5 | Installation 6 | ------------ 7 | 8 | First you will need to install the EditorConfig Python Core package. 9 | 10 | To install from PyPI using pip:: 11 | 12 | pip install editorconfig 13 | 14 | Discovering EditorConfig properties 15 | ----------------------------------- 16 | 17 | The ``get_properties`` function can be used to discover EditorConfig properties 18 | for a given file. Example: 19 | 20 | .. code-block:: python 21 | 22 | import logging 23 | from editorconfig import get_properties, EditorConfigError 24 | 25 | filename = "/home/zoidberg/humans/anatomy.md" 26 | 27 | try: 28 | options = get_properties(filename) 29 | except EditorConfigError: 30 | logging.warning("Error getting EditorConfig properties", exc_info=True) 31 | else: 32 | for key, value in options.items(): 33 | print "%s=%s" % (key, value) 34 | 35 | 36 | The ``get_properties`` method returns a dictionary representing EditorConfig 37 | properties found for the given file. If an error occurs while parsing a file 38 | an exception will be raised. All raised exceptions will inherit from the 39 | ``EditorConfigError`` class. 40 | 41 | Handling Exceptions 42 | ------------------- 43 | 44 | All exceptions raised by EditorConfig will subclass ``EditorConfigError``. To 45 | handle certain exceptions specially, catch them first. More exception classes 46 | may be added in the future so it is advisable to always handle general 47 | ``EditorConfigError`` exceptions in case a future version raises an exception 48 | that your code does not handle specifically. 49 | 50 | Exceptions module reference 51 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 52 | 53 | Exceptions can be found in the ``editorconfig.exceptions`` module. These are 54 | the current exception types: 55 | 56 | .. autoexception:: editorconfig.exceptions.EditorConfigError 57 | .. autoexception:: editorconfig.exceptions.ParsingError 58 | .. autoexception:: editorconfig.exceptions.PathError 59 | .. autoexception:: editorconfig.exceptions.VersionError 60 | 61 | Exception handling example 62 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 63 | 64 | An example of custom exception handling: 65 | 66 | .. code-block:: python 67 | 68 | import logging 69 | from editorconfig import get_properties 70 | from editorconfig import exceptions 71 | 72 | filename = "/home/zoidberg/myfile.txt" 73 | 74 | try: 75 | options = get_properties(filename) 76 | except exceptions.ParsingError: 77 | logging.warning("Error parsing an .editorconfig file", exc_info=True) 78 | except exceptions.PathError: 79 | logging.error("Invalid filename specified", exc_info=True) 80 | except exceptions.EditorConfigError: 81 | logging.error("An unknown EditorConfig error occurred", exc_info=True) 82 | 83 | for key, value in options.iteritems(): 84 | print "%s=%s" % (key, value) 85 | -------------------------------------------------------------------------------- /editorconfig/__init__.py: -------------------------------------------------------------------------------- 1 | """EditorConfig Python Core""" 2 | 3 | from editorconfig.versiontools import join_version 4 | from editorconfig.version import VERSION 5 | 6 | __all__ = ['get_properties', 'EditorConfigError', 'exceptions'] 7 | 8 | __version__ = join_version(VERSION) 9 | 10 | 11 | def get_properties(filename): 12 | """Locate and parse EditorConfig files for the given filename""" 13 | handler = EditorConfigHandler(filename) 14 | return handler.get_configurations() 15 | 16 | 17 | from editorconfig.handler import EditorConfigHandler 18 | from editorconfig.exceptions import * 19 | -------------------------------------------------------------------------------- /editorconfig/__main__.py: -------------------------------------------------------------------------------- 1 | """EditorConfig command line interface 2 | 3 | Licensed under Simplified BSD License (see LICENSE.BSD file). 4 | 5 | """ 6 | 7 | import getopt 8 | import sys 9 | 10 | from editorconfig import VERSION, __version__ 11 | from editorconfig.compat import force_unicode 12 | from editorconfig.exceptions import ParsingError, PathError, VersionError 13 | from editorconfig.handler import EditorConfigHandler 14 | from editorconfig.versiontools import split_version 15 | 16 | 17 | def version(): 18 | print("EditorConfig Python Core Version %s" % __version__) 19 | 20 | 21 | def usage(command, error=False): 22 | if error: 23 | out = sys.stderr 24 | else: 25 | out = sys.stdout 26 | out.write("%s [OPTIONS] FILENAME\n" % command) 27 | out.write('-f ' 28 | 'Specify conf filename other than ".editorconfig".\n') 29 | out.write("-b " 30 | "Specify version (used by devs to test compatibility).\n") 31 | out.write("-h OR --help Print this help message.\n") 32 | out.write("-v OR --version Display version information.\n") 33 | 34 | 35 | def main(): 36 | command_name = sys.argv[0] 37 | try: 38 | opts, args = getopt.getopt(list(map(force_unicode, sys.argv[1:])), 39 | "vhb:f:", ["version", "help"]) 40 | except getopt.GetoptError as e: 41 | print(str(e)) 42 | usage(command_name, error=True) 43 | sys.exit(2) 44 | 45 | version_tuple = VERSION 46 | conf_filename = '.editorconfig' 47 | 48 | for option, arg in opts: 49 | if option in ('-h', '--help'): 50 | usage(command_name) 51 | sys.exit() 52 | if option in ('-v', '--version'): 53 | version() 54 | sys.exit() 55 | if option == '-f': 56 | conf_filename = arg 57 | if option == '-b': 58 | version_tuple = split_version(arg) 59 | if version_tuple is None: 60 | sys.exit("Invalid version number: %s" % arg) 61 | 62 | if len(args) < 1: 63 | usage(command_name, error=True) 64 | sys.exit(2) 65 | filenames = args 66 | multiple_files = len(args) > 1 67 | 68 | for filename in filenames: 69 | handler = EditorConfigHandler(filename, conf_filename, version_tuple) 70 | try: 71 | options = handler.get_configurations() 72 | except (ParsingError, PathError, VersionError) as e: 73 | print(str(e)) 74 | sys.exit(2) 75 | if multiple_files: 76 | print("[%s]" % filename) 77 | for key, value in options.items(): 78 | print("%s=%s" % (key, value)) 79 | 80 | 81 | if __name__ == "__main__": 82 | main() 83 | -------------------------------------------------------------------------------- /editorconfig/compat.py: -------------------------------------------------------------------------------- 1 | """EditorConfig Python2/Python3 compatibility utilities""" 2 | import sys 3 | 4 | 5 | __all__ = ['force_unicode', 'u'] 6 | 7 | 8 | if sys.version_info[0] == 2: 9 | text_type = unicode 10 | else: 11 | text_type = str 12 | 13 | 14 | def force_unicode(string): 15 | if not isinstance(string, text_type): 16 | string = text_type(string, encoding='utf-8') 17 | return string 18 | 19 | 20 | if sys.version_info[0] == 2: 21 | import codecs 22 | u = lambda s: codecs.unicode_escape_decode(s)[0] 23 | else: 24 | u = lambda s: s 25 | -------------------------------------------------------------------------------- /editorconfig/exceptions.py: -------------------------------------------------------------------------------- 1 | """EditorConfig exception classes 2 | 3 | Licensed under Simplified BSD License (see LICENSE.BSD file). 4 | 5 | """ 6 | 7 | 8 | class EditorConfigError(Exception): 9 | """Parent class of all exceptions raised by EditorConfig""" 10 | 11 | 12 | try: 13 | from ConfigParser import ParsingError as _ParsingError 14 | except: 15 | from configparser import ParsingError as _ParsingError 16 | 17 | 18 | class ParsingError(_ParsingError, EditorConfigError): 19 | """Error raised if an EditorConfig file could not be parsed""" 20 | 21 | 22 | class PathError(ValueError, EditorConfigError): 23 | """Error raised if invalid filepath is specified""" 24 | 25 | 26 | class VersionError(ValueError, EditorConfigError): 27 | """Error raised if invalid version number is specified""" 28 | -------------------------------------------------------------------------------- /editorconfig/fnmatch.py: -------------------------------------------------------------------------------- 1 | """Filename matching with shell patterns. 2 | 3 | fnmatch(FILENAME, PATTERN) matches according to the local convention. 4 | fnmatchcase(FILENAME, PATTERN) always takes case in account. 5 | 6 | The functions operate by translating the pattern into a regular 7 | expression. They cache the compiled regular expressions for speed. 8 | 9 | The function translate(PATTERN) returns a regular expression 10 | corresponding to PATTERN. (It does not compile it.) 11 | 12 | Based on code from fnmatch.py file distributed with Python 2.6. 13 | 14 | Licensed under PSF License (see LICENSE.PSF file). 15 | 16 | Changes to original fnmatch module: 17 | - translate function supports ``*`` and ``**`` similarly to fnmatch C library 18 | """ 19 | 20 | import os 21 | import re 22 | 23 | 24 | __all__ = ["fnmatch", "fnmatchcase", "translate"] 25 | 26 | _cache = {} 27 | 28 | LEFT_BRACE = re.compile( 29 | r""" 30 | 31 | (? 0 and not is_escaped: 198 | result += '|' 199 | else: 200 | result += '\\,' 201 | elif current_char == '}': 202 | if brace_level > 0 and not is_escaped: 203 | result += ')' 204 | brace_level -= 1 205 | else: 206 | result += '\\}' 207 | elif current_char == '/': 208 | if pat[index:(index + 3)] == "**/": 209 | result += "(?:/|/.*/)" 210 | index += 3 211 | else: 212 | result += '/' 213 | elif current_char != '\\': 214 | result += re.escape(current_char) 215 | if current_char == '\\': 216 | if is_escaped: 217 | result += re.escape(current_char) 218 | is_escaped = not is_escaped 219 | else: 220 | is_escaped = False 221 | if not nested: 222 | result = r'(?s)%s\Z' % result 223 | return result, numeric_groups 224 | -------------------------------------------------------------------------------- /editorconfig/handler.py: -------------------------------------------------------------------------------- 1 | """EditorConfig file handler 2 | 3 | Provides ``EditorConfigHandler`` class for locating and parsing 4 | EditorConfig files relevant to a given filepath. 5 | 6 | Licensed under Simplified BSD License (see LICENSE.BSD file). 7 | 8 | """ 9 | 10 | import os 11 | 12 | from editorconfig import VERSION 13 | from editorconfig.exceptions import PathError, VersionError 14 | from editorconfig.ini import EditorConfigParser 15 | 16 | 17 | __all__ = ['EditorConfigHandler'] 18 | 19 | 20 | def get_filenames(path, filename): 21 | """Yield full filepath for filename in each directory in and above path""" 22 | path_list = [] 23 | while True: 24 | path_list.append(os.path.join(path, filename)) 25 | newpath = os.path.dirname(path) 26 | if path == newpath: 27 | break 28 | path = newpath 29 | return path_list 30 | 31 | 32 | class EditorConfigHandler(object): 33 | 34 | """ 35 | Allows locating and parsing of EditorConfig files for given filename 36 | 37 | In addition to the constructor a single public method is provided, 38 | ``get_configurations`` which returns the EditorConfig options for 39 | the ``filepath`` specified to the constructor. 40 | 41 | """ 42 | 43 | def __init__(self, filepath, conf_filename='.editorconfig', 44 | version=VERSION): 45 | """Create EditorConfigHandler for matching given filepath""" 46 | self.filepath = filepath 47 | self.conf_filename = conf_filename 48 | self.version = version 49 | self.options = None 50 | 51 | def get_configurations(self): 52 | 53 | """ 54 | Find EditorConfig files and return all options matching filepath 55 | 56 | Special exceptions that may be raised by this function include: 57 | 58 | - ``VersionError``: self.version is invalid EditorConfig version 59 | - ``PathError``: self.filepath is not a valid absolute filepath 60 | - ``ParsingError``: improperly formatted EditorConfig file found 61 | 62 | """ 63 | 64 | self.check_assertions() 65 | path, filename = os.path.split(self.filepath) 66 | conf_files = get_filenames(path, self.conf_filename) 67 | 68 | # Attempt to find and parse every EditorConfig file in filetree 69 | for filename in conf_files: 70 | parser = EditorConfigParser(self.filepath) 71 | parser.read(filename) 72 | 73 | # Merge new EditorConfig file's options into current options 74 | old_options = self.options 75 | self.options = parser.options 76 | if old_options: 77 | self.options.update(old_options) 78 | 79 | # Stop parsing if parsed file has a ``root = true`` option 80 | if parser.root_file: 81 | break 82 | 83 | self.preprocess_values() 84 | return self.options 85 | 86 | def check_assertions(self): 87 | 88 | """Raise error if filepath or version have invalid values""" 89 | 90 | # Raise ``PathError`` if filepath isn't an absolute path 91 | if not os.path.isabs(self.filepath): 92 | raise PathError("Input file must be a full path name.") 93 | 94 | # Raise ``VersionError`` if version specified is greater than current 95 | if self.version is not None and self.version[:3] > VERSION[:3]: 96 | raise VersionError( 97 | "Required version is greater than the current version.") 98 | 99 | def preprocess_values(self): 100 | 101 | """Preprocess option values for consumption by plugins""" 102 | 103 | opts = self.options 104 | 105 | # Lowercase option value for certain options 106 | for name in ["end_of_line", "indent_style", "indent_size", 107 | "insert_final_newline", "trim_trailing_whitespace", 108 | "charset"]: 109 | if name in opts: 110 | opts[name] = opts[name].lower() 111 | 112 | # Set indent_size to "tab" if indent_size is unspecified and 113 | # indent_style is set to "tab". 114 | if (opts.get("indent_style") == "tab" and 115 | not "indent_size" in opts and self.version >= (0, 10, 0)): 116 | opts["indent_size"] = "tab" 117 | 118 | # Set tab_width to indent_size if indent_size is specified and 119 | # tab_width is unspecified 120 | if ("indent_size" in opts and "tab_width" not in opts and 121 | opts["indent_size"] != "tab"): 122 | opts["tab_width"] = opts["indent_size"] 123 | 124 | # Set indent_size to tab_width if indent_size is "tab" 125 | if ("indent_size" in opts and "tab_width" in opts and 126 | opts["indent_size"] == "tab"): 127 | opts["indent_size"] = opts["tab_width"] 128 | -------------------------------------------------------------------------------- /editorconfig/ini.py: -------------------------------------------------------------------------------- 1 | """EditorConfig file parser 2 | 3 | Based on code from ConfigParser.py file distributed with Python 2.6. 4 | 5 | Licensed under PSF License (see LICENSE.PSF file). 6 | 7 | Changes to original ConfigParser: 8 | 9 | - Special characters can be used in section names 10 | - Octothorpe can be used for comments (not just at beginning of line) 11 | - Only track INI options in sections that match target filename 12 | - Stop parsing files with when ``root = true`` is found 13 | 14 | """ 15 | 16 | import posixpath 17 | import re 18 | from codecs import open 19 | from collections import OrderedDict 20 | from os import sep 21 | from os.path import dirname, normpath 22 | 23 | from editorconfig.compat import u 24 | from editorconfig.exceptions import ParsingError 25 | from editorconfig.fnmatch import fnmatch 26 | 27 | 28 | __all__ = ["ParsingError", "EditorConfigParser"] 29 | 30 | 31 | class EditorConfigParser(object): 32 | 33 | """Parser for EditorConfig-style configuration files 34 | 35 | Based on RawConfigParser from ConfigParser.py in Python 2.6. 36 | """ 37 | 38 | # Regular expressions for parsing section headers and options. 39 | # Allow ``]`` and escaped ``;`` and ``#`` characters in section headers 40 | SECTCRE = re.compile( 41 | r""" 42 | 43 | \s * # Optional whitespace 44 | \[ # Opening square brace 45 | 46 | (?P
# One or more characters excluding 47 | ( [^\#;] | \\\# | \\; ) + # unescaped # and ; characters 48 | ) 49 | 50 | \] # Closing square brace 51 | 52 | """, re.VERBOSE 53 | ) 54 | # Regular expression for parsing option name/values. 55 | # Allow any amount of whitespaces, followed by separator 56 | # (either ``:`` or ``=``), followed by any amount of whitespace and then 57 | # any characters to eol 58 | OPTCRE = re.compile( 59 | r""" 60 | 61 | \s * # Optional whitespace 62 | (?P