summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/editorconfig/ini.py
diff options
context:
space:
mode:
authorcyfraeviolae <cyfraeviolae>2024-04-03 03:10:44 -0400
committercyfraeviolae <cyfraeviolae>2024-04-03 03:10:44 -0400
commit6d7ba58f880be618ade07f8ea080fe8c4bf8a896 (patch)
treeb1c931051ffcebd2bd9d61d98d6233ffa289bbce /venv/lib/python3.11/site-packages/editorconfig/ini.py
parent4f884c9abc32990b4061a1bb6997b4b37e58ea0b (diff)
venv
Diffstat (limited to 'venv/lib/python3.11/site-packages/editorconfig/ini.py')
-rw-r--r--venv/lib/python3.11/site-packages/editorconfig/ini.py183
1 files changed, 183 insertions, 0 deletions
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()