Skip to content

Commit

Permalink
feat: Ensure all fixture types are automatically included in the CLI. (
Browse files Browse the repository at this point in the history
  • Loading branch information
DanCardin committed May 3, 2023
1 parent b4ae4e7 commit df55dde
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 51 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pytest-mock-resources"
version = "2.6.11"
version = "2.6.12"
description = "A pytest plugin for easily instantiating reproducible mock resources."
authors = [
"Omar Khan <oakhan3@gmail.com>",
Expand Down
2 changes: 2 additions & 0 deletions src/pytest_mock_resources/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from pytest_mock_resources.container import (
get_container,
MongoConfig,
MotoConfig,
MysqlConfig,
PostgresConfig,
RedisConfig,
Expand Down Expand Up @@ -40,6 +41,7 @@
__all__ = [
"Credentials",
"MongoConfig",
"MotoConfig",
"MysqlConfig",
"PostgresConfig",
"RedisConfig",
Expand Down
67 changes: 20 additions & 47 deletions src/pytest_mock_resources/cli.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
from __future__ import annotations

import argparse
import enum
from typing import Dict, Type

from pytest_mock_resources import (
MongoConfig,
MysqlConfig,
PostgresConfig,
RedisConfig,
RedshiftConfig,
)

from pytest_mock_resources.config import DockerContainerConfig
from pytest_mock_resources.container.base import container_name, get_container

postgres_image = PostgresConfig().image
mysql_image = MysqlConfig().image
mongo_image = MongoConfig().image


class StubPytestConfig:
pmr_multiprocess_safe = False
Expand All @@ -29,28 +18,6 @@ def getini(self, attr):
return getattr(self, attr)


@enum.unique
class FixtureType(enum.Enum):
mongo = "mongo"
mysql = "mysql"
postgres = "postgres"
redis = "redis"
redshift = "redshift"

@classmethod
def options(cls):
return ", ".join(fixture_base.value for fixture_base in cls)


_container_producers: Dict[FixtureType, Type[DockerContainerConfig]] = {
FixtureType.mongo: MongoConfig,
FixtureType.mysql: MysqlConfig,
FixtureType.postgres: PostgresConfig,
FixtureType.redis: RedisConfig,
FixtureType.redshift: RedshiftConfig,
}


def main():
parser = create_parser()
args = parser.parse_args()
Expand All @@ -60,31 +27,36 @@ def main():
stop = args.stop
start = not stop

for fixture_base in args.fixture_bases:
fixture_type = FixtureType(fixture_base)
execute(fixture_type, pytestconfig, start=start, stop=stop)
for fixture in args.fixtures:
if fixture not in DockerContainerConfig.subclasses:
valid_options = ", ".join(DockerContainerConfig.subclasses)
raise argparse.ArgumentError(
args.fixtures,
f"'{fixture}' invalid. Valid options include: {valid_options}",
)

execute(fixture, pytestconfig, start=start, stop=stop)


def create_parser():
# TODO: Add an options arg to DOWN a fixture_base's container
parser = argparse.ArgumentParser(
description="Premptively run docker containers to speed up initial startup of PMR Fixtures."
)
parser.add_argument(
"fixture_bases",
metavar="Fixture Base",
"fixtures",
metavar="Fixture",
type=str,
nargs="+",
help="Available Fixture Bases: {}".format(FixtureType.options()),
help="Available Fixtures: {}".format(", ".join(DockerContainerConfig.subclasses)),
)
parser.add_argument(
"--stop", action="store_true", help="Stop previously started PMR containers"
)
return parser


def execute(fixture_type: FixtureType, pytestconfig: StubPytestConfig, start=True, stop=False):
config_cls = _container_producers[fixture_type]
def execute(fixture: str, pytestconfig: StubPytestConfig, start=True, stop=False):
config_cls = DockerContainerConfig.subclasses[fixture]
config = config_cls()

if start:
Expand All @@ -95,11 +67,12 @@ def execute(fixture_type: FixtureType, pytestconfig: StubPytestConfig, start=Tru
if stop:
from python_on_whales import docker

name = container_name(fixture_type.value, config.port)
assert config.port
name = container_name(fixture, int(config.port))
try:
container = docker.container.inspect(name)
except Exception:
print(f"Failed to stop {fixture_type.value} container")
print(f"Failed to stop {fixture} container")
else:
container.kill()

Expand Down
12 changes: 11 additions & 1 deletion src/pytest_mock_resources/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations

import functools
import os
import socket
from typing import Dict, Iterable
from typing import ClassVar, Dict, Iterable, Type

_DOCKER_HOST = "host.docker.internal"

Expand Down Expand Up @@ -49,9 +51,17 @@ def wrapper(self):


class DockerContainerConfig:
name: ClassVar[str]

_fields: Iterable = {"image", "host", "port", "ci_port", "container_args"}
_fields_defaults: Dict = {}

subclasses: Dict[str, Type[DockerContainerConfig]] = {}

@classmethod
def __init_subclass__(cls):
DockerContainerConfig.subclasses[cls.name] = cls

def __init__(self, **kwargs):
for field, value in kwargs.items():
if field not in self._fields:
Expand Down
13 changes: 12 additions & 1 deletion src/pytest_mock_resources/container/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
# flake8: noqa
from pytest_mock_resources.container.base import get_container
from pytest_mock_resources.container.mongo import MongoConfig
from pytest_mock_resources.container.moto import MotoConfig
from pytest_mock_resources.container.mysql import MysqlConfig
from pytest_mock_resources.container.postgres import PostgresConfig
from pytest_mock_resources.container.redis import RedisConfig
from pytest_mock_resources.container.redshift import RedshiftConfig

__all__ = [
"get_container",
"MongoConfig",
"MysqlConfig",
"PostgresConfig",
"PostgresConfig",
"RedisConfig",
"RedshiftConfig",
"MotoConfig",
]
3 changes: 2 additions & 1 deletion src/pytest_mock_resources/container/moto.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class MotoConfig(DockerContainerConfig):
Defaults to :code:`5432`.
"""

name = "postgres"
name = "moto"

_fields = {"image", "host", "port"}
_fields_defaults = {
"image": "motoserver/moto:4.0.6",
Expand Down

0 comments on commit df55dde

Please sign in to comment.