0
# Configuration System
1
2
The configuration system provides comprehensive parsing of command-line arguments and configuration files with hierarchical inheritance. It manages error code selection, file matching patterns, runtime options, and supports multiple configuration file formats.
3
4
## Capabilities
5
6
### Configuration Parser
7
8
The main configuration parsing class that handles CLI arguments and configuration files with inheritance support.
9
10
```python { .api }
11
class ConfigurationParser:
12
"""
13
Responsible for parsing configuration from files and CLI.
14
15
Supports two types of configurations:
16
- Run configurations: UI-related options (verbosity, debug, etc.)
17
- Check configurations: File and error checking options
18
"""
19
20
# Configuration file options
21
CONFIG_FILE_OPTIONS = ('convention', 'select', 'ignore', 'add-select',
22
'add-ignore', 'match', 'match-dir')
23
24
# Base error selection options (mutually exclusive)
25
BASE_ERROR_SELECTION_OPTIONS = ('ignore', 'select', 'convention')
26
27
# Default patterns
28
DEFAULT_MATCH_RE = '(?!test_).*\.py' # Files to check
29
DEFAULT_MATCH_DIR_RE = '[^\.].*' # Directories to search
30
DEFAULT_CONVENTION = conventions.pep257 # Default error codes
31
32
# Supported config files
33
PROJECT_CONFIG_FILES = ('setup.cfg', 'tox.ini', '.pep257')
34
35
def __init__(self):
36
"""Create a configuration parser."""
37
38
def parse(self):
39
"""
40
Parse the configuration from CLI and config files.
41
42
If one of BASE_ERROR_SELECTION_OPTIONS was selected, overrides all
43
error codes and disregards config file error code settings.
44
45
Raises:
46
IllegalConfiguration: If configuration is invalid
47
"""
48
49
def get_default_run_configuration(self):
50
"""
51
Return a RunConfiguration object set with default values.
52
53
Returns:
54
RunConfiguration: Default runtime configuration
55
"""
56
57
def get_user_run_configuration(self):
58
"""
59
Return the user's run configuration.
60
61
Returns:
62
RunConfiguration: User runtime configuration
63
"""
64
65
def get_files_to_check(self):
66
"""
67
Generate files and error codes to check on each one.
68
69
Walk directory trees under arguments and yield filenames that match
70
under each directory that matches match_dir pattern. Locates
71
configuration for each file and yields (filename, [error_codes]).
72
73
Returns:
74
generator: tuples of (filename, list of error codes)
75
76
Raises:
77
IllegalConfiguration: If invalid configuration file found
78
"""
79
```
80
81
Usage examples:
82
83
```python
84
from pep257 import ConfigurationParser, IllegalConfiguration
85
86
# Basic configuration parsing
87
conf = ConfigurationParser()
88
try:
89
conf.parse()
90
run_config = conf.get_user_run_configuration()
91
92
# Process files with their specific error codes
93
for filename, error_codes in conf.get_files_to_check():
94
print(f"Checking {filename} for codes: {error_codes}")
95
96
except IllegalConfiguration as e:
97
print(f"Configuration error: {e}")
98
```
99
100
### Configuration Objects
101
102
Named tuples that represent different types of configuration settings.
103
104
```python { .api }
105
RunConfiguration = namedtuple('RunConfiguration',
106
('explain', 'source', 'debug', 'verbose', 'count'))
107
"""
108
Configuration for runtime behavior.
109
110
Fields:
111
- explain: bool, show explanation of each error
112
- source: bool, show source for each error
113
- debug: bool, print debug information
114
- verbose: bool, print status information
115
- count: bool, print total number of errors
116
"""
117
118
CheckConfiguration = namedtuple('CheckConfiguration',
119
('checked_codes', 'match', 'match_dir'))
120
"""
121
Configuration for error checking.
122
123
Fields:
124
- checked_codes: set, error codes to check for
125
- match: str, regex pattern for filenames to check
126
- match_dir: str, regex pattern for directories to search
127
"""
128
```
129
130
### Configuration File Support
131
132
The system supports multiple configuration file formats with hierarchical inheritance:
133
134
```python
135
# setup.cfg example
136
[pep257]
137
ignore = D203,D213
138
match = .*\.py
139
match-dir = [^\.].*
140
explain = true
141
142
# tox.ini example
143
[pep257]
144
select = D100,D101,D102
145
add-ignore = D105
146
convention = pep257
147
148
# .pep257 example
149
[pep257]
150
inherit = false
151
ignore = D200,D201,D202
152
```
153
154
Configuration inheritance algorithm:
155
1. Check current directory for config file
156
2. If not found, inherit from parent directory
157
3. If found, optionally merge with parent (inherit = true)
158
4. CLI options always override config file settings
159
160
### Configuration Validation
161
162
```python { .api }
163
class IllegalConfiguration(Exception):
164
"""An exception for illegal configurations."""
165
pass
166
167
def check_initialized(method):
168
"""
169
Decorator to check that configuration object was initialized.
170
171
Parameters:
172
- method: function, method to wrap
173
174
Returns:
175
function: Wrapped method that checks initialization
176
"""
177
```
178
179
### Internal Configuration Methods
180
181
```python { .api }
182
class ConfigurationParser:
183
"""Additional internal methods for configuration processing."""
184
185
def _get_config(self, node):
186
"""
187
Get and cache the run configuration for node.
188
189
Parameters:
190
- node: str, file or directory path
191
192
Returns:
193
CheckConfiguration: Configuration for the node
194
"""
195
196
def _read_configuration_file(self, path):
197
"""
198
Try to read and parse path as a pep257 configuration file.
199
200
Parameters:
201
- path: str, configuration file path
202
203
Returns:
204
tuple: (options, should_inherit)
205
206
Raises:
207
IllegalConfiguration: If configuration is invalid
208
"""
209
210
def _merge_configuration(self, parent_config, child_options):
211
"""
212
Merge parent config into child options.
213
214
Parameters:
215
- parent_config: CheckConfiguration, parent configuration
216
- child_options: options object, child configuration
217
218
Returns:
219
CheckConfiguration: Merged configuration
220
"""
221
222
def _validate_options(self, options):
223
"""
224
Validate mutually exclusive options.
225
226
Parameters:
227
- options: options object to validate
228
229
Returns:
230
bool: True if options are valid
231
"""
232
233
def _has_exclusive_option(self, options):
234
"""
235
Return True if one or more exclusive options were selected.
236
237
Parameters:
238
- options: options object to check
239
240
Returns:
241
bool: True if exclusive options present
242
"""
243
244
def _get_exclusive_error_codes(self, options):
245
"""
246
Extract error codes from selected exclusive option.
247
248
Parameters:
249
- options: options object
250
251
Returns:
252
set: Error codes to check
253
"""
254
255
def _set_add_options(self, checked_codes, options):
256
"""
257
Set checked_codes by add_ignore or add_select options.
258
259
Parameters:
260
- checked_codes: set, error codes to modify in place
261
- options: options object with add selections
262
"""
263
264
def _create_run_config(self, options):
265
"""
266
Create a RunConfiguration object from options.
267
268
Parameters:
269
- options: options object
270
271
Returns:
272
RunConfiguration: Runtime configuration
273
"""
274
275
def _create_check_config(self, options, use_defaults=True):
276
"""
277
Create a CheckConfiguration object from options.
278
279
Parameters:
280
- options: options object
281
- use_defaults: bool, whether to use default values
282
283
Returns:
284
CheckConfiguration: Check configuration
285
"""
286
```
287
288
### Option Parser Creation
289
290
```python { .api }
291
class ConfigurationParser:
292
"""Command-line option parser creation."""
293
294
def _create_option_parser(self):
295
"""
296
Return an option parser to parse command line arguments.
297
298
Returns:
299
OptionParser: Configured option parser
300
"""
301
```
302
303
The option parser supports these command-line options:
304
305
**Run Configuration Options:**
306
- `-e, --explain`: Show explanation of each error
307
- `-s, --source`: Show source for each error
308
- `-d, --debug`: Print debug information
309
- `-v, --verbose`: Print status information
310
- `--count`: Print total number of errors
311
312
**Error Check Options:**
313
- `--select <codes>`: Choose error codes to check for
314
- `--ignore <codes>`: Choose error codes to ignore
315
- `--convention <name>`: Choose error convention (pep257)
316
- `--add-select <codes>`: Add more error codes to check
317
- `--add-ignore <codes>`: Add more error codes to ignore
318
319
**Match Options:**
320
- `--match <pattern>`: Check only files matching pattern
321
- `--match-dir <pattern>`: Search only directories matching pattern
322
323
### Utility Dictionary
324
325
```python { .api }
326
class AttrDict(dict):
327
"""Dictionary subclass with attribute access."""
328
329
def __getattr__(self, item):
330
"""
331
Get dictionary item as attribute.
332
333
Parameters:
334
- item: str, key name
335
336
Returns:
337
Any: Dictionary value
338
"""
339
```
340
341
### Available Conventions
342
343
```python { .api }
344
conventions = AttrDict({
345
'pep257': set # Set of all error codes except D203
346
})
347
```
348
349
The pep257 convention includes all available error codes except D203, which conflicts with D211 in the whitespace rules.