the1conf 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
the1conf/config_var.py ADDED
@@ -0,0 +1,626 @@
1
+ from __future__ import annotations
2
+
3
+ import copy
4
+ from collections.abc import Sequence, Callable
5
+ from dataclasses import dataclass
6
+ from enum import Enum, auto
7
+ from pathlib import Path
8
+ from typing import (
9
+ Any,
10
+ Generic,
11
+ Optional,
12
+ TypeAlias,
13
+ TypeVar,
14
+ Union,
15
+ get_args,
16
+ get_origin,
17
+ get_type_hints,
18
+ dataclass_transform,
19
+ TYPE_CHECKING,
20
+ )
21
+
22
+
23
+ if TYPE_CHECKING:
24
+ from .app_config import AppConfig
25
+
26
+
27
+ class _UndefinedSentinel:
28
+ pass
29
+
30
+
31
+ Undefined: TypeAlias = _UndefinedSentinel
32
+ _undef: Undefined = _UndefinedSentinel()
33
+
34
+
35
+ class PathType(Enum):
36
+ Dir = auto()
37
+ File = auto()
38
+
39
+
40
+ __NO_SEARCH__ = "__NOSEARCH__"
41
+
42
+ _T = TypeVar("_T")
43
+
44
+
45
+ class Flags:
46
+ """
47
+ Flags that control how to search for variable values in AppConfig.
48
+ These flags can be set globally in the AppConfig object or locally when calling resolve_vars() or
49
+ per config variables.
50
+
51
+ Not None flag values override other values with the following precedence:
52
+ ConfigVariableDef > resolve_vars() parameters > AppConfig global flags.
53
+ Which means that a not None value in a ConfVarDef directive will overrride a global flag value defined in AppConfig. And also that a None value in a ConfVarDef directive
54
+ will not override the value set in resolve_vars() parameters or an AppConfig global flags.
55
+
56
+ Attributes:
57
+ no_env_search (bool|None): don't search values in the environment.
58
+ no_value_search (bool|None): don't search values in the values dict.
59
+ no_conffile_search (bool|None): don't search values in the configuration file.
60
+ no_search (bool|None): don't search values in any location.
61
+ click_key_conversion (bool|None): use the variable name converted to lower case and with dashes converted to underscores as
62
+ the key to search in values.
63
+ allow_override (bool|None): allow overriding variable in the configuration when calling resolve_vars.
64
+ no_exception (bool|None): don't raise exception when no value is found for a variable.
65
+ """
66
+
67
+ _no_env_search: bool | None
68
+ _no_value_search: bool | None
69
+ _no_conffile_search: bool | None
70
+ _no_search: bool | None
71
+ _click_key_conversion: bool | None
72
+ _allow_override: bool | None
73
+ _no_exception: bool | None
74
+
75
+ def __init__(
76
+ self,
77
+ *,
78
+ no_env_search: Optional[bool] = None,
79
+ no_value_search: Optional[bool] = None,
80
+ no_conffile_search: Optional[bool] = None,
81
+ no_search: Optional[bool] = None,
82
+ click_key_conversion: Optional[bool] = None,
83
+ allow_override: Optional[bool] = None,
84
+ no_exception: Optional[bool] = None,
85
+ ) -> None:
86
+ self._no_env_search = no_env_search
87
+ self._no_value_search = no_value_search
88
+ self._no_conffile_search = no_conffile_search
89
+ self._no_search = no_search
90
+ if self._no_search:
91
+ self._no_env_search = True
92
+ self._no_value_search = True
93
+ self._no_conffile_search = True
94
+ self._click_key_conversion = click_key_conversion
95
+ self._allow_override = allow_override
96
+ self._no_exception = no_exception
97
+
98
+ def merge(self, *, inplace: bool = False, other: Flags) -> Flags | None:
99
+ """
100
+ Merge the current flags with the given flags.
101
+ If inplace is True then modify the current object, otherwise return a new Flags object.
102
+
103
+ Flags given as parameters have precedence over the current object values if they are not None.
104
+ """
105
+ cur_no_search: Optional[bool]
106
+ cur_no_env_search: Optional[bool]
107
+ cur_no_value_search: Optional[bool]
108
+ cur_no_conffile_search: Optional[bool]
109
+ cur_click_key_conversion: Optional[bool]
110
+ cur_allow_override: Optional[bool]
111
+ cur_no_exception: Optional[bool]
112
+
113
+ cur_no_search = (
114
+ other._no_search if other._no_search is not None else self._no_search
115
+ )
116
+ if cur_no_search:
117
+ cur_no_env_search = True
118
+ cur_no_value_search = True
119
+ cur_no_conffile_search = True
120
+ else:
121
+ cur_no_env_search = (
122
+ other._no_env_search
123
+ if other._no_env_search is not None
124
+ else self._no_env_search
125
+ )
126
+ cur_no_value_search = (
127
+ other._no_value_search
128
+ if other._no_value_search is not None
129
+ else self._no_value_search
130
+ )
131
+ cur_no_conffile_search = (
132
+ other._no_conffile_search
133
+ if other._no_conffile_search is not None
134
+ else self._no_conffile_search
135
+ )
136
+ cur_click_key_conversion = (
137
+ other._click_key_conversion
138
+ if other._click_key_conversion is not None
139
+ else self._click_key_conversion
140
+ )
141
+ cur_allow_override = (
142
+ other._allow_override
143
+ if other._allow_override is not None
144
+ else self._allow_override
145
+ )
146
+ cur_no_exception = (
147
+ other._no_exception if other._no_exception is not None else self._no_exception
148
+ )
149
+ if not inplace:
150
+ return Flags(
151
+ no_env_search=cur_no_env_search,
152
+ no_value_search=cur_no_value_search,
153
+ no_conffile_search=cur_no_conffile_search,
154
+ no_search=cur_no_search,
155
+ click_key_conversion=cur_click_key_conversion,
156
+ allow_override=cur_allow_override,
157
+ no_exception=cur_no_exception,
158
+ )
159
+ else:
160
+ self._no_env_search = cur_no_env_search
161
+ self._no_value_search = cur_no_value_search
162
+ self._no_conffile_search = cur_no_conffile_search
163
+ self._no_search = cur_no_search
164
+ self._click_key_conversion = cur_click_key_conversion
165
+ self._allow_override = cur_allow_override
166
+ self._no_exception = cur_no_exception
167
+ return None
168
+
169
+ @property
170
+ def no_env_search(self) -> bool:
171
+ return (
172
+ False
173
+ if self._no_env_search is None or self._no_env_search == __NO_SEARCH__
174
+ else self._no_env_search
175
+ )
176
+
177
+ @property
178
+ def no_value_search(self) -> bool:
179
+ return (
180
+ False
181
+ if self._no_value_search is None or self._no_value_search == __NO_SEARCH__
182
+ else self._no_value_search
183
+ )
184
+
185
+ @property
186
+ def no_conffile_search(self) -> bool:
187
+ return (
188
+ False
189
+ if self._no_conffile_search is None
190
+ or self._no_conffile_search == __NO_SEARCH__
191
+ else self._no_conffile_search
192
+ )
193
+
194
+ @property
195
+ def no_search(self) -> bool:
196
+ return False if self._no_search is None else self._no_search
197
+
198
+ @property
199
+ def click_key_conversion(self) -> bool:
200
+ return False if self._click_key_conversion is None else self._click_key_conversion
201
+
202
+ @property
203
+ def allow_override(self) -> bool:
204
+ return False if self._allow_override is None else self._allow_override
205
+
206
+ @property
207
+ def no_exception(self) -> bool:
208
+ return False if self._no_exception is None else self._no_exception
209
+
210
+
211
+ @dataclass_transform()
212
+ class ConfigVarDef(Generic[_T]):
213
+ """
214
+ Definition of an application configuration variable.
215
+
216
+ Attribute of this class are called configuration directives that are used to specify the configuration of the application with the AppConfig class.
217
+
218
+ Configuration are used indirectly by defining attributes of an AppConfig subclass with the configvar() function that creates ConfigVarDef objects:
219
+ class MyAppConfig(AppConfig):
220
+ my_var: int = configvar(Default=1)
221
+
222
+ The method resolve_vars() of the AppConfig class uses these configuration variable definitions to look for the values of the variables as explained in its documentation.
223
+ Each configuration variable definition contains several directives to define how to look for the values of the variables in a dictionnarary that can be the CLI parameters,
224
+ or a configuration file, or an environment variables or a computation defined by a python Callable.
225
+
226
+ Two directive are not specified in the constructor of ConfigVarDef because they are inferred from the attribute name and type hint:
227
+ - Name : the name of the variable, inferred from the attribute name.
228
+ - TypeInfo : the type to which to cast the variable value, inferred from the attribute type hint. Must be a python builtin type or a class or a list of
229
+ builtin types.
230
+ Here how to get the list of python builtin types:
231
+ print([t.__name__ for t in __builtins__.__dict__.values() if isinstance(t, type)])
232
+ Lists are handle with a specific processing detail below in the paragraph 'Lists'.
233
+ Complex casting can be handle with a transfom Eval Form or with a class that implements the complex type.
234
+ Optional value are supported like Optional[int] or Union[str, None] to indicate that the variable can be None.
235
+ When the type hint is missing the variable is considered to be of type str.
236
+
237
+ The directives that can be specified in configvar() are:
238
+
239
+ - Help [optional]: a help string that describes the variable.
240
+ - Default [optional]: the default value, can be a value or an Eval Form (see below explanation on Eval forms) whose
241
+ returned value will be the value of the variable if no other value has been found.
242
+ See paragraph about None below for more information.
243
+ - EnvName [optional ]: the name of the environment variable that can contain the value. By default search for Name
244
+ - FileKey [optional ]: the key to look for in the configuration file, key can be in the form a1.a2.a3 (attributes separated by dots) to indicate
245
+ nested namespaces (see AppConfig documentation). By default search for Name.
246
+ - ValueKey [optional ]: the key to look for in the "Values" dict. by default search for Name. None value are ignored.
247
+ If the constructor parameter click_key_conversion flag (see below for flags) is true then the default value is the Name in lowercase and with '-' replaced by '_'
248
+ - Transform : an Eval Form (see below explanation on Eval forms) that transform the value found for the variable and produce another value that will be the value
249
+ of the variable before possible casting (like explain in TypeInfo).
250
+ - Contexts [optional ]: a list of names indicating in which context the variable is valid. If one of the context names passed at variable resolution to
251
+ AppConfig.resolve_vars() matches on e of the context names of the variable or if the variable has no Contexts directive then the variable is
252
+ considered for resolution.
253
+ - SplitToLists [optional ]: Indicates that the value found must be split in order to produce a list of string. The value
254
+ of the directive is the list separator or True if the separator is a comma. Value in the string list will be casted to the type specified in TypeInfo.
255
+ See the paragraph below about Lists that explain how list handled.
256
+ - CanBeRelativeTo [optional]: a directory path or the name of another key that resolves in a directory path.
257
+ If TypeInfo is a Path and the retrieved value is not an empty string nor None nor an absolute path then
258
+ transform the value to an absolute path with the given directory as parent directory.
259
+ See details below on how Path are processed.
260
+ - MakeDirs [optional ]: a PathType that indicates the type of Path for which directories are to be created if they do not exist yet.
261
+ if PathType is:
262
+ - Dir : create the hierarchy of directory necessary to contains this directory as well as the directory itself
263
+ - File: create the parent hierarchy of directory necessary to contains this file
264
+ See details below on how Path are processed.
265
+
266
+ - Flag directives:
267
+ These directives can also be defined globally in the AppConfig object or when calling resolve_vars().Flags defined in a ConfigVarDef override
268
+ the other values if they are defined.
269
+ - NoDirProcessings [optional ]: don't run specific Path processing for this variable.
270
+ - NoEnvSearch [optional ]: boolean, False by default. If true the value of the variable is not searched in the Environment.
271
+ - NoValueSearch[optional ]: boolean, False by default. If true the value of the variable is not searched in the values dict.
272
+ - NoConffileSearch [optional ]: boolean, False by default. If true the value of the variable is not searched in the configuration file.
273
+ - ClickKeyConversion [optional ]: boolean, False by default. If true the value of the variable is converted using Click key conversion.
274
+ - AllowOverride [optional ]: boolean, False by default. If true the variable value can be overridden by another context.
275
+ - NoException [optional ]: boolean, False by default. If true no exception is thrown if the variable value is not found.
276
+ - NoSearch [optional] : boolean, False by default. It true the value of the variable is not searched in the Environment, the values or the configuration
277
+ file. It's equivaleut to set the directives NoEnvSearch, NoValueSearch, NoConffileSearch to True. In this case the value of the variable should be defined by
278
+ the Default directive.
279
+
280
+ For backward compatibilty the special value __NO_SEARCH__ for EnvName, ConfigKey, FileKey and ValueKey are still supported but it's recommended to use
281
+ the NoEnvSearch, NoValueSearch, NoConffileSearch or NoSearch directives instead.
282
+
283
+ By default throw an exception if no value are found except if no_exception is True
284
+
285
+ Eval Forms:
286
+ -----------
287
+
288
+ an eval form is a callable that is evaluated to compute a value for a variable. Eval forms can be used in the Default directive or the
289
+ Transform directive.
290
+
291
+ The callable receives three parameters: the variable name, this configuration object and the current value found for the variable if one has been found
292
+ in the case of a Transform directive.
293
+
294
+ The expression can use value already defined in this application configuration object by using the first parameter of the callable which is the AppConfig object itself,
295
+ knowing that variables are evaluated in the order they are defined.
296
+
297
+ In the case of a Default directive the third parameter of the callable will be None.
298
+ In the case of a Transform directive the third parameter of the callable may be None if no value have been found and
299
+ the 'no_exception' global flag is set to True, otherwise it will be the value found for the variable before transformation.
300
+
301
+ The returned value from the evaluation of the callable will be used to set the variable value before casting to TypeInfo.
302
+ Note that the eventual type casting will be done after the Eval call.
303
+ It's up to the caller to deal with the returned value.
304
+
305
+ Note that the libraries used in Eval Forms must be imported in the module that defines the form.
306
+
307
+ !!Warning!!: Default and Transform directives should be set or return a value that must be 'castable' to the type defined by TypeInfo.
308
+ For example if a variable is declared as a class that accept a string in its constructor then the Default directive should be a string or an Eval
309
+ Form that returns a string not the class instance.
310
+
311
+ Path and Path list TypeInfo variables:
312
+ --------------------------------------
313
+
314
+ If a variable has a TypeInfo that is a Path or a list of Path there a dedicated processing that applies on the
315
+ value found for them.
316
+ This processing takes place at the end of the processing of normal variable and occurs when:
317
+ - the TypeInfo is a Path or a list of Path
318
+ - a value for the variable was found
319
+ - the directive NoDirProcessing is False
320
+
321
+ The specific processing is the following on the Path or on each of the Path in the list of Path:
322
+ - CanBeRelativeTo: if this directive has a value that can be a path-like directory or the name of another key already defined
323
+ that resolves in a path-like directory and the value found is not an absolute Path:
324
+ - then make a Path with the CanBeRelativeTo directory as parent and the value found as its child.
325
+ - MakeDirs: if this directive is True , then create the necessary directories of the path if they don't exist yet.
326
+ - Call the 'expanduser()' and 'resolve()' method on the resulting Path.
327
+
328
+ List:
329
+ -----
330
+
331
+ All values found are strings that should be casted to the type specified in TypeInfo inferred from the type hint of the variable.
332
+ Only list of single type are supported like list[int], list[str], list[MyClass], etc.
333
+ The value is considered as a list when SplitToList is not False and a value was found for the variable.
334
+ In this case the temporaray string value found for the variable is split with the string 'split()' method to generate
335
+ a list of string.
336
+ Then all items of the list of strings are casted to the specified TypeInfo.
337
+
338
+ Contexts:
339
+ --------
340
+ Every configuration variable can specify a list of context(s) in which it is valid.
341
+ When resolving variables it is also possible to specify for which context(s) the resolution must be done.
342
+
343
+ When one or several contexts are specify for the resolution then only the variable valid for these contexts will be considered for resolution
344
+ as well as the VarDef without Context directive. Variable defined without Context directive are common to all context, the one with a Context directive
345
+ are specific to their contexts.
346
+
347
+ This allows to define variables that are specific to some context and to resolve only these variables when needed.
348
+ When the flage AllowOverride is False and several resolutions are done, then variables are evaluated only once even if they are valid in several
349
+ of the requested context(s), only the first valid context is used.
350
+
351
+ None value:
352
+ ----------
353
+ All the VarDef valid for the involved contexts will be resolved and the one for which no value have been found will be set to None if the
354
+ flag 'no_exception' is True.
355
+
356
+ If the flag 'no_exception' is false and one varDef for the context has no value then an exception is raised.
357
+
358
+ Whatever is the value of the flag 'no_exception' it is possible to set a value to None either with the 'Default' directive or with
359
+ an Eval Form or a None value in one of the search location.
360
+
361
+ Note on implementation:
362
+ -----------------------
363
+ ConfigVarDef is a descriptor class that defines the __get__ and __set__ methods.
364
+ This allows to define configuration variables as class attributes on AppConfig subclasses.
365
+ The __set_name__ method is used to set the Name and TypeInfo directives based on the attribute name and type hint.
366
+ """
367
+
368
+ _name: Optional[str] = None
369
+ _help: str = ""
370
+ _default: Any | Callable[[str, Any, Any], Any] | Undefined = _undef
371
+ _env_name: Optional[str] = None
372
+ _file_key: Optional[str] = None
373
+ _value_key: Optional[str] = None
374
+ _type_info: Any = None
375
+ _transform: Optional[Callable[[str, Any, Any], Any]] = None
376
+ _contexts: Optional[Sequence[str]] = None
377
+ _split_to_list: Optional[bool | str | None] = None
378
+ _can_be_relative_to: Optional[Path | str] = None
379
+ _make_dirs: Optional[PathType] = None
380
+ _no_dir_processing: Optional[bool] = None
381
+
382
+ def __init__(
383
+ self,
384
+ *,
385
+ Help: str = "",
386
+ Default: Any | Callable[[str, Any, Any], Any] | Undefined = _undef,
387
+ EnvName: Optional[str] = None,
388
+ FileKey: Optional[str] = None,
389
+ ValueKey: Optional[str] = None,
390
+ Transform: Optional[Callable[[str, Any, Any], Any]] = None,
391
+ CanBeRelativeTo: Optional[Path | str] = None,
392
+ Contexts: Optional[Sequence[str]] = None,
393
+ MakeDirs: Optional[PathType] = None,
394
+ SplitToList: Optional[bool | str] = None,
395
+ NoDirProcessing: Optional[bool] = None,
396
+ NoSearch: Optional[bool] = None,
397
+ NoEnvSearch: Optional[bool] = None,
398
+ NoValueSearch: Optional[bool] = None,
399
+ NoConffileSearch: Optional[bool] = None,
400
+ ClickKeyConversion: Optional[bool] = None,
401
+ AllowOverride: Optional[bool] = None,
402
+ NoException: Optional[bool] = None,
403
+ ) -> None:
404
+ """Initialize the configuration variable definition.
405
+ Should not be used directly but be used through the function configvar() to define a configuration variable as a class attribute
406
+ on an AppConfig subclass like this:
407
+ class MyCfg(AppConfig):
408
+ my_var: int = configvar(Default=1)
409
+
410
+ """
411
+ self._help = Help
412
+ self.__doc__ = Help
413
+ self._default = Default
414
+ self._env_name = EnvName
415
+ self._file_key = FileKey
416
+ self._value_key = ValueKey
417
+ self._no_search = NoSearch
418
+ self._transform = Transform
419
+ self._can_be_relative_to = CanBeRelativeTo
420
+ self._contexts = Contexts
421
+ self._make_dirs = MakeDirs
422
+ self._split_to_list = SplitToList
423
+ self._no_dir_processing = NoDirProcessing
424
+ self.flags = Flags(
425
+ no_env_search=NoEnvSearch,
426
+ no_value_search=NoValueSearch,
427
+ no_conffile_search=NoConffileSearch,
428
+ click_key_conversion=ClickKeyConversion,
429
+ allow_override=AllowOverride,
430
+ no_exception=NoException,
431
+ )
432
+
433
+ def __set_name__(self, owner: type, name: str) -> None:
434
+ """This method is a special python method called when a descriptor is assigned to a class attribute.
435
+ ConfigVarDef is a descriptor class because it defines the __get__ and __set__ methods.
436
+
437
+ The goal of this method is to:
438
+ - set the Name directive of this ConfigVarDef based on the attribute name.
439
+ - infer the type of the attribute and set the TypeInfo directive with it.
440
+
441
+ Args:
442
+ owner (type): the owning class of the attribute that is being assigned the descriptor
443
+ name (str): the attribute name
444
+ """
445
+
446
+ # set Name directive
447
+ self._name = name
448
+
449
+ # get all type hints of the owner class
450
+ try:
451
+ hints = get_type_hints(owner, include_extras=True)
452
+ except Exception:
453
+ hints = getattr(owner, "__annotations__", {})
454
+
455
+ # test if there is a type hint for this attribute, if not we will consider it to be a string.
456
+ if name in hints:
457
+ annotated_type = hints[name]
458
+ self._type_info = annotated_type
459
+
460
+ if self._split_to_list is None:
461
+ origin = get_origin(annotated_type)
462
+ args = get_args(annotated_type)
463
+
464
+ # Check for basic list
465
+ if origin is list or annotated_type is list:
466
+ self._split_to_list = True
467
+ # Check for Optional[list] / Union[list, ...]
468
+ elif origin is Union:
469
+ for arg in args:
470
+ arg_origin = get_origin(arg)
471
+ if arg_origin is list or arg is list:
472
+ self._split_to_list = True
473
+ break
474
+ else:
475
+ # no type hint, consider it as a string
476
+ self._type_info = str
477
+
478
+ def __get__(
479
+ self, instance: Optional[AppConfig], owner: Optional[type] = None
480
+ ) -> ConfigVarDef[_T] | _T | None:
481
+ """
482
+ Descriptor method that gets the value of the configuration variable from the AppConfig instance.
483
+
484
+ The value is retrieved from the instance's __dict__ using the variable's Name because we want to
485
+ handle the case where we have dotted names for nested attributes.
486
+ """
487
+ if instance is None:
488
+ return self
489
+ name = self.Name
490
+ if name in instance.__dict__:
491
+ return instance[name] # type: ignore
492
+ return None
493
+
494
+ def __set__(self, instance: AppConfig, value: Any) -> None:
495
+ """
496
+ Descriptor method that gets the value of the configuration variable from the AppConfig instance.
497
+ The value is set in the instance's __dict__ using the variable's Name because we want to
498
+ handle the case where we have dotted names for nested attributes.
499
+ """
500
+ instance._set_value(self.Name, value)
501
+
502
+ @property
503
+ def Name(self) -> str:
504
+ if self._name is None:
505
+ raise RuntimeError(
506
+ "ConfigVarDef has no Name. Declare it on an AppConfig subclass "
507
+ )
508
+ return self._name
509
+
510
+ @property
511
+ def Help(self) -> str:
512
+ return self._help
513
+
514
+ @property
515
+ def Contexts(self) -> Sequence[str] | None:
516
+ return self._contexts
517
+
518
+ @property
519
+ def ValueKey(self) -> Optional[str]:
520
+ """Note: we can't compute the final value here because it depends on the click_key_conversion
521
+ flag that can be set globally or in resolve_vars."""
522
+ if self.flags.no_value_search:
523
+ return None
524
+ else:
525
+ return self.Name if self._value_key is None else self._value_key
526
+
527
+ @property
528
+ def EnvName(self) -> Optional[str]:
529
+ if self.flags.no_env_search:
530
+ return None
531
+ else:
532
+ return self._env_name if self._env_name is not None else self.Name
533
+
534
+ @property
535
+ def FileKey(self) -> Optional[str]:
536
+ if self.flags.no_conffile_search:
537
+ return None
538
+ else:
539
+ return self._file_key if self._file_key is not None else self.Name
540
+
541
+ @property
542
+ def Default(self) -> Any | Callable[[str, Any, Any], Any] | Undefined:
543
+ return self._default
544
+
545
+ @property
546
+ def SplitToList(self) -> bool | str:
547
+ return False if self._split_to_list is None else self._split_to_list
548
+
549
+ @property
550
+ def Transform(self) -> Optional[Callable[[str, Any, Any], Any]]:
551
+ return self._transform
552
+
553
+ @property
554
+ def TypeInfo(self) -> Any:
555
+ return self._type_info
556
+
557
+ @property
558
+ def NoDirProcessing(self) -> bool:
559
+ return False if self._no_dir_processing is None else self._no_dir_processing
560
+
561
+ @property
562
+ def CanBeRelativeTo(self) -> Optional[Path | str]:
563
+ return self._can_be_relative_to
564
+
565
+ @property
566
+ def MakeDirs(self) -> Optional[PathType]:
567
+ return self._make_dirs
568
+
569
+
570
+ def configvar(
571
+ *,
572
+ Help: str = "",
573
+ Default: Any | Callable[[str, Any, Any], Any] | Undefined = _undef,
574
+ EnvName: Optional[str] = None,
575
+ FileKey: Optional[str] = None,
576
+ ValueKey: Optional[str] = None,
577
+ Transform: Optional[Callable[[str, Any, Any], Any]] = None,
578
+ CanBeRelativeTo: Optional[Path | str] = None,
579
+ Contexts: Optional[Sequence[str]] = None,
580
+ MakeDirs: Optional[PathType] = None,
581
+ SplitToList: Optional[bool | str] = None,
582
+ NoDirProcessing: Optional[bool] = None,
583
+ NoSearch: Optional[bool] = None,
584
+ NoEnvSearch: Optional[bool] = None,
585
+ NoValueSearch: Optional[bool] = None,
586
+ NoConffileSearch: Optional[bool] = None,
587
+ ClickKeyConversion: Optional[bool] = None,
588
+ AllowOverride: Optional[bool] = None,
589
+ NoException: Optional[bool] = None,
590
+ ) -> Any:
591
+ """Create a declarative configuration variable definition.
592
+
593
+ Use it as a class attribute on an AppConfig subclass:
594
+
595
+ class MyCfg(AppConfig):
596
+ my_var: int = configvar(Default=1)
597
+
598
+ The variable name defaults to the attribute name and its type is inferred from the type hint of the attribute declaration.
599
+
600
+ This function allows to assign a ConfigVarDef objects to an attribute definitions of any type by telling the type checkers
601
+ that the type of the assignation is Any instead of ConfigVarDef.
602
+ Indeed ConfigVarDef is a generic class and my_var: int = ConfigVarDef(...) or my_var: ConfigVarDef[int] = ConfigVarDef(...)
603
+ would not be accepted by type checkers. configvar() declares returning Any which deactivates type checking.
604
+
605
+ """
606
+
607
+ return ConfigVarDef(
608
+ Help=Help,
609
+ Default=Default,
610
+ EnvName=EnvName,
611
+ FileKey=FileKey,
612
+ ValueKey=ValueKey,
613
+ Transform=Transform,
614
+ CanBeRelativeTo=CanBeRelativeTo,
615
+ Contexts=Contexts,
616
+ MakeDirs=MakeDirs,
617
+ SplitToList=SplitToList,
618
+ NoDirProcessing=NoDirProcessing,
619
+ NoSearch=NoSearch,
620
+ NoEnvSearch=NoEnvSearch,
621
+ NoValueSearch=NoValueSearch,
622
+ NoConffileSearch=NoConffileSearch,
623
+ ClickKeyConversion=ClickKeyConversion,
624
+ AllowOverride=AllowOverride,
625
+ NoException=NoException,
626
+ )
the1conf/py.typed ADDED
File without changes