pytest-postgresql 5.1.1__tar.gz → 6.0.1__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.
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/CHANGES.rst +60 -1
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/PKG-INFO +8 -6
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/README.rst +6 -4
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pyproject.toml +8 -4
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/__init__.py +1 -1
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/config.py +18 -3
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/executor.py +12 -5
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/executor_noop.py +8 -3
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/factories/__init__.py +3 -3
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/factories/client.py +24 -6
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/factories/noprocess.py +6 -6
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/factories/process.py +6 -6
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/janitor.py +37 -39
- pytest_postgresql-6.0.1/pytest_postgresql/loader.py +32 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/plugin.py +1 -1
- pytest_postgresql-6.0.1/pytest_postgresql/retry.py +48 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql.egg-info/PKG-INFO +8 -6
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql.egg-info/SOURCES.txt +2 -1
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/tests/test_executor.py +1 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/tests/test_janitor.py +15 -3
- pytest_postgresql-6.0.1/tests/test_loader.py +20 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/tests/test_noopexecutor.py +1 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/tests/test_postgres_options_plugin.py +9 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/tests/test_postgresql.py +1 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/tests/test_template_database.py +1 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/tests/test_version.py +1 -0
- pytest-postgresql-5.1.1/pytest_postgresql/retry.py +0 -33
- pytest-postgresql-5.1.1/pytest_postgresql/sql.py +0 -13
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/AUTHORS.rst +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/CONTRIBUTING.rst +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/COPYING +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/COPYING.lesser +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/MANIFEST.in +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/exceptions.py +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/py.typed +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql.egg-info/dependency_links.txt +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql.egg-info/entry_points.txt +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql.egg-info/requires.txt +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql.egg-info/top_level.txt +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql.egg-info/zip-safe +0 -0
- {pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/setup.cfg +0 -0
|
@@ -3,6 +3,65 @@ CHANGELOG
|
|
|
3
3
|
|
|
4
4
|
.. towncrier release notes start
|
|
5
5
|
|
|
6
|
+
6.0.1 (2024-08-14)
|
|
7
|
+
==================
|
|
8
|
+
|
|
9
|
+
Bugfixes
|
|
10
|
+
--------
|
|
11
|
+
|
|
12
|
+
- Fixed a long-standing bug, where calls to pg_ctl weren't getting `LC_*` and `LANG` envvars,
|
|
13
|
+
which caused issues on some systems not recognizing --auth parameter. (`#343 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/343>`__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Miscellaneus
|
|
17
|
+
------------
|
|
18
|
+
|
|
19
|
+
- `#945 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/945>`__
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
6.0.0 (2024-03-11)
|
|
23
|
+
==================
|
|
24
|
+
|
|
25
|
+
Breaking changes
|
|
26
|
+
----------------
|
|
27
|
+
|
|
28
|
+
- DatabaseJanitor class now accepts only keyword arguments. (`#899 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/899>`__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
Bugfixes
|
|
32
|
+
--------
|
|
33
|
+
|
|
34
|
+
- Fix the remaining `DepcrecationWarning` for `datetime.datetime.utcnow` on Python 3.12. (`#896 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/896>`__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
Deprecations
|
|
38
|
+
------------
|
|
39
|
+
|
|
40
|
+
- Deprecated load parameter on a client fixture.
|
|
41
|
+
Developers are encouraged to either use the load function/parameter
|
|
42
|
+
for process fixture, or create an intermediate fixture placed between client
|
|
43
|
+
and tests themselves to fill in the data. (`#850 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/850>`__)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
Features
|
|
47
|
+
--------
|
|
48
|
+
|
|
49
|
+
- Now all sql files used to initialise database for tests, has to be passed as pathlib.Path instance.
|
|
50
|
+
|
|
51
|
+
This helps the DatabaseJanitor choose correct behaviour based on parameter. (`#638 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/638>`__)
|
|
52
|
+
- Have separate parameters for template database name and database name in DatabaseJanitor.
|
|
53
|
+
It'll make it much clearer to understand the code and Janitor's behaviour. (`#672 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/672>`__)
|
|
54
|
+
- Template databases are now created with is_template flag turned on, and not by setting allow_connections to false.
|
|
55
|
+
|
|
56
|
+
The allow_connections flag being set to false is used strictly right before we attempt to drop the database. (`#914 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/914>`__)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
Miscellaneus
|
|
60
|
+
------------
|
|
61
|
+
|
|
62
|
+
- `#865 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/865>`__, `#882 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/882>`__, `#893 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/893>`__, `#900 <https://github.com/ClearcodeHQ/pytest-postgresql/issues/900>`__
|
|
63
|
+
|
|
64
|
+
|
|
6
65
|
5.1.1 (2024-03-07)
|
|
7
66
|
==================
|
|
8
67
|
|
|
@@ -385,4 +444,4 @@ Bugfix
|
|
|
385
444
|
- create command line and pytest.ini configuration options for executable
|
|
386
445
|
- create command line and pytest.ini configuration options for host
|
|
387
446
|
- create command line and pytest.ini configuration options for port
|
|
388
|
-
- Extracted code from pytest-
|
|
447
|
+
- Extracted code from pytest-postgresql
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pytest-postgresql
|
|
3
|
-
Version:
|
|
3
|
+
Version: 6.0.1
|
|
4
4
|
Summary: Postgresql fixtures and fixture factories for Pytest.
|
|
5
5
|
Author-email: Grzegorz Śliwiński <fizyk+pypi@fizyk.dev>
|
|
6
6
|
Project-URL: Source, https://github.com/ClearcodeHQ/pytest-postgresql
|
|
7
7
|
Project-URL: Bug Tracker, https://github.com/ClearcodeHQ/pytest-postgresql/issues
|
|
8
|
-
Project-URL: Changelog, https://github.com/ClearcodeHQ/pytest-postgresql/blob/
|
|
8
|
+
Project-URL: Changelog, https://github.com/ClearcodeHQ/pytest-postgresql/blob/v6.0.1/CHANGES.rst
|
|
9
9
|
Keywords: tests,pytest,fixture,postgresql
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Environment :: Web Environment
|
|
@@ -141,9 +141,10 @@ Client specific loads the database each test
|
|
|
141
141
|
|
|
142
142
|
.. code-block:: python
|
|
143
143
|
|
|
144
|
+
from pathlib import Path
|
|
144
145
|
postgresql_my_with_schema = factories.postgresql(
|
|
145
146
|
'postgresql_my_proc',
|
|
146
|
-
load=["schemafile.sql", "otherschema.sql", "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
147
|
+
load=[Path("schemafile.sql"), Path("otherschema.sql"), "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
147
148
|
)
|
|
148
149
|
|
|
149
150
|
.. warning::
|
|
@@ -152,12 +153,13 @@ Client specific loads the database each test
|
|
|
152
153
|
|
|
153
154
|
|
|
154
155
|
The process fixture performs the load once per test session, and loads the data into the template database.
|
|
155
|
-
Client fixture then creates test database out of the template database each test, which significantly speeds up the tests
|
|
156
|
+
Client fixture then creates test database out of the template database each test, which significantly **speeds up the tests**.
|
|
156
157
|
|
|
157
158
|
.. code-block:: python
|
|
158
159
|
|
|
160
|
+
from pathlib import Path
|
|
159
161
|
postgresql_my_proc = factories.postgresql_proc(
|
|
160
|
-
load=["schemafile.sql", "otherschema.sql", "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
162
|
+
load=[Path("schemafile.sql"), Path("otherschema.sql"), "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
161
163
|
)
|
|
162
164
|
|
|
163
165
|
|
|
@@ -511,7 +513,7 @@ it'll be on a docker machine or running remotely or locally.
|
|
|
511
513
|
Using SQLAlchemy to initialise basic database state
|
|
512
514
|
+++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
513
515
|
|
|
514
|
-
How to use SQLAlchemy for common
|
|
516
|
+
How to use SQLAlchemy for common initialisation:
|
|
515
517
|
|
|
516
518
|
.. code-block:: python
|
|
517
519
|
|
|
@@ -104,9 +104,10 @@ Client specific loads the database each test
|
|
|
104
104
|
|
|
105
105
|
.. code-block:: python
|
|
106
106
|
|
|
107
|
+
from pathlib import Path
|
|
107
108
|
postgresql_my_with_schema = factories.postgresql(
|
|
108
109
|
'postgresql_my_proc',
|
|
109
|
-
load=["schemafile.sql", "otherschema.sql", "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
110
|
+
load=[Path("schemafile.sql"), Path("otherschema.sql"), "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
110
111
|
)
|
|
111
112
|
|
|
112
113
|
.. warning::
|
|
@@ -115,12 +116,13 @@ Client specific loads the database each test
|
|
|
115
116
|
|
|
116
117
|
|
|
117
118
|
The process fixture performs the load once per test session, and loads the data into the template database.
|
|
118
|
-
Client fixture then creates test database out of the template database each test, which significantly speeds up the tests
|
|
119
|
+
Client fixture then creates test database out of the template database each test, which significantly **speeds up the tests**.
|
|
119
120
|
|
|
120
121
|
.. code-block:: python
|
|
121
122
|
|
|
123
|
+
from pathlib import Path
|
|
122
124
|
postgresql_my_proc = factories.postgresql_proc(
|
|
123
|
-
load=["schemafile.sql", "otherschema.sql", "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
125
|
+
load=[Path("schemafile.sql"), Path("otherschema.sql"), "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
124
126
|
)
|
|
125
127
|
|
|
126
128
|
|
|
@@ -474,7 +476,7 @@ it'll be on a docker machine or running remotely or locally.
|
|
|
474
476
|
Using SQLAlchemy to initialise basic database state
|
|
475
477
|
+++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
476
478
|
|
|
477
|
-
How to use SQLAlchemy for common
|
|
479
|
+
How to use SQLAlchemy for common initialisation:
|
|
478
480
|
|
|
479
481
|
.. code-block:: python
|
|
480
482
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pytest-postgresql"
|
|
3
|
-
version = "
|
|
3
|
+
version = "6.0.1"
|
|
4
4
|
description = "Postgresql fixtures and fixture factories for Pytest."
|
|
5
5
|
readme = "README.rst"
|
|
6
6
|
keywords = ["tests", "pytest", "fixture", "postgresql"]
|
|
@@ -39,7 +39,7 @@ requires-python = ">= 3.8"
|
|
|
39
39
|
[project.urls]
|
|
40
40
|
"Source" = "https://github.com/ClearcodeHQ/pytest-postgresql"
|
|
41
41
|
"Bug Tracker" = "https://github.com/ClearcodeHQ/pytest-postgresql/issues"
|
|
42
|
-
"Changelog" = "https://github.com/ClearcodeHQ/pytest-postgresql/blob/
|
|
42
|
+
"Changelog" = "https://github.com/ClearcodeHQ/pytest-postgresql/blob/v6.0.1/CHANGES.rst"
|
|
43
43
|
|
|
44
44
|
[project.entry-points."pytest11"]
|
|
45
45
|
pytest_postgresql = "pytest_postgresql.plugin"
|
|
@@ -95,16 +95,20 @@ showcontent = true
|
|
|
95
95
|
name = "Bugfixes"
|
|
96
96
|
showcontent = true
|
|
97
97
|
|
|
98
|
+
[tool.towncrier.fragment.deprecate]
|
|
99
|
+
name = "Deprecations"
|
|
100
|
+
showcontent = true
|
|
101
|
+
|
|
98
102
|
[tool.towncrier.fragment.break]
|
|
99
103
|
name = "Breaking changes"
|
|
100
104
|
showcontent = true
|
|
101
105
|
|
|
102
106
|
[tool.towncrier.fragment.misc]
|
|
103
107
|
name = "Miscellaneus"
|
|
104
|
-
showcontent =
|
|
108
|
+
showcontent = false
|
|
105
109
|
|
|
106
110
|
[tool.tbump.version]
|
|
107
|
-
current = "
|
|
111
|
+
current = "6.0.1"
|
|
108
112
|
|
|
109
113
|
# Example of a semver regexp.
|
|
110
114
|
# Make sure this matches current_version before
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Plugin's configuration."""
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, List, Optional, TypedDict, Union
|
|
3
5
|
|
|
4
6
|
from pytest import FixtureRequest
|
|
5
7
|
|
|
@@ -16,7 +18,7 @@ class PostgresqlConfigDict(TypedDict):
|
|
|
16
18
|
startparams: str
|
|
17
19
|
unixsocketdir: str
|
|
18
20
|
dbname: str
|
|
19
|
-
load: List[str]
|
|
21
|
+
load: List[Union[Path, str]]
|
|
20
22
|
postgres_options: str
|
|
21
23
|
|
|
22
24
|
|
|
@@ -27,6 +29,8 @@ def get_config(request: FixtureRequest) -> PostgresqlConfigDict:
|
|
|
27
29
|
name = "postgresql_" + option
|
|
28
30
|
return request.config.getoption(name) or request.config.getini(name)
|
|
29
31
|
|
|
32
|
+
load_paths = detect_paths(get_postgresql_option("load"))
|
|
33
|
+
|
|
30
34
|
return PostgresqlConfigDict(
|
|
31
35
|
exec=get_postgresql_option("exec"),
|
|
32
36
|
host=get_postgresql_option("host"),
|
|
@@ -37,6 +41,17 @@ def get_config(request: FixtureRequest) -> PostgresqlConfigDict:
|
|
|
37
41
|
startparams=get_postgresql_option("startparams"),
|
|
38
42
|
unixsocketdir=get_postgresql_option("unixsocketdir"),
|
|
39
43
|
dbname=get_postgresql_option("dbname"),
|
|
40
|
-
load=
|
|
44
|
+
load=load_paths,
|
|
41
45
|
postgres_options=get_postgresql_option("postgres_options"),
|
|
42
46
|
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def detect_paths(load_paths: List[str]) -> List[Union[Path, str]]:
|
|
50
|
+
"""Convert path to sql files to Path instances."""
|
|
51
|
+
converted_load_paths: List[Union[Path, str]] = []
|
|
52
|
+
for path in load_paths:
|
|
53
|
+
if path.endswith(".sql"):
|
|
54
|
+
converted_load_paths.append(Path(path))
|
|
55
|
+
else:
|
|
56
|
+
converted_load_paths.append(path)
|
|
57
|
+
return converted_load_paths
|
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
# This file is part of pytest-postgresql.
|
|
5
5
|
|
|
6
|
-
# pytest-
|
|
6
|
+
# pytest-postgresql is free software: you can redistribute it and/or modify
|
|
7
7
|
# it under the terms of the GNU Lesser General Public License as published by
|
|
8
8
|
# the Free Software Foundation, either version 3 of the License, or
|
|
9
9
|
# (at your option) any later version.
|
|
10
10
|
|
|
11
|
-
# pytest-
|
|
11
|
+
# pytest-postgresql is distributed in the hope that it will be useful,
|
|
12
12
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
13
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
14
|
# GNU Lesser General Public License for more details.
|
|
15
15
|
|
|
16
16
|
# You should have received a copy of the GNU Lesser General Public License
|
|
17
|
-
# along with pytest-
|
|
17
|
+
# along with pytest-postgresql. If not, see <http://www.gnu.org/licenses/>.
|
|
18
18
|
"""PostgreSQL executor crafter around pg_ctl."""
|
|
19
19
|
|
|
20
20
|
import os.path
|
|
@@ -131,6 +131,11 @@ class PostgreSQLExecutor(TCPExecutor):
|
|
|
131
131
|
},
|
|
132
132
|
)
|
|
133
133
|
|
|
134
|
+
@property
|
|
135
|
+
def template_dbname(self) -> str:
|
|
136
|
+
"""Return the template database name."""
|
|
137
|
+
return f"{self.dbname}_tmpl"
|
|
138
|
+
|
|
134
139
|
def start(self: T) -> T:
|
|
135
140
|
"""Add check for postgresql version before starting process."""
|
|
136
141
|
if self.version < self.MIN_SUPPORTED_VERSION:
|
|
@@ -172,11 +177,13 @@ class PostgreSQLExecutor(TCPExecutor):
|
|
|
172
177
|
password_file.write(password)
|
|
173
178
|
password_file.flush()
|
|
174
179
|
init_directory += ["-o", " ".join(options)]
|
|
175
|
-
|
|
180
|
+
# Passing envvars to command to avoid weird MacOs error.
|
|
181
|
+
subprocess.check_output(init_directory, env=self._envvars)
|
|
176
182
|
else:
|
|
177
183
|
options += ["--auth=trust"]
|
|
178
184
|
init_directory += ["-o", " ".join(options)]
|
|
179
|
-
|
|
185
|
+
# Passing envvars to command to avoid weird MacOs error.
|
|
186
|
+
subprocess.check_output(init_directory, env=self._envvars)
|
|
180
187
|
|
|
181
188
|
self._directory_initialised = True
|
|
182
189
|
|
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
# This file is part of pytest-postgresql.
|
|
5
5
|
|
|
6
|
-
# pytest-
|
|
6
|
+
# pytest-postgresql is free software: you can redistribute it and/or modify
|
|
7
7
|
# it under the terms of the GNU Lesser General Public License as published by
|
|
8
8
|
# the Free Software Foundation, either version 3 of the License, or
|
|
9
9
|
# (at your option) any later version.
|
|
10
10
|
|
|
11
|
-
# pytest-
|
|
11
|
+
# pytest-postgresql is distributed in the hope that it will be useful,
|
|
12
12
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
13
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
14
|
# GNU Lesser General Public License for more details.
|
|
15
15
|
|
|
16
16
|
# You should have received a copy of the GNU Lesser General Public License
|
|
17
|
-
# along with pytest-
|
|
17
|
+
# along with pytest-postgresql. If not, see <http://www.gnu.org/licenses/>.
|
|
18
18
|
"""PostgreSQL Noop executor providing connection details for postgres client."""
|
|
19
19
|
from typing import Any, Optional, Union
|
|
20
20
|
|
|
@@ -56,6 +56,11 @@ class NoopExecutor:
|
|
|
56
56
|
self.dbname = dbname
|
|
57
57
|
self._version: Any = None
|
|
58
58
|
|
|
59
|
+
@property
|
|
60
|
+
def template_dbname(self) -> str:
|
|
61
|
+
"""Return the template database name."""
|
|
62
|
+
return f"{self.dbname}_tmpl"
|
|
63
|
+
|
|
59
64
|
@property
|
|
60
65
|
def version(self) -> Any:
|
|
61
66
|
"""Get postgresql's version."""
|
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
# This file is part of pytest-postgresql.
|
|
5
5
|
|
|
6
|
-
# pytest-
|
|
6
|
+
# pytest-postgresql is free software: you can redistribute it and/or modify
|
|
7
7
|
# it under the terms of the GNU Lesser General Public License as published by
|
|
8
8
|
# the Free Software Foundation, either version 3 of the License, or
|
|
9
9
|
# (at your option) any later version.
|
|
10
10
|
|
|
11
|
-
# pytest-
|
|
11
|
+
# pytest-postgresql is distributed in the hope that it will be useful,
|
|
12
12
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
13
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
14
|
# GNU Lesser General Public License for more details.
|
|
15
15
|
|
|
16
16
|
# You should have received a copy of the GNU Lesser General Public License
|
|
17
|
-
# along with pytest-
|
|
17
|
+
# along with pytest-postgresql. If not, see <http://www.gnu.org/licenses/>.
|
|
18
18
|
"""Fixture factories for postgresql fixtures."""
|
|
19
19
|
|
|
20
20
|
from pytest_postgresql.factories.client import postgresql
|
|
@@ -3,19 +3,21 @@
|
|
|
3
3
|
|
|
4
4
|
# This file is part of pytest-postgresql.
|
|
5
5
|
|
|
6
|
-
# pytest-
|
|
6
|
+
# pytest-postgresql is free software: you can redistribute it and/or modify
|
|
7
7
|
# it under the terms of the GNU Lesser General Public License as published by
|
|
8
8
|
# the Free Software Foundation, either version 3 of the License, or
|
|
9
9
|
# (at your option) any later version.
|
|
10
10
|
|
|
11
|
-
# pytest-
|
|
11
|
+
# pytest-postgresql is distributed in the hope that it will be useful,
|
|
12
12
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
13
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
14
|
# GNU Lesser General Public License for more details.
|
|
15
15
|
|
|
16
16
|
# You should have received a copy of the GNU Lesser General Public License
|
|
17
|
-
# along with pytest-
|
|
17
|
+
# along with pytest-postgresql. If not, see <http://www.gnu.org/licenses/>.
|
|
18
18
|
"""Fixture factory for postgresql client."""
|
|
19
|
+
import warnings
|
|
20
|
+
from pathlib import Path
|
|
19
21
|
from typing import Callable, Iterator, List, Optional, Union
|
|
20
22
|
|
|
21
23
|
import psycopg
|
|
@@ -31,7 +33,7 @@ from pytest_postgresql.janitor import DatabaseJanitor
|
|
|
31
33
|
def postgresql(
|
|
32
34
|
process_fixture_name: str,
|
|
33
35
|
dbname: Optional[str] = None,
|
|
34
|
-
load: Optional[List[Union[Callable, str]]] = None,
|
|
36
|
+
load: Optional[List[Union[Callable, str, Path]]] = None,
|
|
35
37
|
isolation_level: "Optional[psycopg.IsolationLevel]" = None,
|
|
36
38
|
) -> Callable[[FixtureRequest], Iterator[Connection]]:
|
|
37
39
|
"""Return connection fixture factory for PostgreSQL.
|
|
@@ -63,9 +65,25 @@ def postgresql(
|
|
|
63
65
|
pg_options = proc_fixture.options
|
|
64
66
|
pg_db = dbname or proc_fixture.dbname
|
|
65
67
|
pg_load = load or []
|
|
66
|
-
|
|
68
|
+
if pg_load:
|
|
69
|
+
warnings.warn(
|
|
70
|
+
message=(
|
|
71
|
+
"Load is deprecated on a client fixture. "
|
|
72
|
+
"You should either process fixture load parameter to pre-fill database, "
|
|
73
|
+
"or add a fixture between client and a test, "
|
|
74
|
+
"that will fill the database with the data."
|
|
75
|
+
),
|
|
76
|
+
category=DeprecationWarning,
|
|
77
|
+
)
|
|
67
78
|
with DatabaseJanitor(
|
|
68
|
-
pg_user,
|
|
79
|
+
user=pg_user,
|
|
80
|
+
host=pg_host,
|
|
81
|
+
port=pg_port,
|
|
82
|
+
dbname=pg_db,
|
|
83
|
+
template_dbname=proc_fixture.template_dbname,
|
|
84
|
+
version=proc_fixture.version,
|
|
85
|
+
password=pg_password,
|
|
86
|
+
isolation_level=isolation_level,
|
|
69
87
|
) as janitor:
|
|
70
88
|
db_connection: Connection = psycopg.connect(
|
|
71
89
|
dbname=pg_db,
|
{pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql/factories/noprocess.py
RENAMED
|
@@ -3,20 +3,21 @@
|
|
|
3
3
|
|
|
4
4
|
# This file is part of pytest-postgresql.
|
|
5
5
|
|
|
6
|
-
# pytest-
|
|
6
|
+
# pytest-postgresql is free software: you can redistribute it and/or modify
|
|
7
7
|
# it under the terms of the GNU Lesser General Public License as published by
|
|
8
8
|
# the Free Software Foundation, either version 3 of the License, or
|
|
9
9
|
# (at your option) any later version.
|
|
10
10
|
|
|
11
|
-
# pytest-
|
|
11
|
+
# pytest-postgresql is distributed in the hope that it will be useful,
|
|
12
12
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
13
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
14
|
# GNU Lesser General Public License for more details.
|
|
15
15
|
|
|
16
16
|
# You should have received a copy of the GNU Lesser General Public License
|
|
17
|
-
# along with pytest-
|
|
17
|
+
# along with pytest-postgresql. If not, see <http://www.gnu.org/licenses/>.
|
|
18
18
|
"""Fixture factory for existing postgresql server."""
|
|
19
19
|
import os
|
|
20
|
+
from pathlib import Path
|
|
20
21
|
from typing import Callable, Iterator, List, Optional, Union
|
|
21
22
|
|
|
22
23
|
import pytest
|
|
@@ -42,7 +43,7 @@ def postgresql_noproc(
|
|
|
42
43
|
password: Optional[str] = None,
|
|
43
44
|
dbname: Optional[str] = None,
|
|
44
45
|
options: str = "",
|
|
45
|
-
load: Optional[List[Union[Callable, str]]] = None,
|
|
46
|
+
load: Optional[List[Union[Callable, str, Path]]] = None,
|
|
46
47
|
) -> Callable[[FixtureRequest], Iterator[NoopExecutor]]:
|
|
47
48
|
"""Postgresql noprocess factory.
|
|
48
49
|
|
|
@@ -80,12 +81,11 @@ def postgresql_noproc(
|
|
|
80
81
|
dbname=pg_dbname,
|
|
81
82
|
options=pg_options,
|
|
82
83
|
)
|
|
83
|
-
template_dbname = f"{noop_exec.dbname}_tmpl"
|
|
84
84
|
with DatabaseJanitor(
|
|
85
85
|
user=noop_exec.user,
|
|
86
86
|
host=noop_exec.host,
|
|
87
87
|
port=noop_exec.port,
|
|
88
|
-
|
|
88
|
+
template_dbname=noop_exec.template_dbname,
|
|
89
89
|
version=noop_exec.version,
|
|
90
90
|
password=noop_exec.password,
|
|
91
91
|
) as janitor:
|
|
@@ -3,22 +3,23 @@
|
|
|
3
3
|
|
|
4
4
|
# This file is part of pytest-postgresql.
|
|
5
5
|
|
|
6
|
-
# pytest-
|
|
6
|
+
# pytest-postgresql is free software: you can redistribute it and/or modify
|
|
7
7
|
# it under the terms of the GNU Lesser General Public License as published by
|
|
8
8
|
# the Free Software Foundation, either version 3 of the License, or
|
|
9
9
|
# (at your option) any later version.
|
|
10
10
|
|
|
11
|
-
# pytest-
|
|
11
|
+
# pytest-postgresql is distributed in the hope that it will be useful,
|
|
12
12
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
13
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
14
|
# GNU Lesser General Public License for more details.
|
|
15
15
|
|
|
16
16
|
# You should have received a copy of the GNU Lesser General Public License
|
|
17
|
-
# along with pytest-
|
|
17
|
+
# along with pytest-postgresql. If not, see <http://www.gnu.org/licenses/>.
|
|
18
18
|
"""Fixture factory for postgresql process."""
|
|
19
19
|
import os.path
|
|
20
20
|
import platform
|
|
21
21
|
import subprocess
|
|
22
|
+
from pathlib import Path
|
|
22
23
|
from typing import Callable, Iterator, List, Optional, Set, Tuple, Union
|
|
23
24
|
|
|
24
25
|
import pytest
|
|
@@ -54,7 +55,7 @@ def postgresql_proc(
|
|
|
54
55
|
startparams: Optional[str] = None,
|
|
55
56
|
unixsocketdir: Optional[str] = None,
|
|
56
57
|
postgres_options: Optional[str] = None,
|
|
57
|
-
load: Optional[List[Union[Callable, str]]] = None,
|
|
58
|
+
load: Optional[List[Union[Callable, str, Path]]] = None,
|
|
58
59
|
) -> Callable[[FixtureRequest, TempPathFactory], Iterator[PostgreSQLExecutor]]:
|
|
59
60
|
"""Postgresql process factory.
|
|
60
61
|
|
|
@@ -135,12 +136,11 @@ def postgresql_proc(
|
|
|
135
136
|
# start server
|
|
136
137
|
with postgresql_executor:
|
|
137
138
|
postgresql_executor.wait_for_postgres()
|
|
138
|
-
template_dbname = f"{postgresql_executor.dbname}_tmpl"
|
|
139
139
|
with DatabaseJanitor(
|
|
140
140
|
user=postgresql_executor.user,
|
|
141
141
|
host=postgresql_executor.host,
|
|
142
142
|
port=postgresql_executor.port,
|
|
143
|
-
|
|
143
|
+
template_dbname=postgresql_executor.template_dbname,
|
|
144
144
|
version=postgresql_executor.version,
|
|
145
145
|
password=postgresql_executor.password,
|
|
146
146
|
) as janitor:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Database Janitor."""
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
from contextlib import contextmanager
|
|
4
|
-
from
|
|
4
|
+
from pathlib import Path
|
|
5
5
|
from types import TracebackType
|
|
6
6
|
from typing import Callable, Iterator, Optional, Type, TypeVar, Union
|
|
7
7
|
|
|
@@ -9,8 +9,8 @@ import psycopg
|
|
|
9
9
|
from packaging.version import parse
|
|
10
10
|
from psycopg import Connection, Cursor
|
|
11
11
|
|
|
12
|
+
from pytest_postgresql.loader import build_loader
|
|
12
13
|
from pytest_postgresql.retry import retry
|
|
13
|
-
from pytest_postgresql.sql import loader
|
|
14
14
|
|
|
15
15
|
Version = type(parse("1"))
|
|
16
16
|
|
|
@@ -23,11 +23,13 @@ class DatabaseJanitor:
|
|
|
23
23
|
|
|
24
24
|
def __init__(
|
|
25
25
|
self,
|
|
26
|
+
*,
|
|
26
27
|
user: str,
|
|
27
28
|
host: str,
|
|
28
29
|
port: Union[str, int],
|
|
29
|
-
dbname: str,
|
|
30
30
|
version: Union[str, float, Version], # type: ignore[valid-type]
|
|
31
|
+
dbname: Optional[str] = None,
|
|
32
|
+
template_dbname: Optional[str] = None,
|
|
31
33
|
password: Optional[str] = None,
|
|
32
34
|
isolation_level: "Optional[psycopg.IsolationLevel]" = None,
|
|
33
35
|
connection_timeout: int = 60,
|
|
@@ -38,6 +40,7 @@ class DatabaseJanitor:
|
|
|
38
40
|
:param host: postgresql host
|
|
39
41
|
:param port: postgresql port
|
|
40
42
|
:param dbname: database name
|
|
43
|
+
:param dbname: template database name
|
|
41
44
|
:param version: postgresql version number
|
|
42
45
|
:param password: optional postgresql password
|
|
43
46
|
:param isolation_level: optional postgresql isolation level
|
|
@@ -49,7 +52,10 @@ class DatabaseJanitor:
|
|
|
49
52
|
self.password = password
|
|
50
53
|
self.host = host
|
|
51
54
|
self.port = port
|
|
55
|
+
# At least one of the dbname or template_dbname has to be filled.
|
|
56
|
+
assert any([dbname, template_dbname])
|
|
52
57
|
self.dbname = dbname
|
|
58
|
+
self.template_dbname = template_dbname
|
|
53
59
|
self._connection_timeout = connection_timeout
|
|
54
60
|
self.isolation_level = isolation_level
|
|
55
61
|
if not isinstance(version, Version):
|
|
@@ -59,36 +65,33 @@ class DatabaseJanitor:
|
|
|
59
65
|
|
|
60
66
|
def init(self) -> None:
|
|
61
67
|
"""Create database in postgresql."""
|
|
62
|
-
template_name = f"{self.dbname}_tmpl"
|
|
63
68
|
with self.cursor() as cur:
|
|
64
|
-
if self.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
cur.execute(
|
|
68
|
-
"SELECT EXISTS "
|
|
69
|
-
"(SELECT datname FROM pg_catalog.pg_database WHERE datname= %s);",
|
|
70
|
-
(template_name,),
|
|
71
|
-
)
|
|
72
|
-
row = cur.fetchone()
|
|
73
|
-
result = (row is not None) and row[0]
|
|
74
|
-
if not result:
|
|
69
|
+
if self.is_template():
|
|
70
|
+
cur.execute(f'CREATE DATABASE "{self.template_dbname}" WITH is_template = true;')
|
|
71
|
+
elif self.template_dbname is None:
|
|
75
72
|
cur.execute(f'CREATE DATABASE "{self.dbname}";')
|
|
76
73
|
else:
|
|
77
|
-
# All template database does not allow connection:
|
|
78
|
-
self._dont_datallowconn(cur, template_name)
|
|
79
74
|
# And make sure no-one is left connected to the template database.
|
|
80
|
-
# Otherwise Creating database from template will fail
|
|
81
|
-
self._terminate_connection(cur,
|
|
82
|
-
cur.execute(f'CREATE DATABASE "{self.dbname}" TEMPLATE "{
|
|
75
|
+
# Otherwise, Creating database from template will fail
|
|
76
|
+
self._terminate_connection(cur, self.template_dbname)
|
|
77
|
+
cur.execute(f'CREATE DATABASE "{self.dbname}" TEMPLATE "{self.template_dbname}";')
|
|
78
|
+
|
|
79
|
+
def is_template(self) -> bool:
|
|
80
|
+
"""Determine whether the DatabaseJanitor maintains template or database."""
|
|
81
|
+
return self.dbname is None
|
|
83
82
|
|
|
84
83
|
def drop(self) -> None:
|
|
85
84
|
"""Drop database in postgresql."""
|
|
86
85
|
# We cannot drop the database while there are connections to it, so we
|
|
87
86
|
# terminate all connections first while not allowing new connections.
|
|
87
|
+
db_to_drop = self.template_dbname if self.is_template() else self.dbname
|
|
88
|
+
assert db_to_drop
|
|
88
89
|
with self.cursor() as cur:
|
|
89
|
-
self._dont_datallowconn(cur,
|
|
90
|
-
self._terminate_connection(cur,
|
|
91
|
-
|
|
90
|
+
self._dont_datallowconn(cur, db_to_drop)
|
|
91
|
+
self._terminate_connection(cur, db_to_drop)
|
|
92
|
+
if self.is_template():
|
|
93
|
+
cur.execute(f'ALTER DATABASE "{db_to_drop}" with is_template false;')
|
|
94
|
+
cur.execute(f'DROP DATABASE IF EXISTS "{db_to_drop}";')
|
|
92
95
|
|
|
93
96
|
@staticmethod
|
|
94
97
|
def _dont_datallowconn(cur: Cursor, dbname: str) -> None:
|
|
@@ -103,28 +106,23 @@ class DatabaseJanitor:
|
|
|
103
106
|
(dbname,),
|
|
104
107
|
)
|
|
105
108
|
|
|
106
|
-
def load(self, load: Union[Callable, str]) -> None:
|
|
109
|
+
def load(self, load: Union[Callable, str, Path]) -> None:
|
|
107
110
|
"""Load data into a database.
|
|
108
111
|
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
Expects:
|
|
113
|
+
|
|
114
|
+
* a Path to sql file, that'll be loaded
|
|
115
|
+
* an import path to import callable
|
|
116
|
+
* a callable that expects: host, port, user, dbname and password arguments.
|
|
117
|
+
|
|
111
118
|
"""
|
|
112
|
-
if
|
|
113
|
-
|
|
114
|
-
_loader: Callable = partial(loader, load)
|
|
115
|
-
else:
|
|
116
|
-
loader_parts = re.split("[.:]", load, 2)
|
|
117
|
-
import_path = ".".join(loader_parts[:-1])
|
|
118
|
-
loader_name = loader_parts[-1]
|
|
119
|
-
_temp_import = __import__(import_path, globals(), locals(), fromlist=[loader_name])
|
|
120
|
-
_loader = getattr(_temp_import, loader_name)
|
|
121
|
-
else:
|
|
122
|
-
_loader = load
|
|
119
|
+
db_to_load = self.template_dbname if self.is_template() else self.dbname
|
|
120
|
+
_loader = build_loader(load)
|
|
123
121
|
_loader(
|
|
124
122
|
host=self.host,
|
|
125
123
|
port=self.port,
|
|
126
124
|
user=self.user,
|
|
127
|
-
dbname=
|
|
125
|
+
dbname=db_to_load,
|
|
128
126
|
password=self.password,
|
|
129
127
|
)
|
|
130
128
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Loader helper functions."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from functools import partial
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Callable, Union
|
|
7
|
+
|
|
8
|
+
import psycopg
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def build_loader(load: Union[Callable, str, Path]) -> Callable:
|
|
12
|
+
"""Build a loader callable."""
|
|
13
|
+
if isinstance(load, Path):
|
|
14
|
+
return partial(sql, load)
|
|
15
|
+
elif isinstance(load, str):
|
|
16
|
+
loader_parts = re.split("[.:]", load, 2)
|
|
17
|
+
import_path = ".".join(loader_parts[:-1])
|
|
18
|
+
loader_name = loader_parts[-1]
|
|
19
|
+
_temp_import = __import__(import_path, globals(), locals(), fromlist=[loader_name])
|
|
20
|
+
_loader: Callable = getattr(_temp_import, loader_name)
|
|
21
|
+
return _loader
|
|
22
|
+
else:
|
|
23
|
+
return load
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def sql(sql_filename: Path, **kwargs: Any) -> None:
|
|
27
|
+
"""Database loader for sql files."""
|
|
28
|
+
db_connection = psycopg.connect(**kwargs)
|
|
29
|
+
with open(sql_filename, "r") as _fd:
|
|
30
|
+
with db_connection.cursor() as cur:
|
|
31
|
+
cur.execute(_fd.read())
|
|
32
|
+
db_connection.commit()
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# This file is part of pytest-postgresql.
|
|
5
5
|
|
|
6
|
-
# pytest-
|
|
6
|
+
# pytest-postgresql is free software: you can redistribute it and/or modify
|
|
7
7
|
# it under the terms of the GNU Lesser General Public License as published by
|
|
8
8
|
# the Free Software Foundation, either version 3 of the License, or
|
|
9
9
|
# (at your option) any later version.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Small retry callable in case of specific error occurred."""
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
import sys
|
|
5
|
+
from time import sleep
|
|
6
|
+
from typing import Callable, Type, TypeVar
|
|
7
|
+
|
|
8
|
+
T = TypeVar("T")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def retry(
|
|
12
|
+
func: Callable[[], T],
|
|
13
|
+
timeout: int = 60,
|
|
14
|
+
possible_exception: Type[Exception] = Exception,
|
|
15
|
+
) -> T:
|
|
16
|
+
"""Attempt to retry the function for timeout time.
|
|
17
|
+
|
|
18
|
+
Most often used for connecting to postgresql database as,
|
|
19
|
+
especially on macos on github-actions, first few tries fails
|
|
20
|
+
with this message:
|
|
21
|
+
|
|
22
|
+
... ::
|
|
23
|
+
FATAL: the database system is starting up
|
|
24
|
+
"""
|
|
25
|
+
time: datetime.datetime = get_current_datetime()
|
|
26
|
+
timeout_diff: datetime.timedelta = datetime.timedelta(seconds=timeout)
|
|
27
|
+
i = 0
|
|
28
|
+
while True:
|
|
29
|
+
i += 1
|
|
30
|
+
try:
|
|
31
|
+
res = func()
|
|
32
|
+
return res
|
|
33
|
+
except possible_exception as e:
|
|
34
|
+
if time + timeout_diff < get_current_datetime():
|
|
35
|
+
raise TimeoutError(f"Failed after {i} attempts") from e
|
|
36
|
+
sleep(1)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def get_current_datetime() -> datetime.datetime:
|
|
40
|
+
"""Get the current datetime."""
|
|
41
|
+
# To ensure the current datetime retrieval is adjusted with the latest
|
|
42
|
+
# versions of Python while ensuring retro-compatibility with
|
|
43
|
+
# Python 3.8, 3.9 and 3.10, we check what version of Python is
|
|
44
|
+
# being used before deciding how to operate
|
|
45
|
+
if sys.version_info.major == 3 and sys.version_info.minor > 10:
|
|
46
|
+
return datetime.datetime.now(datetime.UTC)
|
|
47
|
+
|
|
48
|
+
return datetime.datetime.utcnow()
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pytest-postgresql
|
|
3
|
-
Version:
|
|
3
|
+
Version: 6.0.1
|
|
4
4
|
Summary: Postgresql fixtures and fixture factories for Pytest.
|
|
5
5
|
Author-email: Grzegorz Śliwiński <fizyk+pypi@fizyk.dev>
|
|
6
6
|
Project-URL: Source, https://github.com/ClearcodeHQ/pytest-postgresql
|
|
7
7
|
Project-URL: Bug Tracker, https://github.com/ClearcodeHQ/pytest-postgresql/issues
|
|
8
|
-
Project-URL: Changelog, https://github.com/ClearcodeHQ/pytest-postgresql/blob/
|
|
8
|
+
Project-URL: Changelog, https://github.com/ClearcodeHQ/pytest-postgresql/blob/v6.0.1/CHANGES.rst
|
|
9
9
|
Keywords: tests,pytest,fixture,postgresql
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Environment :: Web Environment
|
|
@@ -141,9 +141,10 @@ Client specific loads the database each test
|
|
|
141
141
|
|
|
142
142
|
.. code-block:: python
|
|
143
143
|
|
|
144
|
+
from pathlib import Path
|
|
144
145
|
postgresql_my_with_schema = factories.postgresql(
|
|
145
146
|
'postgresql_my_proc',
|
|
146
|
-
load=["schemafile.sql", "otherschema.sql", "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
147
|
+
load=[Path("schemafile.sql"), Path("otherschema.sql"), "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
147
148
|
)
|
|
148
149
|
|
|
149
150
|
.. warning::
|
|
@@ -152,12 +153,13 @@ Client specific loads the database each test
|
|
|
152
153
|
|
|
153
154
|
|
|
154
155
|
The process fixture performs the load once per test session, and loads the data into the template database.
|
|
155
|
-
Client fixture then creates test database out of the template database each test, which significantly speeds up the tests
|
|
156
|
+
Client fixture then creates test database out of the template database each test, which significantly **speeds up the tests**.
|
|
156
157
|
|
|
157
158
|
.. code-block:: python
|
|
158
159
|
|
|
160
|
+
from pathlib import Path
|
|
159
161
|
postgresql_my_proc = factories.postgresql_proc(
|
|
160
|
-
load=["schemafile.sql", "otherschema.sql", "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
162
|
+
load=[Path("schemafile.sql"), Path("otherschema.sql"), "import.path.to.function", "import.path.to:otherfunction", load_this]
|
|
161
163
|
)
|
|
162
164
|
|
|
163
165
|
|
|
@@ -511,7 +513,7 @@ it'll be on a docker machine or running remotely or locally.
|
|
|
511
513
|
Using SQLAlchemy to initialise basic database state
|
|
512
514
|
+++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
513
515
|
|
|
514
|
-
How to use SQLAlchemy for common
|
|
516
|
+
How to use SQLAlchemy for common initialisation:
|
|
515
517
|
|
|
516
518
|
.. code-block:: python
|
|
517
519
|
|
|
@@ -12,10 +12,10 @@ pytest_postgresql/exceptions.py
|
|
|
12
12
|
pytest_postgresql/executor.py
|
|
13
13
|
pytest_postgresql/executor_noop.py
|
|
14
14
|
pytest_postgresql/janitor.py
|
|
15
|
+
pytest_postgresql/loader.py
|
|
15
16
|
pytest_postgresql/plugin.py
|
|
16
17
|
pytest_postgresql/py.typed
|
|
17
18
|
pytest_postgresql/retry.py
|
|
18
|
-
pytest_postgresql/sql.py
|
|
19
19
|
pytest_postgresql.egg-info/PKG-INFO
|
|
20
20
|
pytest_postgresql.egg-info/SOURCES.txt
|
|
21
21
|
pytest_postgresql.egg-info/dependency_links.txt
|
|
@@ -29,6 +29,7 @@ pytest_postgresql/factories/noprocess.py
|
|
|
29
29
|
pytest_postgresql/factories/process.py
|
|
30
30
|
tests/test_executor.py
|
|
31
31
|
tests/test_janitor.py
|
|
32
|
+
tests/test_loader.py
|
|
32
33
|
tests/test_noopexecutor.py
|
|
33
34
|
tests/test_postgres_options_plugin.py
|
|
34
35
|
tests/test_postgresql.py
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Database Janitor tests."""
|
|
2
|
+
|
|
2
3
|
import sys
|
|
3
4
|
from typing import Any
|
|
4
5
|
from unittest.mock import MagicMock, patch
|
|
@@ -14,14 +15,18 @@ VERSION = parse("10")
|
|
|
14
15
|
@pytest.mark.parametrize("version", (VERSION, 10, "10"))
|
|
15
16
|
def test_version_cast(version: Any) -> None:
|
|
16
17
|
"""Test that version is cast to Version object."""
|
|
17
|
-
janitor = DatabaseJanitor(
|
|
18
|
+
janitor = DatabaseJanitor(
|
|
19
|
+
user="user", host="host", port="1234", dbname="database_name", version=version
|
|
20
|
+
)
|
|
18
21
|
assert janitor.version == VERSION
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
@patch("pytest_postgresql.janitor.psycopg.connect")
|
|
22
25
|
def test_cursor_selects_postgres_database(connect_mock: MagicMock) -> None:
|
|
23
26
|
"""Test that the cursor requests the postgres database."""
|
|
24
|
-
janitor = DatabaseJanitor(
|
|
27
|
+
janitor = DatabaseJanitor(
|
|
28
|
+
user="user", host="host", port="1234", dbname="database_name", version=10
|
|
29
|
+
)
|
|
25
30
|
with janitor.cursor():
|
|
26
31
|
connect_mock.assert_called_once_with(
|
|
27
32
|
dbname="postgres", user="user", password=None, host="host", port="1234"
|
|
@@ -31,7 +36,14 @@ def test_cursor_selects_postgres_database(connect_mock: MagicMock) -> None:
|
|
|
31
36
|
@patch("pytest_postgresql.janitor.psycopg.connect")
|
|
32
37
|
def test_cursor_connects_with_password(connect_mock: MagicMock) -> None:
|
|
33
38
|
"""Test that the cursor requests the postgres database."""
|
|
34
|
-
janitor = DatabaseJanitor(
|
|
39
|
+
janitor = DatabaseJanitor(
|
|
40
|
+
user="user",
|
|
41
|
+
host="host",
|
|
42
|
+
port="1234",
|
|
43
|
+
dbname="database_name",
|
|
44
|
+
version=10,
|
|
45
|
+
password="some_password",
|
|
46
|
+
)
|
|
35
47
|
with janitor.cursor():
|
|
36
48
|
connect_mock.assert_called_once_with(
|
|
37
49
|
dbname="postgres", user="user", password="some_password", host="host", port="1234"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Tests for the `build_loader` function."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from pytest_postgresql.loader import build_loader, sql
|
|
6
|
+
from tests.loader import load_database
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_loader_callables() -> None:
|
|
10
|
+
"""Test handling callables in build_loader."""
|
|
11
|
+
assert load_database == build_loader(load_database)
|
|
12
|
+
assert load_database == build_loader("tests.loader:load_database")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_loader_sql() -> None:
|
|
16
|
+
"""Test returning partial running sql for the sql file path."""
|
|
17
|
+
sql_path = Path("test_sql/eidastats.sql")
|
|
18
|
+
loader_func = build_loader(sql_path)
|
|
19
|
+
assert loader_func.args == (sql_path,) # type: ignore
|
|
20
|
+
assert loader_func.func == sql # type: ignore
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Test behavior of postgres_options passed in different ways."""
|
|
2
|
+
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
|
|
4
5
|
import pytest
|
|
@@ -32,3 +33,11 @@ def test_postgres_options_config_in_ini(pointed_pytester: Pytester) -> None:
|
|
|
32
33
|
pointed_pytester.makefile(".ini", pytest="[pytest]\npostgresql_postgres_options = -N 16\n")
|
|
33
34
|
ret = pointed_pytester.runpytest("test_postgres_options.py")
|
|
34
35
|
ret.assert_outcomes(passed=1)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_postgres_loader_in_cli(pointed_pytester: Pytester) -> None:
|
|
39
|
+
"""Check that command line arguments are honored."""
|
|
40
|
+
pointed_pytester.copy_example("test_load.py")
|
|
41
|
+
test_sql_path = pointed_pytester.copy_example("test.sql")
|
|
42
|
+
ret = pointed_pytester.runpytest(f"--postgresql-load={test_sql_path}", "test_load.py")
|
|
43
|
+
ret.assert_outcomes(passed=1)
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"""Small retry callable in case of specific error occurred."""
|
|
2
|
-
|
|
3
|
-
from datetime import datetime, timedelta
|
|
4
|
-
from time import sleep
|
|
5
|
-
from typing import Callable, Type, TypeVar
|
|
6
|
-
|
|
7
|
-
T = TypeVar("T")
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def retry(
|
|
11
|
-
func: Callable[[], T], timeout: int = 60, possible_exception: Type[Exception] = Exception
|
|
12
|
-
) -> T:
|
|
13
|
-
"""Attempt to retry the function for timeout time.
|
|
14
|
-
|
|
15
|
-
Most often used for connecting to postgresql database as,
|
|
16
|
-
especially on macos on github-actions, first few tries fails
|
|
17
|
-
with this message:
|
|
18
|
-
|
|
19
|
-
... ::
|
|
20
|
-
FATAL: the database system is starting up
|
|
21
|
-
"""
|
|
22
|
-
time: datetime = datetime.utcnow()
|
|
23
|
-
timeout_diff: timedelta = timedelta(seconds=timeout)
|
|
24
|
-
i = 0
|
|
25
|
-
while True:
|
|
26
|
-
i += 1
|
|
27
|
-
try:
|
|
28
|
-
res = func()
|
|
29
|
-
return res
|
|
30
|
-
except possible_exception as e:
|
|
31
|
-
if time + timeout_diff < datetime.utcnow():
|
|
32
|
-
raise TimeoutError(f"Failed after {i} attempts") from e
|
|
33
|
-
sleep(1)
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"""SQL Loader function."""
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
import psycopg
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def loader(sql_filename: str, **kwargs: Any) -> None:
|
|
8
|
-
"""Database loader for sql files."""
|
|
9
|
-
db_connection = psycopg.connect(**kwargs)
|
|
10
|
-
with open(sql_filename, "r") as _fd:
|
|
11
|
-
with db_connection.cursor() as cur:
|
|
12
|
-
cur.execute(_fd.read())
|
|
13
|
-
db_connection.commit()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{pytest-postgresql-5.1.1 → pytest_postgresql-6.0.1}/pytest_postgresql.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|