Skip to content

Commit 5876ba2

Browse files
📝 Add docstrings to issue-1225
Docstrings generation was requested by @fizyk. * #1241 (comment) The following files were modified: * `pytest_postgresql/config.py` * `pytest_postgresql/factories/client.py` * `pytest_postgresql/factories/noprocess.py` * `pytest_postgresql/factories/process.py` * `tests/test_executor.py`
1 parent 09e89c5 commit 5876ba2

File tree

5 files changed

+150
-62
lines changed

5 files changed

+150
-62
lines changed

pytest_postgresql/config.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,28 @@ class PostgreSQLConfig:
2828

2929

3030
def get_config(request: FixtureRequest) -> PostgreSQLConfig:
31-
"""Return a dictionary with config options."""
31+
"""
32+
Create a PostgreSQLConfig populated from pytest configuration options.
33+
34+
Reads pytest options and INI values prefixed with "postgresql_" to populate a PostgreSQLConfig dataclass. The "load" option is normalized to Paths or strings and "port_search_count" is converted to an int.
35+
36+
Parameters:
37+
request (FixtureRequest): pytest fixture request used to read config options and INI values.
38+
39+
Returns:
40+
PostgreSQLConfig: Configuration populated from the pytest settings.
41+
"""
3242

3343
def get_postgresql_option(option: str) -> Any:
44+
"""
45+
Retrieve a PostgreSQL-related pytest configuration value.
46+
47+
Parameters:
48+
option (str): The suffix of the configuration name (without the "postgresql_" prefix).
49+
50+
Returns:
51+
The value of the pytest configuration option named "postgresql_<option>", or `None` if not set.
52+
"""
3453
name = "postgresql_" + option
3554
return request.config.getoption(name) or request.config.getini(name)
3655

@@ -56,7 +75,15 @@ def get_postgresql_option(option: str) -> Any:
5675

5776

5877
def detect_paths(load_paths: list[LocalPath | str]) -> list[Path | str]:
59-
"""Convert path to sql files to Path instances."""
78+
"""
79+
Normalize a sequence of load paths so SQL file paths are Path objects and other entries are preserved.
80+
81+
Parameters:
82+
load_paths (list[LocalPath | str]): Iterable of paths to normalize; entries may be pytest LocalPath objects or strings.
83+
84+
Returns:
85+
list[Path | str]: A new list where entries that refer to files ending with ".sql" are returned as pathlib.Path objects and all other entries are returned unchanged (strings).
86+
"""
6087
converted_load_paths: list[Path | str] = []
6188
for path in load_paths:
6289
if isinstance(path, LocalPath):
@@ -65,4 +92,4 @@ def detect_paths(load_paths: list[LocalPath | str]) -> list[Path | str]:
6592
converted_load_paths.append(Path(path))
6693
else:
6794
converted_load_paths.append(path)
68-
return converted_load_paths
95+
return converted_load_paths

pytest_postgresql/factories/client.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,30 @@ def postgresql(
3535
dbname: str | None = None,
3636
isolation_level: "psycopg.IsolationLevel | None" = None,
3737
) -> Callable[[FixtureRequest], Iterator[Connection]]:
38-
"""Return connection fixture factory for PostgreSQL.
39-
40-
:param process_fixture_name: name of the process fixture
41-
:param dbname: database name
42-
:param isolation_level: optional postgresql isolation level
43-
defaults to server's default
44-
:returns: function which makes a connection to postgresql
38+
"""
39+
Create a pytest fixture factory that yields a PostgreSQL connection.
40+
41+
Parameters:
42+
process_fixture_name (str): Name of the pytest fixture that provides the database process executor (used to obtain host, port, user, password, template DB name, and server version).
43+
dbname (str | None): Database name to connect to; if None, use the executor's database name.
44+
isolation_level (psycopg.IsolationLevel | None): Optional transaction isolation level to configure the janitor; if None, use the server default.
45+
46+
Returns:
47+
Callable[[FixtureRequest], Iterator[psycopg.Connection]]: A pytest fixture factory function which, when used in a test, yields an open psycopg Connection to the specified database and ensures database janitor lifecycle management around the connection.
4548
"""
4649

4750
@pytest.fixture
4851
def postgresql_factory(request: FixtureRequest) -> Iterator[Connection]:
49-
"""Fixture factory for PostgreSQL.
50-
51-
:param request: fixture request object
52-
:returns: postgresql client
52+
"""
53+
Provide a pytest fixture that yields a psycopg Connection to the test PostgreSQL database.
54+
55+
The fixture resolves the process executor and global config from the given request, prepares or drops the test database as configured, and manages the database janitor and connection lifecycle so the connection is open for the duration of the consuming test.
56+
57+
Parameters:
58+
request (FixtureRequest): Pytest fixture request used to obtain the process fixture and test configuration.
59+
60+
Returns:
61+
Connection: A psycopg Connection connected to the selected test database; the connection is closed after the fixture completes.
5362
"""
5463
proc_fixture: PostgreSQLExecutor | NoopExecutor = request.getfixturevalue(process_fixture_name)
5564
config = get_config(request)
@@ -84,4 +93,4 @@ def postgresql_factory(request: FixtureRequest) -> Iterator[Connection]:
8493
yield db_connection
8594
db_connection.close()
8695

87-
return postgresql_factory
96+
return postgresql_factory

pytest_postgresql/factories/noprocess.py

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,36 @@ def postgresql_noproc(
4646
options: str = "",
4747
load: list[Callable | str | Path] | None = None,
4848
) -> Callable[[FixtureRequest], Iterator[NoopExecutor]]:
49-
"""Postgresql noprocess factory.
50-
51-
:param host: hostname
52-
:param port: exact port (e.g. '8000', 8000)
53-
:param user: postgresql username
54-
:param password: postgresql password
55-
:param dbname: postgresql database name
56-
:param options: Postgresql connection options
57-
:param load: List of functions used to initialize database's template.
58-
:returns: function which makes a postgresql process
49+
"""
50+
Create a pytest session-scoped fixture that provides a NoopExecutor connected to an existing PostgreSQL server.
51+
52+
The returned fixture resolves connection parameters from the explicit arguments or from the test configuration, applies xdist worker-specific adjustment to the database name, and uses a DatabaseJanitor to optionally drop the test database and load initialization elements into the template before yielding the configured NoopExecutor.
53+
54+
Parameters:
55+
host (str | None): Hostname to connect to; if None, taken from test configuration.
56+
port (str | int | None): Port to connect to; if None, taken from configuration or defaults to 5432.
57+
user (str | None): Username to authenticate as; if None, taken from configuration.
58+
password (str | None): Password to authenticate with; if None, taken from configuration.
59+
dbname (str | None): Base database name; if None, taken from configuration. The name is adjusted when pytest-xdist is in use.
60+
options (str): Additional connection options; if empty, taken from configuration.
61+
load (list[Callable | str | Path] | None): Sequence of initialization elements (callables or filesystem paths) to load into the database template; if None, taken from configuration.
62+
63+
Returns:
64+
Callable[[FixtureRequest], Iterator[NoopExecutor]]: A pytest fixture function which yields a configured NoopExecutor instance.
5965
"""
6066

6167
@pytest.fixture(scope="session")
6268
def postgresql_noproc_fixture(request: FixtureRequest) -> Iterator[NoopExecutor]:
63-
"""Noop Process fixture for PostgreSQL.
64-
65-
:param request: fixture request object
66-
:returns: tcp executor-like object
69+
"""
70+
Provide a pytest fixture that yields a NoopExecutor configured for an existing PostgreSQL server.
71+
72+
The fixture resolves connection parameters from the fixture request and the factory's closure values, applies xdist-aware database name transformation, and uses a DatabaseJanitor context to optionally drop the test database (if configured) and load initialization elements into the database template before yielding the executor.
73+
74+
Parameters:
75+
request (FixtureRequest): Pytest fixture request used to obtain configuration.
76+
77+
Returns:
78+
noop_exec (NoopExecutor): Executor-like object configured with the resolved host, port, user, password, dbname, and options.
6779
"""
6880
config = get_config(request)
6981
pg_host = host or config.host
@@ -98,4 +110,4 @@ def postgresql_noproc_fixture(request: FixtureRequest) -> Iterator[NoopExecutor]
98110
janitor.load(load_element)
99111
yield noop_exec
100112

101-
return postgresql_noproc_fixture
113+
return postgresql_noproc_fixture

pytest_postgresql/factories/process.py

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,23 @@
3737

3838

3939
def _pg_exe(executable: str | None, config: PostgreSQLConfig) -> str:
40-
"""If executable is set, use it. Otherwise best effort to find the executable."""
40+
"""
41+
Resolve the filesystem path to the PostgreSQL control executable (pg_ctl).
42+
43+
If `executable` is provided, it is returned as-is. Otherwise the function uses
44+
`config.exec` if that path exists; if not, it attempts to locate `pg_ctl` using
45+
`pg_config --bindir` and returns the `pg_ctl` path from that bindir.
46+
47+
Parameters:
48+
executable (str | None): Explicit path to a pg_ctl-like executable, or None to auto-resolve.
49+
config (PostgreSQLConfig): Configuration providing a fallback executable path via `config.exec`.
50+
51+
Returns:
52+
str: Absolute path to the pg_ctl executable to use.
53+
54+
Raises:
55+
ExecutableMissingException: If neither an existing executable path nor `pg_config` can be found.
56+
"""
4157
postgresql_ctl = executable or config.exec
4258
# check if that executable exists, as it's no on systems' PATH
4359
# only replace it if executable isn't passed manually
@@ -51,7 +67,17 @@ def _pg_exe(executable: str | None, config: PostgreSQLConfig) -> str:
5167

5268

5369
def _pg_port(port: PortType | None, config: PostgreSQLConfig, excluded_ports: Iterable[int]) -> int:
54-
"""User specified port, otherwise find an unused port from config."""
70+
"""
71+
Select the PostgreSQL port to use, preferring an explicit port and falling back to the configured port.
72+
73+
Parameters:
74+
port (PortType | None): Preferred port provided by the caller; may be None.
75+
config (PostgreSQLConfig): Configuration containing the default port to use when `port` is not specified.
76+
excluded_ports (Iterable[int]): Ports that must not be selected.
77+
78+
Returns:
79+
int: A port number that is not in `excluded_ports`.
80+
"""
5581
pg_port = get_port(port, excluded_ports) or get_port(config.port, excluded_ports)
5682
assert pg_port is not None
5783
return pg_port
@@ -82,37 +108,38 @@ def postgresql_proc(
82108
postgres_options: str | None = None,
83109
load: list[Callable | str | Path] | None = None,
84110
) -> Callable[[FixtureRequest, TempPathFactory], Iterator[PostgreSQLExecutor]]:
85-
"""Postgresql process factory.
86-
87-
:param executable: path to postgresql_ctl
88-
:param host: hostname
89-
:param port:
90-
exact port (e.g. '8000', 8000)
91-
randomly selected port (None) - any random available port
92-
-1 - command line or pytest.ini configured port
93-
[(2000,3000)] or (2000,3000) - random available port from a given range
94-
[{4002,4003}] or {4002,4003} - random of 4002 or 4003 ports
95-
[(2000,3000), {4002,4003}] - random of given range and set
96-
:param user: postgresql username
97-
:param password: postgresql password
98-
:param dbname: postgresql database name
99-
:param options: Postgresql connection options
100-
:param startparams: postgresql starting parameters
101-
:param unixsocketdir: directory to create postgresql's unixsockets
102-
:param postgres_options: Postgres executable options for use by pg_ctl
103-
:param load: List of functions used to initialize database's template.
104-
:returns: function which makes a postgresql process
111+
"""
112+
Create a pytest fixture factory that starts a temporary PostgreSQL server process for tests.
113+
114+
This factory returns a session-scoped fixture which allocates a port, initializes a data directory, starts PostgreSQL, runs initial load steps into the template database, and yields a PostgreSQLExecutor for test use. The fixture ensures the server is stopped and cleaned up when tests finish.
115+
116+
Parameters:
117+
executable (str | None): Path to the PostgreSQL control executable (pg_ctl). If None, the configured executable or pg_config discovery will be used.
118+
port (PortType | None | int): Port selection specification. Accepts:
119+
- an exact port (e.g. 8000 or "8000"),
120+
- None to select any available port,
121+
- -1 to use the command-line or pytest.ini configured port,
122+
- a range tuple/list (e.g. (2000, 3000)) to pick a random available port from that range,
123+
- a set/list of ports (e.g. {4002, 4003}) to pick a random port from the set,
124+
- a list combining ranges and sets (e.g. [(2000,3000), {4002,4003}]).
125+
postgres_options (str | None): Additional options for the PostgreSQL server process passed through pg_ctl.
126+
load (list[Callable | str | Path] | None): Initialization steps applied to the template database before tests run; each element is either a callable or a path/SQL identifier that DatabaseJanitor.load understands.
127+
128+
Returns:
129+
Callable[[FixtureRequest, TempPathFactory], Iterator[PostgreSQLExecutor]]: A pytest fixture factory that yields a started PostgreSQLExecutor configured per the provided arguments and test configuration.
105130
"""
106131

107132
@pytest.fixture(scope="session")
108133
def postgresql_proc_fixture(
109134
request: FixtureRequest, tmp_path_factory: TempPathFactory
110135
) -> Iterator[PostgreSQLExecutor]:
111-
"""Process fixture for PostgreSQL.
112-
113-
:param request: fixture request object
114-
:param tmp_path_factory: temporary path object (fixture)
115-
:returns: tcp executor
136+
"""
137+
Create, start, and yield a PostgreSQL server process configured for the requesting test.
138+
139+
This fixture selects an available port, prepares a data directory and logfile, starts a PostgreSQL server via PostgreSQLExecutor, applies any configured initialization/load steps, and yields the running executor to the test. The server is stopped and resources are cleaned up when the fixture context exits.
140+
141+
Returns:
142+
PostgreSQLExecutor: A configured and started executor connected to the test PostgreSQL instance.
116143
"""
117144
config = get_config(request)
118145
pg_dbname = dbname or config.dbname
@@ -181,4 +208,4 @@ def postgresql_proc_fixture(
181208
janitor.load(load_element)
182209
yield postgresql_executor
183210

184-
return postgresql_proc_fixture
211+
return postgresql_proc_fixture

tests/test_executor.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ def version(self) -> Any:
4949

5050

5151
def test_unsupported_version(request: FixtureRequest) -> None:
52-
"""Check that the error gets raised on unsupported postgres version."""
52+
"""
53+
Verify that starting an executor with an unsupported PostgreSQL version raises PostgreSQLUnsupported.
54+
55+
Creates a PatchedPostgreSQLExecutor configured to simulate an unsupported server version and asserts that invoking its start() method raises `PostgreSQLUnsupported`.
56+
"""
5357
config = get_config(request)
5458
port = get_port(config.port)
5559
assert port is not None
@@ -75,7 +79,14 @@ def test_executor_init_with_password(
7579
tmp_path_factory: pytest.TempPathFactory,
7680
locale: str,
7781
) -> None:
78-
"""Test whether the executor initializes properly."""
82+
"""
83+
Verify that a PostgreSQLExecutor initialized with a password and database name can start and stop successfully when running under the specified locale.
84+
85+
The test sets LC_ALL to `locale`, prepares a temporary data directory and logfile, constructs a PostgreSQLExecutor using the test configuration and provided credentials, and asserts the executor can start and stop.
86+
87+
Parameters:
88+
locale (str): Locale string to set for the test environment (e.g., "en_US.UTF-8").
89+
"""
7990
config = get_config(request)
8091
monkeypatch.setenv("LC_ALL", locale)
8192
pg_exe = process._pg_exe(None, config)
@@ -100,7 +111,9 @@ def test_executor_init_bad_tmp_path(
100111
request: FixtureRequest,
101112
tmp_path_factory: pytest.TempPathFactory,
102113
) -> None:
103-
r"""Test init with \ and space chars in the path."""
114+
"""
115+
Verifies executor initialization, startup, and shutdown succeed when the datadir path contains backslash and space characters.
116+
"""
104117
config = get_config(request)
105118
pg_exe = process._pg_exe(None, config)
106119
port = process._pg_port(-1, config, [])
@@ -171,4 +184,4 @@ def test_custom_isolation_level(postgres_isolation_level: Connection) -> None:
171184
"""Check that a client fixture with a custom isolation level works."""
172185
cur = postgres_isolation_level.cursor()
173186
cur.execute("SELECT 1")
174-
assert cur.fetchone() == (1,)
187+
assert cur.fetchone() == (1,)

0 commit comments

Comments
 (0)