fast-test-database 0.1.2__tar.gz → 0.2.0__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.
- {fast-test-database-0.1.2 → fast_test_database-0.2.0}/PKG-INFO +5 -6
- {fast-test-database-0.1.2 → fast_test_database-0.2.0}/fast_test_database/__init__.py +47 -53
- {fast-test-database-0.1.2 → fast_test_database-0.2.0}/pyproject.toml +8 -6
- fast-test-database-0.1.2/setup.py +0 -30
- {fast-test-database-0.1.2 → fast_test_database-0.2.0}/README.rst +0 -0
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fast-test-database
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Configure an in-memory database for running Django tests
|
|
5
5
|
License: GPL-3.0-or-later
|
|
6
6
|
Author: Alexey Kotlyarov
|
|
7
7
|
Author-email: a@koterpillar.com
|
|
8
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.11,<4.0
|
|
9
9
|
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.
|
|
13
|
-
|
|
14
|
-
Requires-Dist: Django (>=3.0,<4.0)
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Requires-Dist: Django (>=5.0.0,<6.0.0)
|
|
15
14
|
Description-Content-Type: text/x-rst
|
|
16
15
|
|
|
17
16
|
Fast test database
|
|
@@ -13,7 +13,7 @@ from time import sleep
|
|
|
13
13
|
def docker(*args):
|
|
14
14
|
"""Run Docker with the specified arguments and return the output."""
|
|
15
15
|
|
|
16
|
-
return subprocess.check_output((
|
|
16
|
+
return subprocess.check_output(("docker",) + args).decode().strip()
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class DatabaseProvider(object):
|
|
@@ -35,18 +35,12 @@ class DatabaseProvider(object):
|
|
|
35
35
|
@property
|
|
36
36
|
def container_name(self):
|
|
37
37
|
"""The Docker container name."""
|
|
38
|
-
return
|
|
39
|
-
os.path.basename(os.getcwd()),
|
|
40
|
-
self.image.replace('/', '.').replace(':', '-'),
|
|
41
|
-
)
|
|
38
|
+
return f"fast_database_{os.path.basename(os.getcwd())}_{self.image.replace('/', '.').replace(':', '-')}"
|
|
42
39
|
|
|
43
40
|
@property
|
|
44
41
|
def image(self):
|
|
45
42
|
"""The Docker image."""
|
|
46
|
-
return
|
|
47
|
-
self.IMAGE,
|
|
48
|
-
self.version or 'latest'
|
|
49
|
-
)
|
|
43
|
+
return f"{self.IMAGE}:{self.version or 'latest'}"
|
|
50
44
|
|
|
51
45
|
def provide(self, engine):
|
|
52
46
|
"""
|
|
@@ -56,38 +50,38 @@ class DatabaseProvider(object):
|
|
|
56
50
|
"""
|
|
57
51
|
|
|
58
52
|
# TODO: Randomize password
|
|
59
|
-
password =
|
|
53
|
+
password = "fast_database"
|
|
60
54
|
|
|
61
55
|
try:
|
|
62
|
-
container = json.loads(docker(
|
|
63
|
-
available = container[0][
|
|
56
|
+
container = json.loads(docker("inspect", self.container_name))
|
|
57
|
+
available = container[0]["State"]["Running"]
|
|
64
58
|
except (LookupError, ValueError, subprocess.CalledProcessError):
|
|
65
59
|
available = False
|
|
66
60
|
|
|
67
61
|
if not available:
|
|
68
62
|
# Delete the old container in case it's stopped
|
|
69
63
|
try:
|
|
70
|
-
docker(
|
|
64
|
+
docker("rm", "-f", self.container_name)
|
|
71
65
|
except subprocess.CalledProcessError:
|
|
72
66
|
pass
|
|
73
67
|
|
|
74
|
-
args = [
|
|
75
|
-
'run',
|
|
76
|
-
'--detach',
|
|
77
|
-
'--env', '{}={}'.format(self.PASSWORD_ENV_VAR, password),
|
|
78
|
-
]
|
|
68
|
+
args = ["run", "--detach", "--env", f"{self.PASSWORD_ENV_VAR}={password}"]
|
|
79
69
|
|
|
80
70
|
# Add custom environment variables
|
|
81
71
|
if self.CUSTOM_ENV:
|
|
82
72
|
for k, v in self.CUSTOM_ENV.items():
|
|
83
|
-
args.extend([
|
|
84
|
-
|
|
85
|
-
args.extend(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
73
|
+
args.extend(["--env", f"{k}={v}"])
|
|
74
|
+
|
|
75
|
+
args.extend(
|
|
76
|
+
[
|
|
77
|
+
f"--tmpfs={self.DATA_DIR}",
|
|
78
|
+
"--publish",
|
|
79
|
+
str(self.PORT),
|
|
80
|
+
"--name",
|
|
81
|
+
self.container_name,
|
|
82
|
+
self.image,
|
|
83
|
+
]
|
|
84
|
+
)
|
|
91
85
|
|
|
92
86
|
docker(*args)
|
|
93
87
|
# Give it time to start
|
|
@@ -97,44 +91,46 @@ class DatabaseProvider(object):
|
|
|
97
91
|
0.0.0.0:49153
|
|
98
92
|
0.0.0.0:49153\n:::49153
|
|
99
93
|
"""
|
|
100
|
-
host, port =
|
|
101
|
-
|
|
102
|
-
|
|
94
|
+
host, port = (
|
|
95
|
+
docker("port", self.container_name, str(self.PORT))
|
|
96
|
+
.splitlines()[0]
|
|
97
|
+
.split(":")
|
|
98
|
+
)
|
|
103
99
|
port = int(port)
|
|
104
100
|
|
|
105
101
|
return {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
102
|
+
"ENGINE": engine,
|
|
103
|
+
"NAME": self.DATABASE,
|
|
104
|
+
"USER": self.USER,
|
|
105
|
+
"PASSWORD": password,
|
|
106
|
+
"HOST": host,
|
|
107
|
+
"PORT": port,
|
|
112
108
|
}
|
|
113
109
|
|
|
114
110
|
|
|
115
111
|
class PostgreSQL(DatabaseProvider):
|
|
116
112
|
"""Provide a PostgreSQL database via Docker."""
|
|
117
113
|
|
|
118
|
-
IMAGE =
|
|
114
|
+
IMAGE = "postgres"
|
|
119
115
|
PORT = 5432
|
|
120
|
-
PASSWORD_ENV_VAR =
|
|
121
|
-
DATA_DIR =
|
|
122
|
-
ENGINE_MATCH =
|
|
123
|
-
USER =
|
|
124
|
-
DATABASE =
|
|
116
|
+
PASSWORD_ENV_VAR = "POSTGRES_PASSWORD"
|
|
117
|
+
DATA_DIR = "/var/lib/postgresql/data"
|
|
118
|
+
ENGINE_MATCH = "postgresql"
|
|
119
|
+
USER = "postgres"
|
|
120
|
+
DATABASE = "postgres"
|
|
125
121
|
|
|
126
122
|
|
|
127
123
|
class MySQL(DatabaseProvider):
|
|
128
124
|
"""Provide a MySQL database via Docker."""
|
|
129
125
|
|
|
130
|
-
IMAGE =
|
|
126
|
+
IMAGE = "mysql"
|
|
131
127
|
PORT = 3306
|
|
132
|
-
PASSWORD_ENV_VAR =
|
|
128
|
+
PASSWORD_ENV_VAR = "MYSQL_ROOT_PASSWORD"
|
|
133
129
|
CUSTOM_ENV = {"MYSQL_ROOT_HOST": "%"}
|
|
134
|
-
DATA_DIR =
|
|
135
|
-
ENGINE_MATCH =
|
|
136
|
-
USER =
|
|
137
|
-
DATABASE =
|
|
130
|
+
DATA_DIR = "/var/lib/mysql"
|
|
131
|
+
ENGINE_MATCH = "mysql"
|
|
132
|
+
USER = "root"
|
|
133
|
+
DATABASE = "mysql" # TODO: is this correct?
|
|
138
134
|
|
|
139
135
|
|
|
140
136
|
PROVIDERS = [
|
|
@@ -146,7 +142,7 @@ PROVIDERS = [
|
|
|
146
142
|
]
|
|
147
143
|
|
|
148
144
|
|
|
149
|
-
def fast_test_database(databases, test_commands=(
|
|
145
|
+
def fast_test_database(databases, test_commands=("test",), version=None):
|
|
150
146
|
"""
|
|
151
147
|
If running tests, start a database on a tmpfs and set it as the default
|
|
152
148
|
connection.
|
|
@@ -156,7 +152,7 @@ def fast_test_database(databases, test_commands=('test',), version=None):
|
|
|
156
152
|
# Not under test, leave connections alone
|
|
157
153
|
return databases
|
|
158
154
|
|
|
159
|
-
engine = databases[
|
|
155
|
+
engine = databases["default"]["ENGINE"]
|
|
160
156
|
|
|
161
157
|
match = None
|
|
162
158
|
for engine_match, provider in PROVIDERS:
|
|
@@ -168,10 +164,8 @@ def fast_test_database(databases, test_commands=('test',), version=None):
|
|
|
168
164
|
return databases
|
|
169
165
|
|
|
170
166
|
databases = copy(databases)
|
|
171
|
-
databases[
|
|
167
|
+
databases["default"] = match(version).provide(engine)
|
|
172
168
|
return databases
|
|
173
169
|
|
|
174
170
|
|
|
175
|
-
__all__ = (
|
|
176
|
-
'fast_test_database',
|
|
177
|
-
)
|
|
171
|
+
__all__ = ("fast_test_database",)
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "fast-test-database"
|
|
3
|
-
version = "
|
|
3
|
+
version = "0.2.0"
|
|
4
4
|
description = "Configure an in-memory database for running Django tests"
|
|
5
5
|
authors = ["Alexey Kotlyarov <a@koterpillar.com>"]
|
|
6
6
|
license = "GPL-3.0-or-later"
|
|
7
7
|
readme = "README.rst"
|
|
8
8
|
|
|
9
9
|
[tool.poetry.dependencies]
|
|
10
|
-
python = "^3.
|
|
11
|
-
Django = "^
|
|
10
|
+
python = "^3.11"
|
|
11
|
+
Django = "^5.0.0"
|
|
12
12
|
|
|
13
13
|
[tool.poetry.dev-dependencies]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
black = "^24.2.0"
|
|
15
|
+
isort = "^5.13.2"
|
|
16
|
+
mysqlclient = "^2.2.4"
|
|
17
|
+
psycopg2 = "^2.9.9"
|
|
18
|
+
pycodestyle = "^2.11.1"
|
|
17
19
|
|
|
18
20
|
[build-system]
|
|
19
21
|
requires = ["poetry-core>=1.0.0"]
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
from setuptools import setup
|
|
3
|
-
|
|
4
|
-
packages = \
|
|
5
|
-
['fast_test_database']
|
|
6
|
-
|
|
7
|
-
package_data = \
|
|
8
|
-
{'': ['*']}
|
|
9
|
-
|
|
10
|
-
install_requires = \
|
|
11
|
-
['Django>=3.0,<4.0']
|
|
12
|
-
|
|
13
|
-
setup_kwargs = {
|
|
14
|
-
'name': 'fast-test-database',
|
|
15
|
-
'version': '0.1.2',
|
|
16
|
-
'description': 'Configure an in-memory database for running Django tests',
|
|
17
|
-
'long_description': "Fast test database\n==================\n\nUse a pure in-memory database for running Django tests.\n\nUsage\n-----\n\nIn ``settings.py``:\n\n.. code:: python\n\n from fast_test_database import fast_test_database\n\n DATABASES = fast_test_database(DATABASES)\n\n # Or:\n DATABASES = fast_test_database(DATABASES,\n test_commands=('test', 'harvest'))\n\n # Or:\n DATABASES = fast_test_database(DATABASES,\n version='5.7')\n\nThis will be a no-op except for ``./manage.py test``, when an in-memory\ndatabase will be automatically started and supplied to the application.\n\nDetails\n-------\n\nThe in-memory database is a full PostgreSQL or MySQL instance started\nusing Docker, using tmpfs for storing the data. A single container will\nbe started if not yet running. It will not be shut down automatically,\nand instead reused for subsequent tests.\n\nThe type of the database (PostgreSQL or MySQL) is chosen based on the\nexisting default database engine.\n\nThe default version of the database (PostgreSQL or MySQL) is latest.\nBut it can be specified by version parameter.\n",
|
|
18
|
-
'author': 'Alexey Kotlyarov',
|
|
19
|
-
'author_email': 'a@koterpillar.com',
|
|
20
|
-
'maintainer': None,
|
|
21
|
-
'maintainer_email': None,
|
|
22
|
-
'url': None,
|
|
23
|
-
'packages': packages,
|
|
24
|
-
'package_data': package_data,
|
|
25
|
-
'install_requires': install_requires,
|
|
26
|
-
'python_requires': '>=3.7,<4.0',
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
setup(**setup_kwargs)
|
|
File without changes
|