1 | import os |
||
2 | from collections import OrderedDict |
||
3 | |||
4 | from coalib.misc.Decorators import generate_repr |
||
5 | from coalib.misc.StringConverter import StringConverter |
||
6 | from coalib.parsing.Globbing import glob_escape |
||
7 | |||
8 | |||
9 | def path(obj, *args, **kwargs): |
||
10 | return obj.__path__(*args, **kwargs) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
![]() Comprehensibility
Best Practice
introduced
by
|
|||
11 | |||
12 | |||
13 | def path_list(obj, *args, **kwargs): |
||
14 | return obj.__path_list__(*args, **kwargs) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||
15 | |||
16 | |||
17 | def url(obj, *args, **kwargs): |
||
18 | return obj.__url__(*args, **kwargs) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||
19 | |||
20 | |||
21 | def glob(obj, *args, **kwargs): |
||
22 | """ |
||
23 | Creates a path in which all special glob characters in all the |
||
24 | parent directories in the given setting are properly escaped. |
||
25 | |||
26 | :param obj: The ``Setting`` object from which the key is obtained. |
||
27 | :return: Returns a path in which special glob characters are escaped. |
||
28 | """ |
||
29 | return obj.__glob__(*args, **kwargs) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||
30 | |||
31 | |||
32 | def glob_list(obj, *args, **kwargs): |
||
33 | """ |
||
34 | Creates a list of paths in which all special glob characters in all the |
||
35 | parent directories of all paths in the given setting are properly escaped. |
||
36 | |||
37 | :param obj: The ``Setting`` object from which the key is obtained. |
||
38 | :return: Returns a list of paths in which special glob characters are |
||
39 | escaped. |
||
40 | """ |
||
41 | return obj.__glob_list__(*args, **kwargs) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||
42 | |||
43 | |||
44 | def typed_list(conversion_func): |
||
45 | """ |
||
46 | Creates a function that converts a setting into a list of elements each |
||
47 | converted with the given conversion function. |
||
48 | |||
49 | :param conversion_func: The conversion function that converts a string into |
||
50 | your desired list item object. |
||
51 | :return: A conversion function. |
||
52 | """ |
||
53 | return lambda setting: [ |
||
54 | conversion_func(StringConverter(elem)) for elem in setting] |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
55 | |||
56 | |||
57 | def typed_dict(key_type, value_type, default): |
||
58 | """ |
||
59 | Creates a function that converts a setting into a dict with the given |
||
60 | types. |
||
61 | |||
62 | :param key_type: The type conversion function for the keys. |
||
63 | :param value_type: The type conversion function for the values. |
||
64 | :param default: The default value to use if no one is given by the user. |
||
65 | :return: A conversion function. |
||
66 | """ |
||
67 | return lambda setting: { |
||
68 | key_type(StringConverter(key)): |
||
69 | value_type(StringConverter(value)) if value != "" else default |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
70 | for key, value in dict(setting).items()} |
||
71 | |||
72 | |||
73 | def typed_ordered_dict(key_type, value_type, default): |
||
74 | """ |
||
75 | Creates a function that converts a setting into an ordered dict with the |
||
76 | given types. |
||
77 | |||
78 | :param key_type: The type conversion function for the keys. |
||
79 | :param value_type: The type conversion function for the values. |
||
80 | :param default: The default value to use if no one is given by the user. |
||
81 | :return: A conversion function. |
||
82 | """ |
||
83 | return lambda setting: OrderedDict( |
||
84 | (key_type(StringConverter(key)), |
||
85 | value_type(StringConverter(value)) if value != "" else default) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
86 | for key, value in OrderedDict(setting).items()) |
||
87 | |||
88 | |||
89 | @generate_repr("key", "value", "origin", "from_cli") |
||
90 | class Setting(StringConverter): |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
91 | """ |
||
92 | A Setting consists mainly of a key and a value. It mainly offers many |
||
93 | conversions into common data types. |
||
94 | """ |
||
95 | |||
96 | def __init__(self, |
||
97 | key, |
||
98 | value, |
||
99 | origin="", |
||
100 | strip_whitespaces=True, |
||
101 | list_delimiters=(",", ";"), |
||
102 | from_cli=False, |
||
103 | remove_empty_iter_elements=True): |
||
104 | """ |
||
105 | Initializes a new Setting, |
||
106 | |||
107 | :param key: The key of the Setting. |
||
108 | :param value: The value, if you apply conversions |
||
109 | to this object these will be applied |
||
110 | to this value. |
||
111 | :param origin: The originating file. This will be |
||
112 | used for path conversions and the |
||
113 | last part will be stripped of. If |
||
114 | you want to specify a directory as |
||
115 | origin be sure to end it with a |
||
116 | directory separator. |
||
117 | :param strip_whitespaces: Whether to strip whitespaces from |
||
118 | the value or not |
||
119 | :param list_delimiters: Delimiters for list conversion |
||
120 | :param from_cli: True if this setting was read by the |
||
121 | CliParser. |
||
122 | :param remove_empty_iter_elements: Whether to remove empty elements in |
||
123 | iterable values. |
||
124 | """ |
||
125 | if not isinstance(from_cli, bool): |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||
126 | raise TypeError("from_cli needs to be a boolean value.") |
||
127 | |||
128 | StringConverter.__init__( |
||
129 | self, |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
130 | value, |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
131 | strip_whitespaces=strip_whitespaces, |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
132 | list_delimiters=list_delimiters, |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
133 | remove_empty_iter_elements=remove_empty_iter_elements) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
134 | |||
135 | self.from_cli = from_cli |
||
136 | self.key = key |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
137 | self.origin = str(origin) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
138 | |||
139 | def __path__(self, origin=None, glob_escape_origin=False): |
||
140 | """ |
||
141 | Determines the path of this setting. |
||
142 | |||
143 | Note: You can also use this function on strings, in that case the |
||
144 | origin argument will be taken in every case. |
||
145 | |||
146 | :param origin: The origin file to take if no origin is |
||
147 | specified for the given setting. If you |
||
148 | want to provide a directory, make sure it |
||
149 | ends with a directory separator. |
||
150 | :param glob_escape_origin: When this is set to true, the origin of |
||
151 | this setting will be escaped with |
||
152 | ``glob_escape``. |
||
153 | :return: An absolute path. |
||
154 | :raises ValueError: If no origin is specified in the setting |
||
155 | nor the given origin parameter. |
||
156 | """ |
||
157 | strrep = str(self).strip() |
||
158 | if os.path.isabs(strrep): |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
159 | return strrep |
||
160 | |||
161 | if hasattr(self, "origin") and self.origin != "": |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
162 | origin = self.origin |
||
163 | |||
164 | if origin is None: |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
165 | raise ValueError("Cannot determine path without origin.") |
||
166 | |||
167 | # We need to get full path before escaping since the full path |
||
168 | # may introduce unintended glob characters |
||
169 | origin = os.path.abspath(os.path.dirname(origin)) |
||
170 | |||
171 | if glob_escape_origin: |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
172 | origin = glob_escape(origin) |
||
173 | |||
174 | return os.path.normpath(os.path.join(origin, strrep)) |
||
175 | |||
176 | def __glob__(self, origin=None): |
||
177 | """ |
||
178 | Determines the path of this setting with proper escaping of its |
||
179 | parent directories. |
||
180 | |||
181 | :param origin: The origin file to take if no origin is specified |
||
182 | for the given setting. If you want to provide a |
||
183 | directory, make sure it ends with a directory |
||
184 | separator. |
||
185 | :return: An absolute path in which the parent directories |
||
186 | are escaped. |
||
187 | :raises ValueError: If no origin is specified in the setting nor the |
||
188 | given origin parameter. |
||
189 | """ |
||
190 | return Setting.__path__(self, origin, glob_escape_origin=True) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||
191 | |||
192 | def __path_list__(self): |
||
193 | """ |
||
194 | Splits the value into a list and creates a path out of each item taking |
||
195 | the origin of the setting into account. |
||
196 | |||
197 | :return: A list of absolute paths. |
||
198 | """ |
||
199 | return [Setting.__path__(elem, self.origin) for elem in self] |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||
200 | |||
201 | def __glob_list__(self): |
||
202 | """ |
||
203 | Splits the value into a list and creates a path out of each item in |
||
204 | which the special glob characters in origin are escaped. |
||
205 | |||
206 | :return: A list of absolute paths in which the special characters in |
||
207 | the parent directories of the setting are escaped. |
||
208 | """ |
||
209 | return [Setting.__glob__(elem, self.origin) for elem in self] |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||
210 | |||
211 | @property |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
212 | def key(self): |
||
213 | return self._key |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
214 | |||
215 | @key.setter |
||
216 | def key(self, key): |
||
217 | newkey = str(key) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
218 | if newkey == "": |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
219 | raise ValueError("An empty key is not allowed for a setting.") |
||
220 | |||
221 | self._key = newkey |
||
222 |