Skip to content

Commit 6e33b6f

Browse files
committed
Move _decompose(); support for plain config (without comments) in get_config()
1 parent 6e0a140 commit 6e33b6f

File tree

2 files changed

+77
-62
lines changed

2 files changed

+77
-62
lines changed

src/firebird/base/config.py

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
from enum import Enum, Flag
5959
import os
6060
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
6262
from .strconv import get_convertor, convert_to_str, Convertor
6363

6464
PROTO_CONFIG = 'firebird.base.ConfigProto'
@@ -84,6 +84,49 @@ def create_config(_cls: Type[Config], name: str) -> Config: # pragma: no cover
8484
"""
8585
return _cls(name)
8686

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)
87130

88131
class DirectoryScheme:
89132
"""Class that provide paths to typically used application directories.
@@ -413,26 +456,30 @@ def _check_value(self, value: T) -> None:
413456
f" not '{type(value).__name__}'")
414457
def _get_value_description(self) -> str:
415458
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]:
417460
"""Returns list of strings containing text lines suitable for use in configuration
418461
file processed with `~configparser.ConfigParser`.
419462
420463
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.
421468
422469
Note:
423470
This function is intended for internal use. To get string describing current
424471
configuration that is suitable for configuration files, use `get_config` method.
425472
"""
426-
hdr = f"{self.name} [{self.datatype.__name__}][{'REQUIRED' if self.required else 'optional'}]"
427473
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
436483
value = self.get_value()
437484
nodef = ';' if value == self.default else ''
438485
value = '<UNDEFINED>' if value is None else self.get_formatted()
@@ -467,11 +514,15 @@ def validate(self) -> None:
467514
"""
468515
if self.required and self.get_value() is None:
469516
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:
471518
"""Returns string containing text lines suitable for use in configuration file
472519
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.
473524
"""
474-
return ''.join(self._get_config_lines())
525+
return ''.join(self._get_config_lines(plain=plain))
475526
def has_value(self) -> bool:
476527
"""Returns True if option value is not None.
477528
"""
@@ -585,18 +636,25 @@ def get_description(self) -> str:
585636
Note: If description is not provided on instance creation, class doc string.
586637
"""
587638
return '' if self._description is None else self._description
588-
def get_config(self) -> str:
639+
def get_config(self, *, plain: bool=False) -> str:
589640
"""Returns string containing text lines suitable for use in configuration file
590641
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.
591646
"""
592647
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")
595651
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))
598655
for config in self.configs:
599-
lines.append('\n')
656+
if not plain:
657+
lines.append('\n')
600658
lines.append(config.get_config())
601659
return ''.join(lines)
602660
def load_config(self, config: ConfigParser, section: str=None) -> None:

src/firebird/base/types.py

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -476,46 +476,3 @@ def load(spec: str) -> Any:
476476
result = getattr(result, item)
477477
return result
478478

479-
# Next two functions are copied from stdlib enum module, as they were removed in Python 3.11
480-
481-
def _decompose(flag, value):
482-
"""
483-
Extract all members from the value.
484-
"""
485-
# _decompose is only called if the value is not named
486-
not_covered = value
487-
negative = value < 0
488-
# issue29167: wrap accesses to _value2member_map_ in a list to avoid race
489-
# conditions between iterating over it and having more pseudo-
490-
# members added to it
491-
if negative:
492-
# only check for named flags
493-
flags_to_check = [
494-
(m, v)
495-
for v, m in list(flag._value2member_map_.items())
496-
if m.name is not None
497-
]
498-
else:
499-
# check for named flags and powers-of-two flags
500-
flags_to_check = [
501-
(m, v)
502-
for v, m in list(flag._value2member_map_.items())
503-
if m.name is not None or _power_of_two(v)
504-
]
505-
members = []
506-
for member, member_value in flags_to_check:
507-
if member_value and member_value & value == member_value:
508-
members.append(member)
509-
not_covered &= ~member_value
510-
if not members and value in flag._value2member_map_:
511-
members.append(flag._value2member_map_[value])
512-
members.sort(key=lambda m: m._value_, reverse=True)
513-
if len(members) > 1 and members[0].value == value:
514-
# we have the breakdown, don't need the value member itself
515-
members.pop(0)
516-
return members, not_covered
517-
518-
def _power_of_two(value):
519-
if value < 1:
520-
return False
521-
return value == 2 ** (value.bit_length() - 1)

0 commit comments

Comments
 (0)