Skip to content

Commit 295f976

Browse files
committed
Updated documentation; fix dependency
- Improved documentation - Added missing python-dateutil dependency
1 parent fc20adc commit 295f976

File tree

6 files changed

+171
-39
lines changed

6 files changed

+171
-39
lines changed

docs/ref-config.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@
55
firebird.driver.config
66
======================
77

8-
This module contains firebird-driver configuration. Uses configuration classes from firebird-base
9-
package.
8+
This module defines the configuration system for the firebird-driver.
9+
It uses an INI-style format managed via the `DriverConfig` class, which
10+
allows defining settings for the driver itself, default server/database
11+
parameters, and named configurations for specific servers and databases.
12+
13+
Configuration can be loaded from files, strings, or dictionaries, and
14+
supports environment variable interpolation. The primary interaction point
15+
is usually the global `driver_config` instance.
1016

1117
Classes
1218
=======

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ classifiers = [
2828
"Topic :: Database",
2929
]
3030
dependencies = [
31-
#"firebird-base @file:////home/job/python/projects/firebird-base",
32-
"firebird-base~=2.0",
31+
"firebird-base @file:////home/job/python/projects/firebird-base",
32+
#"firebird-base~=2.0",
33+
"python-dateutil~=2.8",
3334
]
3435

3536
[project.urls]

src/firebird/driver/config.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,14 @@
3535

3636
"""firebird-driver - Driver configuration
3737
38+
This module defines the configuration system for the firebird-driver.
39+
It uses an INI-style format managed via the `DriverConfig` class, which
40+
allows defining settings for the driver itself, default server/database
41+
parameters, and named configurations for specific servers and databases.
3842
43+
Configuration can be loaded from files, strings, or dictionaries, and
44+
supports environment variable interpolation. The primary interaction point
45+
is usually the global `driver_config` instance.
3946
"""
4047

4148
from __future__ import annotations
@@ -46,7 +53,7 @@
4653
from .types import NetProtocol, DecfloatRound, DecfloatTraps
4754

4855
class ServerConfig(Config): # pylint: disable=R0902
49-
"""Server configuration.
56+
"""Represents configuration options specific to a named Firebird server entry.
5057
"""
5158
def __init__(self, name: str, *, optional: bool=False, description: str=None):
5259
super().__init__(name, optional=optional, description=description)
@@ -81,7 +88,7 @@ def __init__(self, name: str, *, optional: bool=False, description: str=None):
8188
StrOption('encoding_errors', "Handler used for encoding errors", default='strict')
8289

8390
class DatabaseConfig(Config): # pylint: disable=R0902
84-
"""Database configuration.
91+
"""Represents configuration options specific to a named Firebird database entry, including connection and creation parameters.
8592
"""
8693
def __init__(self, name: str, *, optional: bool=False, description: str=None):
8794
super().__init__(name, optional=optional, description=description)
@@ -94,12 +101,12 @@ def __init__(self, name: str, *, optional: bool=False, description: str=None):
94101
#: Database file specification or alias
95102
self.database: StrOption = \
96103
StrOption('database', "Database file specification or alias")
97-
#: Database filename should be passed in UTF8
104+
#: Specifies whether the database parameter (filename) is encoded in UTF-8 when passed to the server.
98105
self.utf8filename: BoolOption = \
99-
BoolOption('utf8filename', "Database filename should be passed in UTF8")
100-
#: Protocol to be used for databasem value is `.NetProtocol`
106+
BoolOption('utf8filename', "Specifies whether the database parameter (filename) is encoded in UTF-8 when passed to the server.")
107+
#: Network protocol to use for the connection. Value must be a member of the .NetProtocol enum.
101108
self.protocol: EnumOption = \
102-
EnumOption('protocol', NetProtocol, "Protocol to be used for database")
109+
EnumOption('protocol', NetProtocol, "Network protocol to use for the connection. Value must be a member of the .NetProtocol enum.")
103110
#: Defaul user name, default is envar ISC_USER or None if not specified
104111
self.user: StrOption = \
105112
StrOption('user', "Defaul user name", default=os.environ.get('ISC_USER', None))
@@ -147,14 +154,15 @@ def __init__(self, name: str, *, optional: bool=False, description: str=None):
147154
#: Set DECFLOAT ROUND [Firebird 4], value is `.DecfloatRound`
148155
self.decfloat_round: EnumOption = \
149156
EnumOption('decfloat_round', DecfloatRound, "DECFLOAT round mode")
150-
#: Set DECFLOAT TRAPS [Firebird 4], values are `.DecfloatTraps`
157+
#: Specifies which DECFLOAT exceptional conditions should cause a trap (raise an error) [Firebird 4]. Accepts a list of .DecfloatTraps enum members.
151158
self.decfloat_traps: ListOption = \
152159
ListOption('decfloat_traps', DecfloatTraps,
153-
"Which DECFLOAT exceptional conditions cause a trap")
160+
"""Specifies which DECFLOAT exceptional conditions should cause a trap
161+
(raise an error) [Firebird 4]. Accepts a list of .DecfloatTraps enum members.""")
154162
#: Number of parallel workers
155163
self.parallel_workers = \
156164
IntOption('parallel_workers', "Number of parallel workers")
157-
# Create options
165+
# --- Options specific to Database Creation ---
158166
#: Database create option. Page size to be used.
159167
self.page_size: IntOption = \
160168
IntOption('page_size', "Page size to be used for created database.")
@@ -179,7 +187,12 @@ def __init__(self, name: str, *, optional: bool=False, description: str=None):
179187
"Data page space usage for created database (True = reserve space, False = Use all space)")
180188

181189
class DriverConfig(Config):
182-
"""Firebird driver configuration.
190+
"""Main configuration object for the Firebird driver. Holds global settings, default
191+
configurations, and lists of registered servers and databases.
192+
193+
Settings loaded from specific server/database sections override those in the `db_defaults`
194+
and `server_defaults` sections. When reading multiple files, options from later files
195+
override those from earlier ones.
183196
"""
184197
def __init__(self, name: str):
185198
super().__init__(name)
@@ -310,4 +323,7 @@ def register_database(self, name: str, config: str=None) -> DatabaseConfig:
310323

311324
# Configuration
312325

326+
#: Global driver configuration instance.
327+
#: Load settings from files/strings/dicts into this object before connecting,
328+
#: or modify its attributes directly for programmatic configuration.
313329
driver_config: DriverConfig = DriverConfig('firebird.driver')

src/firebird/driver/core.py

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@
3434
# ______________________________________
3535
# pylint: disable=C0302, W0212, R0902, R0912,R0913, R0914, R0915, R0904
3636

37-
"""firebird-driver - Main driver code (connection, transaction, cursor etc.)
37+
"""firebird-driver - Main driver code
38+
39+
This module implements the core components of the firebird-driver, including the DB-API 2.0
40+
compliant Connection, Cursor, and Transaction objects, as well as helper classes for managing
41+
events, BLOBs, parameter buffers, and accessing database/server information.
3842
"""
3943

4044
from __future__ import annotations
@@ -296,7 +300,7 @@ def temp_database(*args, **kwargs) -> Connection:
296300

297301
# Managers for Parameter buffers
298302
class TPB: # pylint: disable=R0902
299-
"""Transaction Parameter Buffer.
303+
"""Helper class to build and parse Transaction Parameter Buffers (TPB) used when starting transactions.
300304
"""
301305
def __init__(self, *, access_mode: TraAccessMode=TraAccessMode.WRITE,
302306
isolation: Isolation=Isolation.SNAPSHOT,
@@ -412,7 +416,7 @@ def reserve_table(self, name: str, share_mode: TableShareMode, access_mode: Tabl
412416
self._table_reservation.append((name, share_mode, access_mode))
413417

414418
class DPB:
415-
"""Database Parameter Buffer.
419+
"""Helper class to build and parse Database Parameter Buffers (DPB) used when connecting databases.
416420
"""
417421
def __init__(self, *, user: str=None, password: str=None, role: str=None,
418422
trusted_auth: bool=False, sql_dialect: int=3, timeout: int=None,
@@ -684,7 +688,8 @@ def get_buffer(self, *, for_create: bool = False) -> bytes:
684688
return result
685689

686690
class SPB_ATTACH:
687-
"""Service Parameter Buffer.
691+
"""Helper class to build and parse Service Parameter Buffers (SPB) used when connecting
692+
to service manager.
688693
"""
689694
def __init__(self, *, user: str = None, password: str = None, trusted_auth: bool = False,
690695
config: str = None, auth_plugin_list: str = None, expected_db: str=None,
@@ -1106,6 +1111,9 @@ def get_engine_version(self, con: Connection | Server) -> float:
11061111
class DatabaseInfoProvider3(InfoProvider):
11071112
"""Provides access to information about attached database [Firebird 3+].
11081113
1114+
Information can be accessed either via specific properties (preferred) or the lower-level
1115+
`get_info()` method.
1116+
11091117
Important:
11101118
Do NOT create instances of this class directly! Use `Connection.info` property to
11111119
access the instance already bound to attached database.
@@ -1316,6 +1324,13 @@ def get_info(self, info_code: DbInfoCode, page_number: int=None) -> Any:
13161324
13171325
Returns:
13181326
The data type of returned value depends on information required.
1327+
1328+
Note:
1329+
Info codes that return stable values are cached on first call, so subsequent calls do not
1330+
access the server. These codes are: `CREATION_DATE`, `DB_CLASS`, `DB_PROVIDER`,
1331+
`DB_SQL_DIALECT`, `ODS_MINOR_VERSION`, `ODS_VERSION`, `PAGE_SIZE`, `VERSION`,
1332+
`FIREBIRD_VERSION`, `IMPLEMENTATION_OLD`, `IMPLEMENTATION`, `DB_ID`, `BASE_LEVEL`,
1333+
and `ATTACHMENT_ID`.
13191334
"""
13201335
if info_code in self._cache:
13211336
return self._cache[info_code]
@@ -1589,6 +1604,9 @@ def engine_version(self) -> float:
15891604
class DatabaseInfoProvider(DatabaseInfoProvider3):
15901605
"""Provides access to information about attached database [Firebird 4+].
15911606
1607+
Information can be accessed either via specific properties (preferred) or the lower-level
1608+
`get_info()` method.
1609+
15921610
Important:
15931611
Do NOT create instances of this class directly! Use `Connection.info` property to
15941612
access the instance already bound to attached database.
@@ -1754,6 +1772,7 @@ def _prepare(self, sql: str, tra: TransactionManager) -> Statement:
17541772
tra.commit()
17551773
return result
17561774
def _determine_field_precision(self, meta: ItemMetadata) -> int:
1775+
# This internal method involve database queries using _tra_qry.
17571776
if (not meta.relation) or (not meta.field):
17581777
# Either or both field name and relation name are not provided,
17591778
# so we cannot determine field precision. It's normal situation
@@ -1796,6 +1815,7 @@ def _determine_field_precision(self, meta: ItemMetadata) -> int:
17961815
# We ran out of options
17971816
return 0
17981817
def _get_array_sqlsubtype(self, relation: bytes, column: bytes) -> int | None:
1818+
# This internal method involve database query using _tra_qry.
17991819
subtype = self.__sqlsubtype_cache.get((relation, column))
18001820
if subtype is not None:
18011821
return subtype
@@ -1820,6 +1840,9 @@ def drop_database(self) -> None:
18201840
Closes all event collectors, transaction managers (with rollback) and statements
18211841
associated with this connection before attempt to drop the database.
18221842
1843+
Important:
1844+
The connection object becomes unusable after this call.
1845+
18231846
Hooks:
18241847
Event `.ConnectionHook.DROPPED`: Executed after database is sucessfuly dropped.
18251848
Hook must have signature::
@@ -2021,7 +2044,7 @@ def transactions(self) -> list[TransactionManager]:
20212044
return result
20222045
@property
20232046
def schema(self) -> 'firebird.lib.schema.Schema':
2024-
"""Access to database schema. Requires firebird.lib package.
2047+
"""Access to database schema. Requires `firebird.lib` package.
20252048
"""
20262049
if self.__schema is None:
20272050
import firebird.lib.schema # pylint: disable=C0415
@@ -2031,7 +2054,7 @@ def schema(self) -> 'firebird.lib.schema.Schema':
20312054
return self.__schema
20322055
@property
20332056
def monitor(self) -> 'firebird.lib.monitor.Monitor':
2034-
"""Access to database monitoring tables. Requires firebird.lib package.
2057+
"""Access to database monitoring tables. Requires `firebird.lib` package.
20352058
"""
20362059
if self.__monitor is None:
20372060
import firebird.lib.monitor # pylint: disable=C0415
@@ -2283,6 +2306,9 @@ def create_database(database: str | Path, *, user: str=None, password: str=None,
22832306
class TransactionInfoProvider3(InfoProvider):
22842307
"""Provides access to information about transaction [Firebird 3+].
22852308
2309+
Information can be accessed either via specific properties (preferred) or the lower-level
2310+
`get_info()` method.
2311+
22862312
Important:
22872313
Do NOT create instances of this class directly! Use `TransactionManager.info`
22882314
property to access the instance already bound to transaction context.
@@ -2392,6 +2418,9 @@ def snapshot_number(self) -> int:
23922418
class TransactionInfoProvider(TransactionInfoProvider3):
23932419
"""Provides access to information about transaction [Firebird 4+].
23942420
2421+
Information can be accessed either via specific properties (preferred) or the lower-level
2422+
`get_info()` method.
2423+
23952424
Important:
23962425
Do NOT create instances of this class directly! Use `TransactionManager.info`
23972426
property to access the instance already bound to transaction context.
@@ -2467,6 +2496,8 @@ def _get_handle(self) -> a.FB_API_HANDLE:
24672496
def close(self) -> None:
24682497
"""Close the transaction manager and release all associated resources.
24692498
2499+
Implicitly ends the current active transaction according to default_action (if active).
2500+
24702501
Important:
24712502
Closed instance SHALL NOT be used anymore.
24722503
"""
@@ -3015,7 +3046,8 @@ def read(self, size: int=-1) -> str | bytes:
30153046
Like `file.read()`.
30163047
30173048
Note:
3018-
Performs automatic conversion to `str` for TEXT BLOBs.
3049+
Performs automatic conversion to `str` for TEXT BLOBs (subtype 1) based on the
3050+
connection's encoding.
30193051
"""
30203052
assert self._blob is not None
30213053
if size >= 0:
@@ -3195,6 +3227,7 @@ def __init__(self, connection: Connection, transaction: TransactionManager): # p
31953227
#: Names of columns that should be returned as `BlobReader`.
31963228
self.stream_blobs: list[str] = []
31973229
#: BLOBs greater than threshold are returned as `BlobReader` instead in materialized form.
3230+
#: Defaults to the value from `driver_config`.
31983231
self.stream_blob_threshold = driver_config.stream_blob_threshold.value
31993232
def __enter__(self) -> Cursor:
32003233
return self
@@ -3930,7 +3963,7 @@ def executemany(self, operation: str | Statement,
39303963
Note:
39313964
This function simply calls `.execute` in a loop, feeding it with
39323965
parameters from `seq_of_parameters`. Because `.execute` reuses the statement,
3933-
calling `executemany` is equally efective as direct use of prepared `Statement`
3966+
calling `executemany` is equally effective as direct use of prepared `Statement`
39343967
and calling `execute` in a loop directly in application.
39353968
"""
39363969
for parameters in seq_of_parameters:
@@ -4075,7 +4108,7 @@ def to_dict(self, row: tuple, into: dict=None) -> dict:
40754108
40764109
Arguments:
40774110
row: Row data returned by fetch_* method.
4078-
into: Dictionary that shouold be updated with row data.
4111+
into: Dictionary that should be updated with row data.
40794112
"""
40804113
assert len(self._stmt._names) == len(row), "Length of data must match number of fields"
40814114
if into is None:
@@ -4216,6 +4249,9 @@ def name(self) -> str:
42164249
class ServerInfoProvider(InfoProvider):
42174250
"""Provides access to information about attached server.
42184251
4252+
Information can be accessed either via specific properties (preferred) or the lower-level
4253+
`get_info()` method.
4254+
42194255
Important:
42204256
Do NOT create instances of this class directly! Use `Server.info` property to access
42214257
the instance already bound to connectected server.
@@ -5458,7 +5494,7 @@ def __init__(self, svc: iService, spb: bytes, host: str, encoding: str,
54585494
self.host: str = host
54595495
#: Service output mode (line or eof)
54605496
self.mode: SrvInfoCode = SrvInfoCode.TO_EOF
5461-
#: Response buffer used to comunicate with service
5497+
#: Response buffer used to communicate with service
54625498
self.response: CBuffer = CBuffer(USHRT_MAX)
54635499
self._eof: bool = False
54645500
self.__line_buffer: list[str] = []

src/firebird/driver/hooks.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,44 @@
3333
# Contributor(s): Pavel Císař (original code)
3434
# ______________________________________
3535

36-
"""firebird-driver - Drivers hooks
36+
"""firebird-driver - Driver Hooks
37+
38+
This module defines specific hook points (events) within the firebird-driver
39+
lifecycle where custom functions can be registered and executed. These hooks
40+
allow for extending or modifying driver behavior, logging, or monitoring.
41+
42+
Hooks are registered using `firebird.driver.add_hook()` or the `firebird.base.hooks.hook_manager`.
43+
The specific signature required for each hook function and the context in which
44+
it's called are documented within the driver methods that trigger these hooks
45+
(primarily in `firebird.driver.core`).
3746
"""
3847

3948
from __future__ import annotations
4049
from enum import Enum, auto
4150
from firebird.base.hooks import register_class, get_callbacks, add_hook, hook_manager
4251

4352
class APIHook(Enum):
44-
"""Firebird API hooks.
53+
"""Hooks related to the loading and initialization of the underlying Firebird client API.
4554
"""
55+
#: Called after the Firebird client library has been successfully loaded and basic interfaces obtained.
4656
LOADED = auto()
4757

4858
class ConnectionHook(Enum):
49-
"""Connection hooks.
59+
"""Hooks related to the lifecycle of a database connection (attachment, detachment, dropping).
5060
"""
61+
#: Called before attempting to attach to a database, allows interception or modification.
5162
ATTACH_REQUEST = auto()
63+
#: Called after a database connection (attachment) has been successfully established.
5264
ATTACHED = auto()
65+
#: Called before attempting to detach from a database, allows cancellation.
5366
DETACH_REQUEST = auto()
67+
#: Called after a database connection has been successfully closed (detached).
5468
CLOSED = auto()
69+
#: Called after a database has been successfully dropped.
5570
DROPPED = auto()
5671

5772
class ServerHook(Enum):
58-
"""Server hooks.
73+
"""Hooks related to the lifecycle of a service manager connection.
5974
"""
75+
#: Called after connecting to the Firebird service manager.
6076
ATTACHED = auto()

0 commit comments

Comments
 (0)