pytest-databases 0.5.0__tar.gz → 0.7.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.
Files changed (84) hide show
  1. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/.pre-commit-config.yaml +1 -1
  2. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/Makefile +10 -9
  3. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/PKG-INFO +5 -2
  4. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/README.md +1 -0
  5. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/pyproject.toml +16 -25
  6. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/scripts/build_docs.py +0 -23
  7. pytest_databases-0.7.0/scripts/install-hatch.sh +56 -0
  8. pytest_databases-0.7.0/src/pytest_databases/__init__.py +3 -0
  9. pytest_databases-0.7.0/src/pytest_databases/__metadata__.py +16 -0
  10. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/__init__.py +11 -25
  11. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/alloydb_omni.py +22 -23
  12. pytest_databases-0.7.0/src/pytest_databases/docker/azure_blob.py +166 -0
  13. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/bigquery.py +12 -23
  14. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/cockroachdb.py +26 -27
  15. pytest_databases-0.7.0/src/pytest_databases/docker/docker-compose.azurite.yml +9 -0
  16. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.cockroachdb.yml +7 -3
  17. pytest_databases-0.7.0/src/pytest_databases/docker/docker-compose.valkey.yml +8 -0
  18. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/dragonfly.py +0 -23
  19. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/elastic_search.py +0 -23
  20. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/keydb.py +0 -23
  21. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/mariadb.py +39 -24
  22. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/mssql.py +40 -27
  23. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/mysql.py +77 -24
  24. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/oracle.py +57 -23
  25. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/postgres.py +134 -25
  26. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/redis.py +0 -23
  27. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/spanner.py +10 -23
  28. pytest_databases-0.7.0/src/pytest_databases/docker/valkey.py +85 -0
  29. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/helpers.py +0 -23
  30. pytest_databases-0.7.0/src/pytest_databases/py.typed +0 -0
  31. pytest_databases-0.7.0/tests/__init__.py +0 -0
  32. pytest_databases-0.7.0/tests/conftest.py +17 -0
  33. pytest_databases-0.7.0/tests/docker/__init__.py +0 -0
  34. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/tests/docker/test_alloydb_omni.py +10 -22
  35. pytest_databases-0.7.0/tests/docker/test_azure_blob.py +13 -0
  36. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/tests/docker/test_bigquery.py +7 -22
  37. pytest_databases-0.7.0/tests/docker/test_cockroachdb.py +46 -0
  38. pytest_databases-0.7.0/tests/docker/test_dragonfly.py +28 -0
  39. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/tests/docker/test_elasticsearch.py +0 -23
  40. pytest_databases-0.7.0/tests/docker/test_keydb.py +28 -0
  41. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/tests/docker/test_mariadb.py +21 -23
  42. pytest_databases-0.7.0/tests/docker/test_mssql.py +93 -0
  43. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/tests/docker/test_mysql.py +41 -23
  44. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/tests/docker/test_oracle.py +30 -23
  45. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/tests/docker/test_postgres.py +50 -22
  46. pytest_databases-0.7.0/tests/docker/test_redis.py +28 -0
  47. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/tests/docker/test_spanner.py +7 -22
  48. pytest_databases-0.7.0/tests/docker/test_valkey.py +28 -0
  49. pytest_databases-0.5.0/requirements/requirements-dev.txt +0 -497
  50. pytest_databases-0.5.0/requirements/requirements-docs.txt +0 -405
  51. pytest_databases-0.5.0/requirements/requirements.txt +0 -13
  52. pytest_databases-0.5.0/scripts/__init__.py +0 -21
  53. pytest_databases-0.5.0/src/pytest_databases/__init__.py +0 -21
  54. pytest_databases-0.5.0/src/pytest_databases/__metadata__.py +0 -39
  55. pytest_databases-0.5.0/tests/__init__.py +0 -21
  56. pytest_databases-0.5.0/tests/conftest.py +0 -40
  57. pytest_databases-0.5.0/tests/docker/__init__.py +0 -21
  58. pytest_databases-0.5.0/tests/docker/test_cockroachdb.py +0 -59
  59. pytest_databases-0.5.0/tests/docker/test_dragonfly.py +0 -51
  60. pytest_databases-0.5.0/tests/docker/test_keydb.py +0 -51
  61. pytest_databases-0.5.0/tests/docker/test_mssql.py +0 -112
  62. pytest_databases-0.5.0/tests/docker/test_redis.py +0 -51
  63. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/.gitignore +0 -0
  64. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/.sourcery.yaml +0 -0
  65. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/.vscode/launch.json +0 -0
  66. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/.vscode/settings.json +0 -0
  67. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/CODEOWNERS +0 -0
  68. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/CONTRIBUTING.rst +0 -0
  69. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/LICENSE +0 -0
  70. /pytest_databases-0.5.0/src/pytest_databases/py.typed → /pytest_databases-0.7.0/scripts/__init__.py +0 -0
  71. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/scripts/convert_docs.sh +0 -0
  72. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/sonar-project.properties +0 -0
  73. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.alloydb-omni.yml +0 -0
  74. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.bigquery.yml +0 -0
  75. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.dragonfly.yml +0 -0
  76. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.elasticsearch.yml +0 -0
  77. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.keydb.yml +0 -0
  78. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.mariadb.yml +0 -0
  79. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.mssql.yml +0 -0
  80. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.mysql.yml +0 -0
  81. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.oracle.yml +0 -0
  82. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.postgres.yml +0 -0
  83. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.redis.yml +0 -0
  84. {pytest_databases-0.5.0 → pytest_databases-0.7.0}/src/pytest_databases/docker/docker-compose.spanner.yml +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.0" # make sure this is always consistent with hatch configs
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]
@@ -20,25 +20,20 @@ help: ## Display this help
20
20
  # =============================================================================
21
21
  # Developer Utils
22
22
  # =============================================================================
23
- install-pipx: ## Install pipx
24
- @python3 -m pip install --upgrade --user pipx
25
-
26
- install-hatch: ## Install Hatch, UV, and Ruff
27
- @pipx install hatch --force
28
- @pipx inject hatch ruff uv hatch-pip-compile hatch-vcs hatch-mypyc mypy --include-deps --include-apps --force
23
+ install-hatch: ## Install Hatch
24
+ @sh ./scripts/install-hatch.sh
29
25
 
30
26
  configure-hatch: ## Configure Hatch defaults
31
27
  @hatch config set dirs.env.virtual .direnv
32
28
  @hatch config set dirs.env.pip-compile .direnv
33
29
 
34
30
  upgrade-hatch: ## Update Hatch, UV, and Ruff
35
- @pipx upgrade hatch --include-injected
31
+ @hatch self update
36
32
 
37
33
  install: ## Install the project and all dependencies
38
34
  @if [ "$(VENV_EXISTS)" ]; then echo "=> Removing existing virtual environment"; $(MAKE) destroy-venv; fi
39
35
  @$(MAKE) clean
40
- @if ! pipx --version > /dev/null; then echo '=> Installing `pipx`'; $(MAKE) install-pipx ; fi
41
- @if ! hatch --version > /dev/null; then echo '=> Installing `hatch` with `pipx`'; $(MAKE) install-hatch ; fi
36
+ @if ! hatch --version > /dev/null; then echo '=> Installing `hatch` with standalone installation'; $(MAKE) install-hatch ; fi
42
37
  @if ! hatch-pip-compile --version > /dev/null; then echo '=> Updating `hatch` and installing plugins'; $(MAKE) upgrade-hatch ; fi
43
38
  @echo "=> Creating Python environments..."
44
39
  @$(MAKE) configure-hatch
@@ -111,6 +106,12 @@ lint: ## Runs pre-commit hooks; includes ruff linting, codespell, bl
111
106
 
112
107
  .PHONY: test
113
108
  test: ## Run the tests
109
+ @echo "=> Running test cases"
110
+ @hatch run +py=3.12 test:cov
111
+ @echo "=> Tests complete"
112
+
113
+ .PHONY: test-all
114
+ test-all: ## Run the tests for all python versions
114
115
  @echo "=> Running test cases"
115
116
  @hatch run test:cov
116
117
  @echo "=> Tests complete"
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: pytest-databases
3
- Version: 0.5.0
3
+ Version: 0.7.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", "hatch-pip-compile"]
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.5.0"
15
+ version = "0.7.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,18 +81,9 @@ exclude = ["/.github", "/docs"]
80
81
 
81
82
  # Default environment with production dependencies
82
83
  [tool.hatch.envs.default]
83
- lock-filename = "requirements/requirements.txt"
84
- pip-compile-constraint = "default"
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
- [tool.hatch.envs.default.scripts]
93
- upgrade-all = "PIP_COMPILE_UPGRADE=1 hatch env run --env {env_name} -- python --version"
94
- upgrade-pkg = "PIP_COMPILE_UPGRADE='{args}' hatch env run --env {env_name} -- python --version"
95
87
 
96
88
  # Test environment with test-only dependencies
97
89
  [tool.hatch.envs.test]
@@ -119,6 +111,7 @@ features = [
119
111
  "elasticsearch7",
120
112
  "elasticsearch8",
121
113
  "bigquery",
114
+ "azure-storage",
122
115
  ]
123
116
  template = "default"
124
117
  type = "virtual"
@@ -178,11 +171,9 @@ features = [
178
171
  "elasticsearch8",
179
172
  "bigquery",
180
173
  ]
181
- lock-filename = "requirements/requirements-docs.txt"
182
- pip-compile-constraint = "default"
183
174
  python = "3.11"
184
- template = "test"
185
- type = "pip-compile"
175
+ template = "default"
176
+ type = "virtual"
186
177
 
187
178
  [tool.hatch.envs.docs.env-vars]
188
179
  PYTHONPATH = "."
@@ -250,12 +241,10 @@ features = [
250
241
  "elasticsearch8",
251
242
  "bigquery",
252
243
  ]
253
- lock-filename = "requirements/requirements-dev.txt"
254
244
  path = ".venv/"
255
- pip-compile-constraint = "docs"
256
245
  python = "3.11"
257
246
  template = "docs"
258
- type = "pip-compile"
247
+ type = "virtual"
259
248
 
260
249
 
261
250
  # Lint environment
@@ -291,6 +280,7 @@ features = [
291
280
  ]
292
281
  python = "3.11"
293
282
  template = "docs"
283
+ type = "virtual"
294
284
 
295
285
  [tool.hatch.envs.lint.scripts]
296
286
  check = ["style", "typing"]
@@ -524,6 +514,7 @@ lint.ignore = [
524
514
  "PERF203", # ignore for now; investigate
525
515
  "COM812",
526
516
  "PLR0917",
517
+ "CPY001", # copywrite check
527
518
  ]
528
519
  lint.select = ["ALL"]
529
520
  # Allow unused variables when underscore-prefixed.
@@ -563,10 +554,6 @@ ban-relative-imports = "all"
563
554
  "FA102",
564
555
  ]
565
556
 
566
- # copyright
567
- # Enable once this is released: https://github.com/astral-sh/ruff/issues/10021
568
- # Ruff v0.3.4 has not included this release yet
569
- # "**/*.py" = ["CPY001"]
570
557
 
571
558
  [tool.ruff.lint.mccabe]
572
559
  max-complexity = 12
@@ -596,7 +583,11 @@ line-length = 120
596
583
 
597
584
  [tool.pytest.ini_options]
598
585
  addopts = "--dist loadfile -n 2 -ra -q --doctest-glob='*.md'"
599
- filterwarnings = ["ignore::DeprecationWarning:pkg_resources", "ignore::DeprecationWarning:xdist.*"]
586
+ filterwarnings = [
587
+ "ignore::DeprecationWarning:pkg_resources",
588
+ "ignore::DeprecationWarning:xdist.*",
589
+ "ignore::DeprecationWarning:importlib._bootstrap",
590
+ ]
600
591
  markers = [
601
592
  "mysql: MySQL Tests",
602
593
  "postgres: Postgres Tests",
@@ -1,26 +1,3 @@
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
-
24
1
  from __future__ import annotations
25
2
 
26
3
  import argparse
@@ -0,0 +1,56 @@
1
+ #!/bin/bash
2
+
3
+ # --- Constants ---
4
+ BASE_URL="https://github.com/pypa/hatch/releases/latest/download"
5
+ EXTRACT_CMD="tar -xzf"
6
+
7
+ # --- Handle Optional Installation Directory ---
8
+ INSTALL_DIR="$1" # Default: current directory
9
+ if [[ -n "$INSTALL_DIR" ]]; then
10
+ if [[ ! -d "$INSTALL_DIR" ]]; then # Check if directory exists
11
+ INSTALL_DIR="$HOME/.local/bin"
12
+ echo "Error: Invalid install directory '$INSTALL_DIR'"
13
+ exit 1
14
+ fi
15
+ INSTALL_DIR=$(realpath "$INSTALL_DIR") # Get absolute path
16
+ fi
17
+
18
+ # --- Determine Platform ---
19
+ PLATFORM=$(uname -s)
20
+ MACHINE=$(uname -m)
21
+ FILE_EXT="tar.gz"
22
+
23
+ if [[ $PLATFORM == "Darwin" ]]; then
24
+ PLATFORM_NAME="apple-darwin"
25
+ elif [[ $PLATFORM == "Linux" ]]; then
26
+ PLATFORM_NAME="unknown-linux-gnu"
27
+ if [[ $MACHINE == "aarch64" ]]; then
28
+ MACHINE="aarch64"
29
+ fi
30
+ elif [[ $PLATFORM == "Windows" ]]; then
31
+ PLATFORM_NAME="pc-windows-msvc"
32
+ FILE_EXT="zip"
33
+ EXTRACT_CMD="unzip"
34
+ else
35
+ echo "Unsupported platform: $PLATFORM"
36
+ exit 1
37
+ fi
38
+
39
+ # --- Construct File Name and URL ---
40
+ FILENAME="hatch-$MACHINE-$PLATFORM_NAME.$FILE_EXT"
41
+ URL="$BASE_URL/$FILENAME"
42
+
43
+ # --- Download and Extract ---
44
+ echo "Downloading Hatch binary: $FILENAME"
45
+ curl -L -o "$FILENAME" "$URL"
46
+
47
+ echo "Extracting to '$INSTALL_DIR'..."
48
+ $EXTRACT_CMD "$FILENAME" -C "$INSTALL_DIR" # Extract to install directory
49
+ rm "$FILENAME" # Remove archive
50
+
51
+ HATCH_BINARY="$INSTALL_DIR/hatch" # Path to the extracted binary
52
+ if [[ -x "$HATCH_BINARY" ]]; then
53
+ echo "Hatch binary successfully installed at '$HATCH_BINARY'"
54
+ else
55
+ echo "Error: Hatch binary not found or not executable."
56
+ fi
@@ -0,0 +1,3 @@
1
+ # SPDX-FileCopyrightText: 2024-present Litestar <hello@litestar.dev>
2
+ #
3
+ # SPDX-License-Identifier: MIT
@@ -0,0 +1,16 @@
1
+ from __future__ import annotations
2
+
3
+ from importlib.metadata import PackageNotFoundError, metadata, version
4
+
5
+ __all__ = ("__project__", "__version__")
6
+
7
+ try:
8
+ __version__ = version("pytest-databases")
9
+ """Version of the project."""
10
+ __project__ = metadata("pytest-databases")["Name"]
11
+ """Name of the project."""
12
+ except PackageNotFoundError: # pragma: no cover
13
+ __version__ = "0.0.0"
14
+ __project__ = "pytest-databases"
15
+ finally:
16
+ del version, PackageNotFoundError, metadata
@@ -1,26 +1,3 @@
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
-
24
1
  from __future__ import annotations
25
2
 
26
3
  import asyncio
@@ -29,7 +6,7 @@ import re
29
6
  import subprocess # noqa: S404
30
7
  import sys
31
8
  import timeit
32
- from typing import TYPE_CHECKING, Any, Callable
9
+ from typing import TYPE_CHECKING, Any, Callable, Iterable
33
10
 
34
11
  import pytest
35
12
 
@@ -72,7 +49,12 @@ COMPOSE_PROJECT_NAME: str = f"pytest-databases-{simple_string_hash(__file__)}"
72
49
 
73
50
 
74
51
  class DockerServiceRegistry:
75
- def __init__(self, worker_id: str, compose_project_name: str = COMPOSE_PROJECT_NAME) -> None:
52
+ def __init__(
53
+ self,
54
+ worker_id: str,
55
+ compose_project_name: str = COMPOSE_PROJECT_NAME,
56
+ before_start: Iterable[Callable[[], Any]] | None = None,
57
+ ) -> None:
76
58
  self._running_services: set[str] = set()
77
59
  self.docker_ip = self._get_docker_ip()
78
60
  self._base_command = ["docker-compose"] if USE_LEGACY_DOCKER_COMPOSE else ["docker", "compose"]
@@ -82,6 +64,7 @@ class DockerServiceRegistry:
82
64
  f"--project-name={compose_project_name}-{worker_id}",
83
65
  ],
84
66
  )
67
+ self._before_start = list(before_start) if before_start else []
85
68
 
86
69
  @staticmethod
87
70
  def _get_docker_ip() -> str:
@@ -109,6 +92,9 @@ class DockerServiceRegistry:
109
92
  pause: float = 0.1,
110
93
  **kwargs: Any,
111
94
  ) -> None:
95
+ for before_start in self._before_start:
96
+ before_start()
97
+
112
98
  if SKIP_DOCKER_COMPOSE:
113
99
  self._running_services.add(name)
114
100
  if name not in self._running_services:
@@ -1,26 +1,3 @@
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
-
24
1
  from __future__ import annotations
25
2
 
26
3
  import os
@@ -141,3 +118,25 @@ async def alloydb_omni_service(
141
118
  password=postgres_password,
142
119
  )
143
120
  yield
121
+
122
+
123
+ @pytest.fixture(autouse=False, scope="session")
124
+ async def alloydb_omni_startup_connection(
125
+ alloydb_omni_service: DockerServiceRegistry,
126
+ alloydb_docker_ip: str,
127
+ alloydb_omni_port: int,
128
+ postgres_database: str,
129
+ postgres_user: str,
130
+ postgres_password: str,
131
+ ) -> AsyncGenerator[asyncpg.Connection[asyncpg.Record], None]:
132
+ conn = await asyncpg.connect(
133
+ host=alloydb_docker_ip,
134
+ port=alloydb_omni_port,
135
+ user=postgres_user,
136
+ database=postgres_database,
137
+ password=postgres_password,
138
+ )
139
+ try:
140
+ yield conn
141
+ finally:
142
+ await conn.close()
@@ -0,0 +1,166 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ import secrets
6
+ import subprocess # noqa: S404
7
+ from pathlib import Path
8
+ from typing import AsyncGenerator, Generator
9
+
10
+ import pytest
11
+ from azure.storage.blob import ContainerClient
12
+ from azure.storage.blob.aio import ContainerClient as AsyncContainerClient
13
+
14
+ from pytest_databases.docker import DockerServiceRegistry
15
+ from pytest_databases.helpers import simple_string_hash
16
+
17
+ COMPOSE_PROJECT_NAME: str = f"pytest-databases-azure-blob-{simple_string_hash(__file__)}"
18
+
19
+
20
+ def _get_container_ids(compose_file_name: str) -> list[str]:
21
+ proc = subprocess.run(
22
+ [ # noqa: S607
23
+ "docker",
24
+ "container",
25
+ "ls",
26
+ f"--filter=label=com.docker.compose.project.config_files={compose_file_name}",
27
+ "--format=json",
28
+ ],
29
+ capture_output=True,
30
+ text=True,
31
+ check=True,
32
+ )
33
+ return [json.loads(line)["ID"] for line in proc.stdout.splitlines()]
34
+
35
+
36
+ def _get_container_logs(compose_file_name: str) -> str:
37
+ logs = ""
38
+ for container_id in _get_container_ids(compose_file_name):
39
+ stdout = subprocess.run(
40
+ ["docker", "logs", container_id], # noqa: S607
41
+ capture_output=True,
42
+ text=True,
43
+ check=True,
44
+ ).stdout
45
+ logs += stdout
46
+ return logs
47
+
48
+
49
+ @pytest.fixture(scope="session")
50
+ def azure_blob_compose_project_name() -> str:
51
+ return os.environ.get("COMPOSE_PROJECT_NAME", COMPOSE_PROJECT_NAME)
52
+
53
+
54
+ @pytest.fixture(scope="session")
55
+ def azure_blob_service_startup_delay() -> int:
56
+ return 1
57
+
58
+
59
+ @pytest.fixture(scope="session")
60
+ def azure_blob_docker_services(
61
+ azure_blob_compose_project_name: str,
62
+ azure_blob_service_startup_delay: int,
63
+ worker_id: str = "main",
64
+ ) -> Generator[DockerServiceRegistry, None, None]:
65
+ registry = DockerServiceRegistry(
66
+ worker_id,
67
+ compose_project_name=azure_blob_compose_project_name,
68
+ )
69
+ try:
70
+ yield registry
71
+ finally:
72
+ registry.down()
73
+
74
+
75
+ @pytest.fixture(scope="session")
76
+ def azure_blob_connection_string() -> str:
77
+ return "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"
78
+
79
+
80
+ @pytest.fixture(scope="session")
81
+ def azure_blob_account_name() -> str:
82
+ return "devstoreaccount1"
83
+
84
+
85
+ @pytest.fixture(scope="session")
86
+ def azure_blob_account_key() -> str:
87
+ return "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
88
+
89
+
90
+ @pytest.fixture(scope="session")
91
+ def azure_blob_account_url() -> str:
92
+ return "http://127.0.0.1:10000/devstoreaccount1"
93
+
94
+
95
+ @pytest.fixture(scope="session")
96
+ def azure_blob_port() -> int:
97
+ return 10000
98
+
99
+
100
+ @pytest.fixture(scope="session")
101
+ def azure_blob_docker_compose_files() -> list[Path]:
102
+ return [Path(Path(__file__).parent / "docker-compose.azurite.yml")]
103
+
104
+
105
+ @pytest.fixture(scope="session")
106
+ def default_azure_blob_redis_service_name() -> str:
107
+ return "azurite"
108
+
109
+
110
+ @pytest.fixture(scope="session")
111
+ def azure_blob_docker_ip(azure_blob_docker_services: DockerServiceRegistry) -> str:
112
+ return azure_blob_docker_services.docker_ip
113
+
114
+
115
+ @pytest.fixture(scope="session")
116
+ def azure_blob_default_container_name() -> str:
117
+ return secrets.token_hex(4)
118
+
119
+
120
+ @pytest.fixture(scope="session")
121
+ def azure_blob_container_client(
122
+ azure_blob_connection_string: str,
123
+ azure_blob_default_container_name: str,
124
+ azure_blob_service: None,
125
+ ) -> Generator[ContainerClient, None, None]:
126
+ with ContainerClient.from_connection_string(
127
+ azure_blob_connection_string, container_name=azure_blob_default_container_name
128
+ ) as container_client:
129
+ yield container_client
130
+
131
+
132
+ @pytest.fixture(scope="session")
133
+ async def azure_blob_async_container_client(
134
+ azure_blob_connection_string: str, azure_blob_default_container_name: str
135
+ ) -> AsyncGenerator[AsyncContainerClient, None]:
136
+ async with AsyncContainerClient.from_connection_string(
137
+ azure_blob_connection_string, container_name=azure_blob_default_container_name
138
+ ) as container_client:
139
+ yield container_client
140
+
141
+
142
+ @pytest.fixture(autouse=False, scope="session")
143
+ async def azure_blob_service(
144
+ azure_blob_docker_services: DockerServiceRegistry,
145
+ default_azure_blob_redis_service_name: str,
146
+ azure_blob_docker_compose_files: list[Path],
147
+ azure_blob_connection_string: str,
148
+ azure_blob_port: int,
149
+ azure_blob_default_container_name: str,
150
+ ) -> AsyncGenerator[None, None]:
151
+ os.environ["AZURE_BLOB_PORT"] = str(azure_blob_port)
152
+
153
+ def azurite_responsive(host: str, port: int) -> bool:
154
+ # because azurite has a bug where it will hang for a long time if you make a
155
+ # request against it before it has completed startup we can't ping it, so we're
156
+ # inspecting the container logs instead
157
+ logs = _get_container_logs(str(azure_blob_docker_compose_files[0].absolute()))
158
+ return "Azurite Blob service successfully listens on" in logs
159
+
160
+ await azure_blob_docker_services.start(
161
+ name=default_azure_blob_redis_service_name,
162
+ docker_compose_files=azure_blob_docker_compose_files,
163
+ check=azurite_responsive,
164
+ port=azure_blob_port,
165
+ )
166
+ yield
@@ -1,26 +1,3 @@
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
-
24
1
  from __future__ import annotations
25
2
 
26
3
  import os
@@ -163,3 +140,15 @@ async def bigquery_service(
163
140
  bigquery_client_options=bigquery_client_options,
164
141
  )
165
142
  yield
143
+
144
+
145
+ @pytest.fixture(autouse=False, scope="session")
146
+ async def bigquery_startup_connection(
147
+ bigquery_service: DockerServiceRegistry,
148
+ bigquery_project: str,
149
+ bigquery_credentials: Credentials,
150
+ bigquery_client_options: ClientOptions,
151
+ ) -> AsyncGenerator[bigquery.Client, None]:
152
+ yield bigquery.Client(
153
+ project=bigquery_project, client_options=bigquery_client_options, credentials=bigquery_credentials
154
+ )