ThirdParty/EditorConfig/editorconfig/handler.py

changeset 6099
a7fecbc392d7
child 6161
91456f5321b5
equal deleted inserted replaced
6098:a1d10c6ce103 6099:a7fecbc392d7
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 PSF License (see LICENSE.txt file).
7
8 """
9
10 import os
11
12 from editorconfig import VERSION
13 from editorconfig.ini import EditorConfigParser
14 from editorconfig.exceptions import PathError, VersionError
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"]

eric ide

mercurial