summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/editorconfig
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.11/site-packages/editorconfig')
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/__init__.py18
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/__main__.py82
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/__pycache__/__init__.cpython-311.pycbin0 -> 947 bytes
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/__pycache__/__main__.cpython-311.pycbin0 -> 4419 bytes
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/__pycache__/compat.cpython-311.pycbin0 -> 1107 bytes
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/__pycache__/exceptions.cpython-311.pycbin0 -> 1614 bytes
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/__pycache__/fnmatch.cpython-311.pycbin0 -> 7505 bytes
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/__pycache__/handler.cpython-311.pycbin0 -> 5119 bytes
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/__pycache__/ini.cpython-311.pycbin0 -> 7410 bytes
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/__pycache__/version.cpython-311.pycbin0 -> 228 bytes
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/__pycache__/versiontools.cpython-311.pycbin0 -> 1612 bytes
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/compat.py24
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/exceptions.py27
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/fnmatch.py223
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/handler.py127
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/ini.py183
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/version.py1
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/versiontools.py35
18 files changed, 720 insertions, 0 deletions
diff --git a/venv/lib/python3.11/site-packages/editorconfig/__init__.py b/venv/lib/python3.11/site-packages/editorconfig/__init__.py
new file mode 100644
index 0000000..2574ce4
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/__init__.py
@@ -0,0 +1,18 @@
+"""EditorConfig Python Core"""
+
+from editorconfig.versiontools import join_version
+from editorconfig.version import VERSION
+
+__all__ = ['get_properties', 'EditorConfigError', 'exceptions']
+
+__version__ = join_version(VERSION)
+
+
+def get_properties(filename):
+ """Locate and parse EditorConfig files for the given filename"""
+ handler = EditorConfigHandler(filename)
+ return handler.get_configurations()
+
+
+from editorconfig.handler import EditorConfigHandler
+from editorconfig.exceptions import *
diff --git a/venv/lib/python3.11/site-packages/editorconfig/__main__.py b/venv/lib/python3.11/site-packages/editorconfig/__main__.py
new file mode 100644
index 0000000..fc98b6f
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/__main__.py
@@ -0,0 +1,82 @@
+"""EditorConfig command line interface
+
+Licensed under Simplified BSD License (see LICENSE.BSD file).
+
+"""
+
+import getopt
+import sys
+
+from editorconfig import VERSION, __version__
+from editorconfig.compat import force_unicode
+from editorconfig.exceptions import ParsingError, PathError, VersionError
+from editorconfig.handler import EditorConfigHandler
+from editorconfig.versiontools import split_version
+
+
+def version():
+ print("EditorConfig Python Core Version %s" % __version__)
+
+
+def usage(command, error=False):
+ if error:
+ 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")
+
+
+def main():
+ command_name = sys.argv[0]
+ try:
+ opts, args = getopt.getopt(list(map(force_unicode, sys.argv[1:])),
+ "vhb:f:", ["version", "help"])
+ except getopt.GetoptError as e:
+ print(str(e))
+ usage(command_name, error=True)
+ sys.exit(2)
+
+ version_tuple = VERSION
+ conf_filename = '.editorconfig'
+
+ for option, arg in opts:
+ if option in ('-h', '--help'):
+ usage(command_name)
+ sys.exit()
+ if option in ('-v', '--version'):
+ version()
+ sys.exit()
+ if option == '-f':
+ conf_filename = arg
+ if option == '-b':
+ version_tuple = split_version(arg)
+ if version_tuple is None:
+ sys.exit("Invalid version number: %s" % arg)
+
+ if len(args) < 1:
+ usage(command_name, error=True)
+ sys.exit(2)
+ filenames = args
+ multiple_files = len(args) > 1
+
+ for filename in filenames:
+ handler = EditorConfigHandler(filename, conf_filename, version_tuple)
+ try:
+ options = handler.get_configurations()
+ except (ParsingError, PathError, VersionError) as e:
+ print(str(e))
+ sys.exit(2)
+ if multiple_files:
+ print("[%s]" % filename)
+ for key, value in options.items():
+ print("%s=%s" % (key, value))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/venv/lib/python3.11/site-packages/editorconfig/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..35f562f
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/__init__.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/editorconfig/__pycache__/__main__.cpython-311.pyc b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/__main__.cpython-311.pyc
new file mode 100644
index 0000000..5343829
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/__main__.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/editorconfig/__pycache__/compat.cpython-311.pyc b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/compat.cpython-311.pyc
new file mode 100644
index 0000000..1686a75
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/compat.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/editorconfig/__pycache__/exceptions.cpython-311.pyc b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/exceptions.cpython-311.pyc
new file mode 100644
index 0000000..511078f
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/exceptions.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/editorconfig/__pycache__/fnmatch.cpython-311.pyc b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/fnmatch.cpython-311.pyc
new file mode 100644
index 0000000..5d4a548
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/fnmatch.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/editorconfig/__pycache__/handler.cpython-311.pyc b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/handler.cpython-311.pyc
new file mode 100644
index 0000000..8504183
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/handler.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/editorconfig/__pycache__/ini.cpython-311.pyc b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/ini.cpython-311.pyc
new file mode 100644
index 0000000..65d5307
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/ini.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/editorconfig/__pycache__/version.cpython-311.pyc b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/version.cpython-311.pyc
new file mode 100644
index 0000000..2f937fa
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/version.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/editorconfig/__pycache__/versiontools.cpython-311.pyc b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/versiontools.cpython-311.pyc
new file mode 100644
index 0000000..69373b5
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/__pycache__/versiontools.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/editorconfig/compat.py b/venv/lib/python3.11/site-packages/editorconfig/compat.py
new file mode 100644
index 0000000..4b9f8ca
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/compat.py
@@ -0,0 +1,24 @@
+"""EditorConfig Python2/Python3 compatibility utilities"""
+import sys
+
+
+__all__ = ['force_unicode', 'u']
+
+
+if sys.version_info[0] == 2:
+ text_type = unicode
+else:
+ text_type = str
+
+
+def force_unicode(string):
+ if not isinstance(string, text_type):
+ string = text_type(string, encoding='utf-8')
+ return string
+
+
+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/venv/lib/python3.11/site-packages/editorconfig/exceptions.py b/venv/lib/python3.11/site-packages/editorconfig/exceptions.py
new file mode 100644
index 0000000..c25f681
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/exceptions.py
@@ -0,0 +1,27 @@
+"""EditorConfig exception classes
+
+Licensed under Simplified BSD License (see LICENSE.BSD file).
+
+"""
+
+
+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
+
+
+class ParsingError(_ParsingError, EditorConfigError):
+ """Error raised if an EditorConfig file could not be parsed"""
+
+
+class PathError(ValueError, EditorConfigError):
+ """Error raised if invalid filepath is specified"""
+
+
+class VersionError(ValueError, EditorConfigError):
+ """Error raised if invalid version number is specified"""
diff --git a/venv/lib/python3.11/site-packages/editorconfig/fnmatch.py b/venv/lib/python3.11/site-packages/editorconfig/fnmatch.py
new file mode 100644
index 0000000..76692b8
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/fnmatch.py
@@ -0,0 +1,223 @@
+"""Filename matching with shell patterns.
+
+fnmatch(FILENAME, PATTERN) matches according to the local convention.
+fnmatchcase(FILENAME, PATTERN) always takes case in account.
+
+The functions operate by translating the pattern into a regular
+expression. They cache the compiled regular expressions for speed.
+
+The function translate(PATTERN) returns a regular expression
+corresponding to PATTERN. (It does not compile it.)
+
+Based on code from fnmatch.py file distributed with Python 2.6.
+
+Licensed under PSF License (see LICENSE.PSF file).
+
+Changes to original fnmatch module:
+- translate function supports ``*`` and ``**`` similarly to fnmatch C library
+"""
+
+import os
+import re
+
+
+__all__ = ["fnmatch", "fnmatchcase", "translate"]
+
+_cache = {}
+
+LEFT_BRACE = re.compile(
+ r"""
+
+ (?<! \\ ) # Not preceded by "\"
+
+ \{ # "{"
+
+ """, re.VERBOSE
+)
+
+RIGHT_BRACE = re.compile(
+ r"""
+
+ (?<! \\ ) # Not preceded by "\"
+
+ \} # "}"
+
+ """, re.VERBOSE
+)
+
+NUMERIC_RANGE = re.compile(
+ r"""
+ ( # Capture a number
+ [+-] ? # Zero or one "+" or "-" characters
+ \d + # One or more digits
+ )
+
+ \.\. # ".."
+
+ ( # Capture a number
+ [+-] ? # Zero or one "+" or "-" characters
+ \d + # One or more digits
+ )
+ """, re.VERBOSE
+)
+
+
+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)
+
+ An initial period in FILENAME is not special.
+ Both FILENAME and PATTERN are first case-normalized
+ if the operating system requires it.
+ If you don't want this, use fnmatchcase(FILENAME, PATTERN).
+ """
+
+ name = os.path.normpath(name).replace(os.sep, "/")
+ return fnmatchcase(name, pat)
+
+
+def cached_translate(pat):
+ if not pat in _cache:
+ res, num_groups = translate(pat)
+ regex = re.compile(res)
+ _cache[pat] = regex, num_groups
+ return _cache[pat]
+
+
+def fnmatchcase(name, pat):
+ """Test whether FILENAME matches PATTERN, including case.
+
+ This is a version of fnmatch() which doesn't case-normalize
+ its arguments.
+ """
+
+ regex, num_groups = cached_translate(pat)
+ match = regex.match(name)
+ if not match:
+ return False
+ pattern_matched = True
+ for (num, (min_num, max_num)) in zip(match.groups(), num_groups):
+ if num[0] == '0' or not (min_num <= int(num) <= max_num):
+ pattern_matched = False
+ break
+ return pattern_matched
+
+
+def translate(pat, nested=False):
+ """Translate a shell PATTERN to a regular expression.
+
+ There is no way to quote meta-characters.
+ """
+
+ index, length = 0, len(pat) # Current index and length of pattern
+ brace_level = 0
+ in_brackets = False
+ result = ''
+ is_escaped = False
+ matching_braces = (len(LEFT_BRACE.findall(pat)) ==
+ len(RIGHT_BRACE.findall(pat)))
+ numeric_groups = []
+ while index < length:
+ current_char = pat[index]
+ index += 1
+ if current_char == '*':
+ pos = index
+ if pos < length and pat[pos] == '*':
+ result += '.*'
+ else:
+ result += '[^/]*'
+ elif current_char == '?':
+ result += '[^/]'
+ elif current_char == '[':
+ if in_brackets:
+ result += '\\['
+ else:
+ pos = index
+ has_slash = False
+ while pos < length and pat[pos] != ']':
+ if pat[pos] == '/' and pat[pos-1] != '\\':
+ has_slash = True
+ break
+ pos += 1
+ if has_slash:
+ result += '\\[' + pat[index:(pos + 1)]
+ index = pos + 1
+ else:
+ if index < length and pat[index] in '!^':
+ index += 1
+ result += '[^'
+ else:
+ result += '['
+ in_brackets = True
+ elif current_char == '-':
+ if in_brackets:
+ result += current_char
+ else:
+ result += '\\' + current_char
+ elif current_char == ']':
+ if in_brackets and pat[index-2] == '\\':
+ result += '\\]'
+ else:
+ result += current_char
+ in_brackets = False
+ elif current_char == '{':
+ pos = index
+ has_comma = False
+ while pos < length and (pat[pos] != '}' or is_escaped):
+ if pat[pos] == ',' and not is_escaped:
+ has_comma = True
+ break
+ is_escaped = pat[pos] == '\\' and not is_escaped
+ pos += 1
+ if not has_comma and pos < length:
+ num_range = NUMERIC_RANGE.match(pat[index:pos])
+ if num_range:
+ numeric_groups.append(map(int, num_range.groups()))
+ result += r"([+-]?\d+)"
+ else:
+ inner_result, inner_groups = translate(pat[index:pos],
+ nested=True)
+ result += '\\{%s\\}' % (inner_result,)
+ numeric_groups += inner_groups
+ index = pos + 1
+ elif matching_braces:
+ result += '(?:'
+ brace_level += 1
+ else:
+ result += '\\{'
+ elif current_char == ',':
+ if brace_level > 0 and not is_escaped:
+ result += '|'
+ else:
+ result += '\\,'
+ elif current_char == '}':
+ if brace_level > 0 and not is_escaped:
+ result += ')'
+ brace_level -= 1
+ else:
+ result += '\\}'
+ elif current_char == '/':
+ if pat[index:(index + 3)] == "**/":
+ result += "(?:/|/.*/)"
+ index += 3
+ else:
+ result += '/'
+ elif current_char != '\\':
+ result += re.escape(current_char)
+ if current_char == '\\':
+ if is_escaped:
+ result += re.escape(current_char)
+ is_escaped = not is_escaped
+ else:
+ is_escaped = False
+ if not nested:
+ result = r'(?s)%s\Z' % result
+ return result, numeric_groups
diff --git a/venv/lib/python3.11/site-packages/editorconfig/handler.py b/venv/lib/python3.11/site-packages/editorconfig/handler.py
new file mode 100644
index 0000000..1c33c02
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/handler.py
@@ -0,0 +1,127 @@
+"""EditorConfig file handler
+
+Provides ``EditorConfigHandler`` class for locating and parsing
+EditorConfig files relevant to a given filepath.
+
+Licensed under Simplified BSD License (see LICENSE.BSD file).
+
+"""
+
+import os
+
+from editorconfig import VERSION
+from editorconfig.exceptions import PathError, VersionError
+from editorconfig.ini import EditorConfigParser
+
+
+__all__ = ['EditorConfigHandler']
+
+
+def get_filenames(path, filename):
+ """Yield full filepath for filename in each directory in and above path"""
+ path_list = []
+ while True:
+ path_list.append(os.path.join(path, filename))
+ newpath = os.path.dirname(path)
+ if path == newpath:
+ break
+ path = newpath
+ return path_list
+
+
+class EditorConfigHandler(object):
+
+ """
+ Allows locating and parsing of EditorConfig files for given filename
+
+ In addition to the constructor a single public method is provided,
+ ``get_configurations`` which returns the EditorConfig options for
+ the ``filepath`` specified to the constructor.
+
+ """
+
+ def __init__(self, filepath, conf_filename='.editorconfig',
+ version=VERSION):
+ """Create EditorConfigHandler for matching given filepath"""
+ self.filepath = filepath
+ self.conf_filename = conf_filename
+ self.version = version
+ self.options = None
+
+ def get_configurations(self):
+
+ """
+ Find EditorConfig files and return all options matching filepath
+
+ Special exceptions that may be raised by this function include:
+
+ - ``VersionError``: self.version is invalid EditorConfig version
+ - ``PathError``: self.filepath is not a valid absolute filepath
+ - ``ParsingError``: improperly formatted EditorConfig file found
+
+ """
+
+ self.check_assertions()
+ path, filename = os.path.split(self.filepath)
+ conf_files = get_filenames(path, self.conf_filename)
+
+ # Attempt to find and parse every EditorConfig file in filetree
+ for filename in conf_files:
+ parser = EditorConfigParser(self.filepath)
+ parser.read(filename)
+
+ # Merge new EditorConfig file's options into current options
+ old_options = self.options
+ self.options = parser.options
+ if old_options:
+ self.options.update(old_options)
+
+ # Stop parsing if parsed file has a ``root = true`` option
+ if parser.root_file:
+ break
+
+ self.preprocess_values()
+ return self.options
+
+ def check_assertions(self):
+
+ """Raise error if filepath or version have invalid values"""
+
+ # Raise ``PathError`` if filepath isn't an absolute path
+ if not os.path.isabs(self.filepath):
+ raise PathError("Input file must be a full path name.")
+
+ # Raise ``VersionError`` if version specified is greater than current
+ if self.version is not None and self.version[:3] > VERSION[:3]:
+ raise VersionError(
+ "Required version is greater than the current version.")
+
+ def preprocess_values(self):
+
+ """Preprocess option values for consumption by plugins"""
+
+ 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"]:
+ if name in opts:
+ opts[name] = opts[name].lower()
+
+ # Set indent_size to "tab" if indent_size is unspecified and
+ # indent_style is set to "tab".
+ if (opts.get("indent_style") == "tab" and
+ not "indent_size" in opts and self.version >= (0, 10, 0)):
+ opts["indent_size"] = "tab"
+
+ # Set tab_width to indent_size if indent_size is specified and
+ # tab_width is unspecified
+ 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/venv/lib/python3.11/site-packages/editorconfig/ini.py b/venv/lib/python3.11/site-packages/editorconfig/ini.py
new file mode 100644
index 0000000..c603d79
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/ini.py
@@ -0,0 +1,183 @@
+"""EditorConfig file parser
+
+Based on code from ConfigParser.py file distributed with Python 2.6.
+
+Licensed under PSF License (see LICENSE.PSF file).
+
+Changes to original ConfigParser:
+
+- Special characters can be used in section names
+- Octothorpe can be used for comments (not just at beginning of line)
+- Only track INI options in sections that match target filename
+- Stop parsing files with when ``root = true`` is found
+
+"""
+
+import posixpath
+import re
+from codecs import open
+from collections import OrderedDict
+from os import sep
+from os.path import dirname, normpath
+
+from editorconfig.compat import u
+from editorconfig.exceptions import ParsingError
+from editorconfig.fnmatch import fnmatch
+
+
+__all__ = ["ParsingError", "EditorConfigParser"]
+
+MAX_SECTION_LENGTH = 4096
+MAX_PROPERTY_LENGTH= 50
+MAX_VALUE_LENGTH = 255
+
+
+class EditorConfigParser(object):
+
+ """Parser for EditorConfig-style configuration files
+
+ Based on RawConfigParser from ConfigParser.py in Python 2.6.
+ """
+
+ # Regular expressions for parsing section headers and options.
+ # Allow ``]`` and escaped ``;`` and ``#`` characters in section headers
+ SECTCRE = re.compile(
+ r"""
+
+ \s * # Optional whitespace
+ \[ # Opening square brace
+
+ (?P<header> # One or more characters excluding
+ ( [^\#;] | \\\# | \\; ) + # unescaped # and ; characters
+ )
+
+ \] # Closing square brace
+
+ """, re.VERBOSE
+ )
+ # Regular expression for parsing option name/values.
+ # Allow any amount of whitespaces, followed by separator
+ # (either ``:`` or ``=``), followed by any amount of whitespace and then
+ # any characters to eol
+ OPTCRE = re.compile(
+ r"""
+
+ \s * # Optional whitespace
+ (?P<option> # One or more characters excluding
+ [^:=\s] # : a = characters (and first
+ [^:=] * # must not be whitespace)
+ )
+ \s * # Optional whitespace
+ (?P<vi>
+ [:=] # Single = or : character
+ )
+ \s * # Optional whitespace
+ (?P<value>
+ . * # One or more characters
+ )
+ $
+
+ """, re.VERBOSE
+ )
+
+ def __init__(self, filename):
+ self.filename = filename
+ self.options = OrderedDict()
+ self.root_file = False
+
+ def matches_filename(self, config_filename, glob):
+ """Return True if section glob matches filename"""
+ config_dirname = normpath(dirname(config_filename)).replace(sep, '/')
+ glob = glob.replace("\\#", "#")
+ glob = glob.replace("\\;", ";")
+ if '/' in glob:
+ if glob.find('/') == 0:
+ glob = glob[1:]
+ glob = posixpath.join(config_dirname, glob)
+ else:
+ glob = posixpath.join('**/', glob)
+ return fnmatch(self.filename, glob)
+
+ def read(self, filename):
+ """Read and parse single EditorConfig file"""
+ try:
+ fp = open(filename, encoding='utf-8')
+ except IOError:
+ return
+ self._read(fp, filename)
+ fp.close()
+
+ def _read(self, fp, fpname):
+ """Parse a sectioned setup file.
+
+ The sections in setup file contains a title line at the top,
+ indicated by a name in square brackets (`[]'), plus key/value
+ options lines, indicated by `name: value' format lines.
+ Continuations are represented by an embedded newline then
+ leading whitespace. Blank lines, lines beginning with a '#',
+ and just about everything else are ignored.
+ """
+ in_section = False
+ matching_section = False
+ optname = None
+ lineno = 0
+ e = None # None, or an exception
+ while True:
+ 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 '#;':
+ continue
+ # a section header or option header?
+ else:
+ # is it a section header?
+ mo = self.SECTCRE.match(line)
+ if mo:
+ sectname = mo.group('header')
+ if len(sectname) > MAX_SECTION_LENGTH:
+ continue
+ in_section = True
+ matching_section = self.matches_filename(fpname, sectname)
+ # So sections can't start with a continuation line
+ optname = None
+ # an option line?
+ else:
+ mo = self.OPTCRE.match(line)
+ if mo:
+ optname, vi, optval = mo.group('option', 'vi', 'value')
+ if ';' in optval or '#' in optval:
+ # ';' and '#' are comment delimiters only if
+ # preceeded by a spacing character
+ m = re.search('(.*?) [;#]', optval)
+ if m:
+ optval = m.group(1)
+ optval = optval.strip()
+ # allow empty values
+ if optval == '""':
+ optval = ''
+ optname = self.optionxform(optname.rstrip())
+ if (len(optname) > MAX_PROPERTY_LENGTH or
+ len(optval) > MAX_VALUE_LENGTH):
+ continue
+ if not in_section and optname == 'root':
+ self.root_file = (optval.lower() == 'true')
+ if matching_section:
+ self.options[optname] = optval
+ else:
+ # a non-fatal parsing error occurred. set up the
+ # exception but keep going. the exception will be
+ # raised at the end of the file and will contain a
+ # list of all bogus lines
+ if not e:
+ e = ParsingError(fpname)
+ e.append(lineno, repr(line))
+ # if any parsing errors occurred, raise an exception
+ if e:
+ raise e
+
+ def optionxform(self, optionstr):
+ return optionstr.lower()
diff --git a/venv/lib/python3.11/site-packages/editorconfig/version.py b/venv/lib/python3.11/site-packages/editorconfig/version.py
new file mode 100644
index 0000000..1dc3e55
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/version.py
@@ -0,0 +1 @@
+VERSION = (0, 12, 4, "final")
diff --git a/venv/lib/python3.11/site-packages/editorconfig/versiontools.py b/venv/lib/python3.11/site-packages/editorconfig/versiontools.py
new file mode 100644
index 0000000..01744f8
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/editorconfig/versiontools.py
@@ -0,0 +1,35 @@
+"""EditorConfig version tools
+
+Provides ``join_version`` and ``split_version`` classes for converting
+__version__ strings to VERSION tuples and vice versa.
+
+"""
+
+import re
+
+
+__all__ = ['join_version', 'split_version']
+
+
+_version_re = re.compile(r'^(\d+)\.(\d+)\.(\d+)(\..*)?$', re.VERBOSE)
+
+
+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]
+ return version
+
+
+def split_version(version):
+ """Return VERSION tuple for given string representation of version"""
+ match = _version_re.search(version)
+ if not match:
+ return None
+ else:
+ 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:]
+ return tuple(split_version)