firebird-base 2.0.0__tar.gz → 2.0.2__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firebird-base
3
- Version: 2.0.0
3
+ Version: 2.0.2
4
4
  Summary: Firebird base modules for Python
5
5
  Project-URL: Home, https://github.com/FirebirdSQL/python3-base
6
6
  Project-URL: Documentation, https://firebird-base.rtfd.io
@@ -1,4 +1,4 @@
1
1
  # SPDX-FileCopyrightText: 2020-present The Firebird Projects <www.firebirdsql.org>
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- __version__ = "2.0.0"
4
+ __version__ = "2.0.2"
@@ -101,7 +101,7 @@ from configparser import (
101
101
  NoSectionError,
102
102
  )
103
103
  from decimal import Decimal, DecimalException
104
- from enum import Enum, Flag
104
+ from enum import Enum, Flag, _high_bit
105
105
  from inspect import Parameter, Signature, signature
106
106
  from pathlib import Path
107
107
  from typing import Any, Generic, TypeVar, cast, get_type_hints
@@ -148,32 +148,25 @@ def _eq(a: Any, b: Any) -> bool:
148
148
 
149
149
  # --- Internal helpers for FlagOption copied from stdlib enum (pre-Python 3.11) ---
150
150
  def _decompose(flag, value):
151
- "Extract all members from the value (internal helper for FlagOption)."
151
+ """Extract all members from the value.
152
+ """
152
153
  # _decompose is only called if the value is not named
153
154
  not_covered = value
154
155
  negative = value < 0
155
- # issue29167: wrap accesses to _value2member_map_ in a list to avoid race
156
- # conditions between iterating over it and having more pseudo-
157
- # members added to it
158
- if negative:
159
- # only check for named flags
160
- flags_to_check = [
161
- (m, v)
162
- for v, m in list(flag._value2member_map_.items())
163
- if m.name is not None
164
- ]
165
- else:
166
- # check for named flags and powers-of-two flags
167
- flags_to_check = [
168
- (m, v)
169
- for v, m in list(flag._value2member_map_.items())
170
- if m.name is not None or _power_of_two(v)
171
- ]
172
156
  members = []
173
- for member, member_value in flags_to_check:
157
+ for member in flag:
158
+ member_value = member.value
174
159
  if member_value and member_value & value == member_value:
175
160
  members.append(member)
176
161
  not_covered &= ~member_value
162
+ if not negative:
163
+ tmp = not_covered
164
+ while tmp:
165
+ flag_value = 2 ** _high_bit(tmp)
166
+ if flag_value in flag._value2member_map_:
167
+ members.append(flag._value2member_map_[flag_value])
168
+ not_covered &= ~flag_value
169
+ tmp &= ~flag_value
177
170
  if not members and value in flag._value2member_map_:
178
171
  members.append(flag._value2member_map_[value])
179
172
  members.sort(key=lambda m: m._value_, reverse=True)
@@ -2608,8 +2601,8 @@ class DataclassOption(Option[Any]):
2608
2601
  @dataclass
2609
2602
  class DBInfo:
2610
2603
  host: str
2611
- port: int = 5432 # Field with default
2612
2604
  user: str
2605
+ port: int = 5432 # Field with default
2613
2606
  ssl_mode: bool = field(default=False)
2614
2607
 
2615
2608
  class AppSettings(Config):
@@ -331,20 +331,18 @@ class eventsocket: # noqa: N801
331
331
  """
332
332
  _empty: _EventSocket = _EventSocket()
333
333
  def __init__(self, fget: Callable, doc: str | None=None):
334
- s = Signature.from_callable(fget)
335
- # Remove 'self' from list of parameters
336
- self._sig: Signature = s.replace(parameters=[v for k,v in s.parameters.items()
337
- if k.lower() != 'self'])
334
+ # Store callable for later signature inspection
335
+ self._callable = fget
338
336
  # Key: instance of class where this eventsocket instance is used to define a property
339
337
  # Value: _EventSocket
340
338
  self._map = WeakKeyDictionary()
341
339
  if doc is None and fget is not None:
342
340
  doc = fget.__doc__
343
341
  self.__doc__ = doc
344
- def _kw_test(self, sig: Signature) -> bool:
345
- p = sig.parameters
342
+ def _kw_test(self, given: Signature, expected: Signature) -> bool:
343
+ p = given.parameters
346
344
  result = False
347
- for k in set(p).difference(set(self._sig.parameters)):
345
+ for k in set(p).difference(set(expected.parameters)):
348
346
  result = True
349
347
  if p[k].default is Signature.empty:
350
348
  return False
@@ -361,10 +359,15 @@ class eventsocket: # noqa: N801
361
359
  if not callable(value):
362
360
  raise ValueError(f"Connection to non-callable '{value.__class__.__name__}' object failed")
363
361
  # Verify signatures
364
- sig = Signature.from_callable(value)
365
- if str(sig) != str(self._sig):
362
+ expected_sig: Signature = Signature.from_callable(self._callable, eval_str=True)
363
+ # Remove 'self' from list of parameters
364
+ expected_sig = expected_sig.replace(parameters=[v for k,v in expected_sig.parameters.items()
365
+ if k.lower() != 'self'])
366
+
367
+ given_sig = Signature.from_callable(value, eval_str=True)
368
+ if str(given_sig) != str(expected_sig):
366
369
  # Check if the difference is only in keyword arguments with defaults.
367
- if not self._kw_test(sig):
370
+ if not self._kw_test(given_sig, expected_sig):
368
371
  raise ValueError("Callable signature does not match the event signature")
369
372
  self._map[obj] = _EventSocket(value)
370
373
  def __delete__(self, obj):
@@ -404,9 +404,8 @@ class TracedClassConfig(BaseTraceConfig):
404
404
  ListOption('methods', str, "Names of traced class methods")
405
405
  #: Configuration sections with extended config of traced class methods
406
406
  self.special: ConfigListOption = \
407
- ConfigListOption('special',
408
- "Configuration sections with extended config of traced class methods",
409
- TracedMethodConfig)
407
+ ConfigListOption('special', TracedMethodConfig,
408
+ "Configuration sections with extended config of traced class methods")
410
409
  #: Wherher configuration should be applied also to all registered descendant classes [default: True].
411
410
  self.apply_to_descendants: BoolOption = \
412
411
  BoolOption('apply_to_descendants',
@@ -428,9 +427,9 @@ class TraceConfig(BaseTraceConfig):
428
427
  default=True)
429
428
  #: Configuration sections with traced Python classes [required].
430
429
  self.classes: ConfigListOption = \
431
- ConfigListOption('classes',
430
+ ConfigListOption('classes', TracedClassConfig,
432
431
  "Configuration sections with traced Python classes",
433
- TracedClassConfig, required=True)
432
+ required=True)
434
433
 
435
434
  class TraceManager:
436
435
  """Trace manager.
@@ -460,6 +459,7 @@ class TraceManager:
460
459
  def clear(self) -> None:
461
460
  """Removes all trace specifications.
462
461
  """
462
+ cls: TracedClass
463
463
  for cls in self._traced:
464
464
  cls.traced.clear()
465
465
  def register(self, cls: type) -> None:
@@ -524,6 +524,7 @@ class TraceManager:
524
524
  if strict:
525
525
  raise TypeError(f"Class '{obj.__class__.__name__}' not registered for trace!")
526
526
  return obj
527
+ item: TracedItem
527
528
  for item in entry.traced:
528
529
  setattr(obj, item.method, item.decorator(*item.args, **item.kwargs)(getattr(obj, item.method)))
529
530
  return obj
@@ -583,6 +584,7 @@ class TraceManager:
583
584
  cls_kwargs = {}
584
585
  cls_kwargs.update(global_kwargs)
585
586
  cls_kwargs.update(build_kwargs(cls_cfg))
587
+ cls_desc: TracedClass
586
588
  if (cls_desc := self._traced.find(partial(with_name, cls_name))) is None:
587
589
  if cfg.autoregister.value:
588
590
  cls = load(':'.join(cls_name.rsplit('.', 1)))
File without changes
File without changes
File without changes