58
58
from enum import Enum , Flag
59
59
import os
60
60
from .config_pb2 import ConfigProto
61
- from .types import Error , MIME , ZMQAddress , PyExpr , PyCode , PyCallable , _decompose
61
+ from .types import Error , MIME , ZMQAddress , PyExpr , PyCode , PyCallable
62
62
from .strconv import get_convertor , convert_to_str , Convertor
63
63
64
64
PROTO_CONFIG = 'firebird.base.ConfigProto'
@@ -84,6 +84,49 @@ def create_config(_cls: Type[Config], name: str) -> Config: # pragma: no cover
84
84
"""
85
85
return _cls (name )
86
86
87
+ # Next two functions are copied from stdlib enum module, as they were removed in Python 3.11
88
+
89
+ def _decompose (flag , value ):
90
+ """
91
+ Extract all members from the value.
92
+ """
93
+ # _decompose is only called if the value is not named
94
+ not_covered = value
95
+ negative = value < 0
96
+ # issue29167: wrap accesses to _value2member_map_ in a list to avoid race
97
+ # conditions between iterating over it and having more pseudo-
98
+ # members added to it
99
+ if negative :
100
+ # only check for named flags
101
+ flags_to_check = [
102
+ (m , v )
103
+ for v , m in list (flag ._value2member_map_ .items ())
104
+ if m .name is not None
105
+ ]
106
+ else :
107
+ # check for named flags and powers-of-two flags
108
+ flags_to_check = [
109
+ (m , v )
110
+ for v , m in list (flag ._value2member_map_ .items ())
111
+ if m .name is not None or _power_of_two (v )
112
+ ]
113
+ members = []
114
+ for member , member_value in flags_to_check :
115
+ if member_value and member_value & value == member_value :
116
+ members .append (member )
117
+ not_covered &= ~ member_value
118
+ if not members and value in flag ._value2member_map_ :
119
+ members .append (flag ._value2member_map_ [value ])
120
+ members .sort (key = lambda m : m ._value_ , reverse = True )
121
+ if len (members ) > 1 and members [0 ].value == value :
122
+ # we have the breakdown, don't need the value member itself
123
+ members .pop (0 )
124
+ return members , not_covered
125
+
126
+ def _power_of_two (value ):
127
+ if value < 1 :
128
+ return False
129
+ return value == 2 ** (value .bit_length () - 1 )
87
130
88
131
class DirectoryScheme :
89
132
"""Class that provide paths to typically used application directories.
@@ -413,26 +456,30 @@ def _check_value(self, value: T) -> None:
413
456
f" not '{ type (value ).__name__ } '" )
414
457
def _get_value_description (self ) -> str :
415
458
return f'{ self .datatype .__name__ } \n '
416
- def _get_config_lines (self ) -> List [str ]:
459
+ def _get_config_lines (self , plain : bool = False ) -> List [str ]:
417
460
"""Returns list of strings containing text lines suitable for use in configuration
418
461
file processed with `~configparser.ConfigParser`.
419
462
420
463
Text lines with configuration start with comment marker `;` and end with newline.
464
+
465
+ Arguments:
466
+ plain: When True, it outputs only the option value. When False, it includes also
467
+ option description and other helpful information.
421
468
422
469
Note:
423
470
This function is intended for internal use. To get string describing current
424
471
configuration that is suitable for configuration files, use `get_config` method.
425
472
"""
426
- hdr = f"{ self .name } [{ self .datatype .__name__ } ][{ 'REQUIRED' if self .required else 'optional' } ]"
427
473
lines = []
428
- if self .required :
429
- lines .append ("; REQUIRED option.\n " )
430
- for line in self .description .strip ().splitlines ():
431
- lines .append (f"; { line } \n " )
432
- first = True
433
- for line in self ._get_value_description ().splitlines ():
434
- lines .append (f"; { 'Type: ' if first else '' } { line } \n " )
435
- first = False
474
+ if not plain :
475
+ if self .required :
476
+ lines .append ("; REQUIRED option.\n " )
477
+ for line in self .description .strip ().splitlines ():
478
+ lines .append (f"; { line } \n " )
479
+ first = True
480
+ for line in self ._get_value_description ().splitlines ():
481
+ lines .append (f"; { 'Type: ' if first else '' } { line } \n " )
482
+ first = False
436
483
value = self .get_value ()
437
484
nodef = ';' if value == self .default else ''
438
485
value = '<UNDEFINED>' if value is None else self .get_formatted ()
@@ -467,11 +514,15 @@ def validate(self) -> None:
467
514
"""
468
515
if self .required and self .get_value () is None :
469
516
raise Error (f"Missing value for required option '{ self .name } '" )
470
- def get_config (self ) -> str :
517
+ def get_config (self , * , plain : bool = False ) -> str :
471
518
"""Returns string containing text lines suitable for use in configuration file
472
519
processed with `~configparser.ConfigParser`.
520
+
521
+ Arguments:
522
+ plain: When True, it outputs only the option value. When False, it includes also
523
+ option description and other helpful information.
473
524
"""
474
- return '' .join (self ._get_config_lines ())
525
+ return '' .join (self ._get_config_lines (plain = plain ))
475
526
def has_value (self ) -> bool :
476
527
"""Returns True if option value is not None.
477
528
"""
@@ -585,18 +636,25 @@ def get_description(self) -> str:
585
636
Note: If description is not provided on instance creation, class doc string.
586
637
"""
587
638
return '' if self ._description is None else self ._description
588
- def get_config (self ) -> str :
639
+ def get_config (self , * , plain : bool = False ) -> str :
589
640
"""Returns string containing text lines suitable for use in configuration file
590
641
processed with `~configparser.ConfigParser`.
642
+
643
+ Arguments:
644
+ plain: When True, it outputs only the option values. When False, it includes also
645
+ option descriptions and other helpful information.
591
646
"""
592
647
lines = [f'[{ self .name } ]\n ' , ';\n ' ]
593
- for line in self .get_description ().strip ().splitlines ():
594
- lines .append (f"; { line } \n " )
648
+ if not plain :
649
+ for line in self .get_description ().strip ().splitlines ():
650
+ lines .append (f"; { line } \n " )
595
651
for option in self .options :
596
- lines .append ('\n ' )
597
- lines .append (option .get_config ())
652
+ if not plain :
653
+ lines .append ('\n ' )
654
+ lines .append (option .get_config (plain = plain ))
598
655
for config in self .configs :
599
- lines .append ('\n ' )
656
+ if not plain :
657
+ lines .append ('\n ' )
600
658
lines .append (config .get_config ())
601
659
return '' .join (lines )
602
660
def load_config (self , config : ConfigParser , section : str = None ) -> None :
0 commit comments