pytest-databases 0.5.0__tar.gz → 0.6.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.
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/.pre-commit-config.yaml +1 -1
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/Makefile +6 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/PKG-INFO +5 -2
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/README.md +1 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/pyproject.toml +15 -18
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/__init__.py +11 -2
- pytest_databases-0.6.0/src/pytest_databases/docker/azure_blob.py +187 -0
- pytest_databases-0.6.0/src/pytest_databases/docker/docker-compose.azurite.yml +9 -0
- pytest_databases-0.6.0/tests/docker/test_azure_blob.py +35 -0
- pytest_databases-0.5.0/requirements/requirements-dev.txt +0 -497
- pytest_databases-0.5.0/requirements/requirements-docs.txt +0 -405
- pytest_databases-0.5.0/requirements/requirements.txt +0 -13
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/.gitignore +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/.sourcery.yaml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/.vscode/launch.json +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/.vscode/settings.json +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/CODEOWNERS +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/CONTRIBUTING.rst +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/LICENSE +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/scripts/__init__.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/scripts/build_docs.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/scripts/convert_docs.sh +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/sonar-project.properties +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/__init__.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/__metadata__.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/alloydb_omni.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/bigquery.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/cockroachdb.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.alloydb-omni.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.bigquery.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.cockroachdb.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.dragonfly.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.elasticsearch.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.keydb.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.mariadb.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.mssql.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.mysql.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.oracle.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.postgres.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.redis.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/docker-compose.spanner.yml +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/dragonfly.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/elastic_search.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/keydb.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/mariadb.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/mssql.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/mysql.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/oracle.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/postgres.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/redis.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/docker/spanner.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/helpers.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/src/pytest_databases/py.typed +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/__init__.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/conftest.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/__init__.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_alloydb_omni.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_bigquery.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_cockroachdb.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_dragonfly.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_elasticsearch.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_keydb.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_mariadb.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_mssql.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_mysql.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_oracle.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_postgres.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_redis.py +0 -0
- {pytest_databases-0.5.0 → pytest_databases-0.6.0}/tests/docker/test_spanner.py +0 -0
|
@@ -19,7 +19,7 @@ repos:
|
|
|
19
19
|
|
|
20
20
|
# Ruff replaces black, flake8, autoflake and isort
|
|
21
21
|
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
|
22
|
-
rev: "v0.4.
|
|
22
|
+
rev: "v0.4.5" # make sure this is always consistent with hatch configs
|
|
23
23
|
hooks:
|
|
24
24
|
- id: ruff
|
|
25
25
|
args: [--config, ./pyproject.toml]
|
|
@@ -111,6 +111,12 @@ lint: ## Runs pre-commit hooks; includes ruff linting, codespell, bl
|
|
|
111
111
|
|
|
112
112
|
.PHONY: test
|
|
113
113
|
test: ## Run the tests
|
|
114
|
+
@echo "=> Running test cases"
|
|
115
|
+
@hatch run +py=3.12 test:cov
|
|
116
|
+
@echo "=> Tests complete"
|
|
117
|
+
|
|
118
|
+
.PHONY: test-all
|
|
119
|
+
test-all: ## Run the tests for all python versions
|
|
114
120
|
@echo "=> Running test cases"
|
|
115
121
|
@hatch run test:cov
|
|
116
122
|
@echo "=> Tests complete"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: pytest-databases
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Reusable database fixtures for any and all databases.
|
|
5
5
|
Project-URL: Documentation, https://github.com/litestar-org/pytest-databases#readme
|
|
6
6
|
Project-URL: Issues, https://github.com/litestar-org/pytest-databases/issues
|
|
@@ -20,6 +20,8 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
20
20
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
21
21
|
Requires-Python: >=3.8
|
|
22
22
|
Requires-Dist: pytest
|
|
23
|
+
Provides-Extra: azure-storage
|
|
24
|
+
Requires-Dist: azure-storage-blob; extra == 'azure-storage'
|
|
23
25
|
Provides-Extra: bigquery
|
|
24
26
|
Requires-Dist: google-cloud-bigquery; extra == 'bigquery'
|
|
25
27
|
Provides-Extra: cockroachdb
|
|
@@ -94,6 +96,7 @@ It is designed to offer pre-configured testing setups for many different types a
|
|
|
94
96
|
- **Dragonfly**: Latest server
|
|
95
97
|
- **KeyDB**: Latest server
|
|
96
98
|
- **Elasticsearch**: Version 7 and 8 are available
|
|
99
|
+
- **Azure blob storage**: Via azurite
|
|
97
100
|
|
|
98
101
|
## Contributing
|
|
99
102
|
|
|
@@ -44,6 +44,7 @@ It is designed to offer pre-configured testing setups for many different types a
|
|
|
44
44
|
- **Dragonfly**: Latest server
|
|
45
45
|
- **KeyDB**: Latest server
|
|
46
46
|
- **Elasticsearch**: Version 7 and 8 are available
|
|
47
|
+
- **Azure blob storage**: Via azurite
|
|
47
48
|
|
|
48
49
|
## Contributing
|
|
49
50
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[build-system]
|
|
2
2
|
build-backend = "hatchling.build"
|
|
3
|
-
requires = ["hatchling"
|
|
3
|
+
requires = ["hatchling"]
|
|
4
4
|
|
|
5
5
|
####################
|
|
6
6
|
# Project Metadata #
|
|
@@ -12,7 +12,7 @@ license = "MIT"
|
|
|
12
12
|
name = "pytest-databases"
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
requires-python = ">=3.8"
|
|
15
|
-
version = "0.
|
|
15
|
+
version = "0.6.0"
|
|
16
16
|
#
|
|
17
17
|
authors = [{ name = "Cody Fincher", email = "cody.fincher@gmail.com" }]
|
|
18
18
|
keywords = [
|
|
@@ -52,6 +52,7 @@ Issues = "https://github.com/litestar-org/pytest-databases/issues"
|
|
|
52
52
|
Source = "https://github.com/litestar-org/pytest-databases"
|
|
53
53
|
|
|
54
54
|
[project.optional-dependencies]
|
|
55
|
+
azure-storage = ["azure-storage-blob"]
|
|
55
56
|
bigquery = ["google-cloud-bigquery"]
|
|
56
57
|
cockroachdb = ["psycopg"]
|
|
57
58
|
dragonfly = ["redis"]
|
|
@@ -80,14 +81,8 @@ exclude = ["/.github", "/docs"]
|
|
|
80
81
|
|
|
81
82
|
# Default environment with production dependencies
|
|
82
83
|
[tool.hatch.envs.default]
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
pip-compile-hashes = false
|
|
86
|
-
pip-compile-installer = "uv"
|
|
87
|
-
pip-compile-resolver = "uv"
|
|
88
|
-
python = "3.11"
|
|
89
|
-
requires = ["hatch-pip-compile"]
|
|
90
|
-
type = "pip-compile"
|
|
84
|
+
installer = "uv"
|
|
85
|
+
python = "3.12"
|
|
91
86
|
|
|
92
87
|
[tool.hatch.envs.default.scripts]
|
|
93
88
|
upgrade-all = "PIP_COMPILE_UPGRADE=1 hatch env run --env {env_name} -- python --version"
|
|
@@ -119,6 +114,7 @@ features = [
|
|
|
119
114
|
"elasticsearch7",
|
|
120
115
|
"elasticsearch8",
|
|
121
116
|
"bigquery",
|
|
117
|
+
"azure-storage",
|
|
122
118
|
]
|
|
123
119
|
template = "default"
|
|
124
120
|
type = "virtual"
|
|
@@ -178,11 +174,9 @@ features = [
|
|
|
178
174
|
"elasticsearch8",
|
|
179
175
|
"bigquery",
|
|
180
176
|
]
|
|
181
|
-
lock-filename = "requirements/requirements-docs.txt"
|
|
182
|
-
pip-compile-constraint = "default"
|
|
183
177
|
python = "3.11"
|
|
184
|
-
template = "
|
|
185
|
-
type = "
|
|
178
|
+
template = "default"
|
|
179
|
+
type = "virtual"
|
|
186
180
|
|
|
187
181
|
[tool.hatch.envs.docs.env-vars]
|
|
188
182
|
PYTHONPATH = "."
|
|
@@ -250,12 +244,10 @@ features = [
|
|
|
250
244
|
"elasticsearch8",
|
|
251
245
|
"bigquery",
|
|
252
246
|
]
|
|
253
|
-
lock-filename = "requirements/requirements-dev.txt"
|
|
254
247
|
path = ".venv/"
|
|
255
|
-
pip-compile-constraint = "docs"
|
|
256
248
|
python = "3.11"
|
|
257
249
|
template = "docs"
|
|
258
|
-
type = "
|
|
250
|
+
type = "virtual"
|
|
259
251
|
|
|
260
252
|
|
|
261
253
|
# Lint environment
|
|
@@ -291,6 +283,7 @@ features = [
|
|
|
291
283
|
]
|
|
292
284
|
python = "3.11"
|
|
293
285
|
template = "docs"
|
|
286
|
+
type = "virtual"
|
|
294
287
|
|
|
295
288
|
[tool.hatch.envs.lint.scripts]
|
|
296
289
|
check = ["style", "typing"]
|
|
@@ -596,7 +589,11 @@ line-length = 120
|
|
|
596
589
|
|
|
597
590
|
[tool.pytest.ini_options]
|
|
598
591
|
addopts = "--dist loadfile -n 2 -ra -q --doctest-glob='*.md'"
|
|
599
|
-
filterwarnings = [
|
|
592
|
+
filterwarnings = [
|
|
593
|
+
"ignore::DeprecationWarning:pkg_resources",
|
|
594
|
+
"ignore::DeprecationWarning:xdist.*",
|
|
595
|
+
"ignore::DeprecationWarning:importlib._bootstrap",
|
|
596
|
+
]
|
|
600
597
|
markers = [
|
|
601
598
|
"mysql: MySQL Tests",
|
|
602
599
|
"postgres: Postgres Tests",
|
|
@@ -29,7 +29,7 @@ import re
|
|
|
29
29
|
import subprocess # noqa: S404
|
|
30
30
|
import sys
|
|
31
31
|
import timeit
|
|
32
|
-
from typing import TYPE_CHECKING, Any, Callable
|
|
32
|
+
from typing import TYPE_CHECKING, Any, Callable, Iterable
|
|
33
33
|
|
|
34
34
|
import pytest
|
|
35
35
|
|
|
@@ -72,7 +72,12 @@ COMPOSE_PROJECT_NAME: str = f"pytest-databases-{simple_string_hash(__file__)}"
|
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
class DockerServiceRegistry:
|
|
75
|
-
def __init__(
|
|
75
|
+
def __init__(
|
|
76
|
+
self,
|
|
77
|
+
worker_id: str,
|
|
78
|
+
compose_project_name: str = COMPOSE_PROJECT_NAME,
|
|
79
|
+
before_start: Iterable[Callable[[], Any]] | None = None,
|
|
80
|
+
) -> None:
|
|
76
81
|
self._running_services: set[str] = set()
|
|
77
82
|
self.docker_ip = self._get_docker_ip()
|
|
78
83
|
self._base_command = ["docker-compose"] if USE_LEGACY_DOCKER_COMPOSE else ["docker", "compose"]
|
|
@@ -82,6 +87,7 @@ class DockerServiceRegistry:
|
|
|
82
87
|
f"--project-name={compose_project_name}-{worker_id}",
|
|
83
88
|
],
|
|
84
89
|
)
|
|
90
|
+
self._before_start = list(before_start) if before_start else []
|
|
85
91
|
|
|
86
92
|
@staticmethod
|
|
87
93
|
def _get_docker_ip() -> str:
|
|
@@ -109,6 +115,9 @@ class DockerServiceRegistry:
|
|
|
109
115
|
pause: float = 0.1,
|
|
110
116
|
**kwargs: Any,
|
|
111
117
|
) -> None:
|
|
118
|
+
for before_start in self._before_start:
|
|
119
|
+
before_start()
|
|
120
|
+
|
|
112
121
|
if SKIP_DOCKER_COMPOSE:
|
|
113
122
|
self._running_services.add(name)
|
|
114
123
|
if name not in self._running_services:
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2024 Litestar
|
|
4
|
+
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import json
|
|
25
|
+
import os
|
|
26
|
+
import secrets
|
|
27
|
+
import subprocess # noqa: S404
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import AsyncGenerator, Generator
|
|
30
|
+
|
|
31
|
+
import pytest
|
|
32
|
+
from azure.storage.blob import ContainerClient
|
|
33
|
+
from azure.storage.blob.aio import ContainerClient as AsyncContainerClient
|
|
34
|
+
|
|
35
|
+
from pytest_databases.docker import DockerServiceRegistry
|
|
36
|
+
from pytest_databases.helpers import simple_string_hash
|
|
37
|
+
|
|
38
|
+
COMPOSE_PROJECT_NAME: str = f"pytest-databases-azure-blob-{simple_string_hash(__file__)}"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _get_container_ids(compose_file_name: str) -> list[str]:
|
|
42
|
+
proc = subprocess.run(
|
|
43
|
+
[ # noqa: S607
|
|
44
|
+
"docker",
|
|
45
|
+
"container",
|
|
46
|
+
"ls",
|
|
47
|
+
f"--filter=label=com.docker.compose.project.config_files={compose_file_name}",
|
|
48
|
+
"--format=json",
|
|
49
|
+
],
|
|
50
|
+
capture_output=True,
|
|
51
|
+
text=True,
|
|
52
|
+
check=True,
|
|
53
|
+
)
|
|
54
|
+
return [json.loads(line)["ID"] for line in proc.stdout.splitlines()]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _get_container_logs(compose_file_name: str) -> str:
|
|
58
|
+
logs = ""
|
|
59
|
+
for container_id in _get_container_ids(compose_file_name):
|
|
60
|
+
stdout = subprocess.run(
|
|
61
|
+
["docker", "logs", container_id], # noqa: S607
|
|
62
|
+
capture_output=True,
|
|
63
|
+
text=True,
|
|
64
|
+
check=True,
|
|
65
|
+
).stdout
|
|
66
|
+
logs += stdout
|
|
67
|
+
return logs
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@pytest.fixture(scope="session")
|
|
71
|
+
def azure_blob_compose_project_name() -> str:
|
|
72
|
+
return os.environ.get("COMPOSE_PROJECT_NAME", COMPOSE_PROJECT_NAME)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@pytest.fixture(scope="session")
|
|
76
|
+
def azure_blob_service_startup_delay() -> int:
|
|
77
|
+
return 1
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@pytest.fixture(scope="session")
|
|
81
|
+
def azure_blob_docker_services(
|
|
82
|
+
azure_blob_compose_project_name: str,
|
|
83
|
+
azure_blob_service_startup_delay: int,
|
|
84
|
+
worker_id: str = "main",
|
|
85
|
+
) -> Generator[DockerServiceRegistry, None, None]:
|
|
86
|
+
registry = DockerServiceRegistry(
|
|
87
|
+
worker_id,
|
|
88
|
+
compose_project_name=azure_blob_compose_project_name,
|
|
89
|
+
)
|
|
90
|
+
try:
|
|
91
|
+
yield registry
|
|
92
|
+
finally:
|
|
93
|
+
registry.down()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@pytest.fixture(scope="session")
|
|
97
|
+
def azure_blob_connection_string() -> str:
|
|
98
|
+
return "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@pytest.fixture(scope="session")
|
|
102
|
+
def azure_blob_account_name() -> str:
|
|
103
|
+
return "devstoreaccount1"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@pytest.fixture(scope="session")
|
|
107
|
+
def azure_blob_account_key() -> str:
|
|
108
|
+
return "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@pytest.fixture(scope="session")
|
|
112
|
+
def azure_blob_account_url() -> str:
|
|
113
|
+
return "http://127.0.0.1:10000/devstoreaccount1"
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@pytest.fixture(scope="session")
|
|
117
|
+
def azure_blob_port() -> int:
|
|
118
|
+
return 10000
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@pytest.fixture(scope="session")
|
|
122
|
+
def azure_blob_docker_compose_files() -> list[Path]:
|
|
123
|
+
return [Path(Path(__file__).parent / "docker-compose.azurite.yml")]
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@pytest.fixture(scope="session")
|
|
127
|
+
def default_azure_blob_redis_service_name() -> str:
|
|
128
|
+
return "azurite"
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@pytest.fixture(scope="session")
|
|
132
|
+
def azure_blob_docker_ip(azure_blob_docker_services: DockerServiceRegistry) -> str:
|
|
133
|
+
return azure_blob_docker_services.docker_ip
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@pytest.fixture(scope="session")
|
|
137
|
+
def azure_blob_default_container_name() -> str:
|
|
138
|
+
return secrets.token_hex(4)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@pytest.fixture(scope="session")
|
|
142
|
+
def azure_blob_container_client(
|
|
143
|
+
azure_blob_connection_string: str,
|
|
144
|
+
azure_blob_default_container_name: str,
|
|
145
|
+
azure_blob_service: None,
|
|
146
|
+
) -> Generator[ContainerClient, None, None]:
|
|
147
|
+
with ContainerClient.from_connection_string(
|
|
148
|
+
azure_blob_connection_string, container_name=azure_blob_default_container_name
|
|
149
|
+
) as container_client:
|
|
150
|
+
yield container_client
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@pytest.fixture(scope="session")
|
|
154
|
+
async def azure_blob_async_container_client(
|
|
155
|
+
azure_blob_connection_string: str, azure_blob_default_container_name: str
|
|
156
|
+
) -> AsyncGenerator[AsyncContainerClient, None]:
|
|
157
|
+
async with AsyncContainerClient.from_connection_string(
|
|
158
|
+
azure_blob_connection_string, container_name=azure_blob_default_container_name
|
|
159
|
+
) as container_client:
|
|
160
|
+
yield container_client
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@pytest.fixture(autouse=False, scope="session")
|
|
164
|
+
async def azure_blob_service(
|
|
165
|
+
azure_blob_docker_services: DockerServiceRegistry,
|
|
166
|
+
default_azure_blob_redis_service_name: str,
|
|
167
|
+
azure_blob_docker_compose_files: list[Path],
|
|
168
|
+
azure_blob_connection_string: str,
|
|
169
|
+
azure_blob_port: int,
|
|
170
|
+
azure_blob_default_container_name: str,
|
|
171
|
+
) -> AsyncGenerator[None, None]:
|
|
172
|
+
os.environ["AZURE_BLOB_PORT"] = str(azure_blob_port)
|
|
173
|
+
|
|
174
|
+
def azurite_responsive(host: str, port: int) -> bool:
|
|
175
|
+
# because azurite has a bug where it will hang for a long time if you make a
|
|
176
|
+
# request against it before it has completed startup we can't ping it, so we're
|
|
177
|
+
# inspecting the container logs instead
|
|
178
|
+
logs = _get_container_logs(str(azure_blob_docker_compose_files[0].absolute()))
|
|
179
|
+
return "Azurite Blob service successfully listens on" in logs
|
|
180
|
+
|
|
181
|
+
await azure_blob_docker_services.start(
|
|
182
|
+
name=default_azure_blob_redis_service_name,
|
|
183
|
+
docker_compose_files=azure_blob_docker_compose_files,
|
|
184
|
+
check=azurite_responsive,
|
|
185
|
+
port=azure_blob_port,
|
|
186
|
+
)
|
|
187
|
+
yield
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2024 Litestar
|
|
4
|
+
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
import pytest
|
|
24
|
+
from azure.storage.blob import ContainerClient
|
|
25
|
+
|
|
26
|
+
pytestmark = pytest.mark.anyio
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
pytest_plugins = [
|
|
30
|
+
"pytest_databases.docker.azure_blob",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
async def test_azure_blob_service(azure_blob_container_client: ContainerClient) -> None:
|
|
35
|
+
assert not azure_blob_container_client.exists()
|