Skip to content

Commit

Permalink
Fixes [unit] webserver 03 and [unit] settings-library (both mypy and …
Browse files Browse the repository at this point in the history
  • Loading branch information
pcrespov authored Nov 20, 2024
1 parent 66a492f commit c38b064
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 89 deletions.
38 changes: 38 additions & 0 deletions packages/common-library/src/common_library/basic_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from enum import StrEnum


class LogLevel(StrEnum):
DEBUG = "DEBUG"
INFO = "INFO"
WARNING = "WARNING"
ERROR = "ERROR"


class BootModeEnum(StrEnum):
"""
Values taken by SC_BOOT_MODE environment variable
set in Dockerfile and used during docker/boot.sh
"""

DEFAULT = "default"
LOCAL = "local-development"
DEBUG = "debug"
PRODUCTION = "production"
DEVELOPMENT = "development"

def is_devel_mode(self) -> bool:
"""returns True if this boot mode is used for development"""
return self in (self.DEBUG, self.DEVELOPMENT, self.LOCAL)


class BuildTargetEnum(StrEnum):
"""
Values taken by SC_BUILD_TARGET environment variable
set in Dockerfile that defines the stage targeted in the
docker image build
"""

BUILD = "build"
CACHE = "cache"
PRODUCTION = "production"
DEVELOPMENT = "development"
51 changes: 13 additions & 38 deletions packages/models-library/src/models_library/basic_types.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from decimal import Decimal
from enum import StrEnum
from enum import Enum
from re import Pattern
from typing import Annotated, ClassVar, Final, TypeAlias

from common_library.basic_types import BootModeEnum, BuildTargetEnum, LogLevel
from pydantic import Field, HttpUrl, PositiveInt, StringConstraints
from pydantic_core import core_schema

Expand All @@ -13,6 +14,17 @@
UUID_RE,
)

assert issubclass(LogLevel, Enum) # nosec
assert issubclass(BootModeEnum, Enum) # nosec
assert issubclass(BuildTargetEnum, Enum) # nosec

__all__: tuple[str, ...] = (
"LogLevel",
"BootModeEnum",
"BuildTargetEnum",
)


NonNegativeDecimal: TypeAlias = Annotated[Decimal, Field(ge=0)]

PositiveDecimal: TypeAlias = Annotated[Decimal, Field(gt=0)]
Expand Down Expand Up @@ -145,41 +157,4 @@ class HttpUrlWithCustomMinLength(HttpUrl):
min_length = 0


class LogLevel(StrEnum):
DEBUG = "DEBUG"
INFO = "INFO"
WARNING = "WARNING"
ERROR = "ERROR"


class BootModeEnum(StrEnum):
"""
Values taken by SC_BOOT_MODE environment variable
set in Dockerfile and used during docker/boot.sh
"""

DEFAULT = "default"
LOCAL = "local-development"
DEBUG = "debug"
PRODUCTION = "production"
DEVELOPMENT = "development"

def is_devel_mode(self) -> bool:
"""returns True if this boot mode is used for development"""
return self in (self.DEBUG, self.DEVELOPMENT, self.LOCAL)


class BuildTargetEnum(StrEnum):
"""
Values taken by SC_BUILD_TARGET environment variable
set in Dockerfile that defines the stage targeted in the
docker image build
"""

BUILD = "build"
CACHE = "cache"
PRODUCTION = "production"
DEVELOPMENT = "development"


KeyIDStr = Annotated[str, StringConstraints(pattern=PROPERTY_KEY_RE)]
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from models_library.basic_types import BootModeEnum
from pydantic import Field, PositiveInt

from .base import BaseCustomSettings
from .basic_types import BuildTargetEnum
from .basic_types import BootModeEnum, BuildTargetEnum


class BaseApplicationSettings(BaseCustomSettings):
Expand Down
4 changes: 2 additions & 2 deletions packages/settings-library/src/settings_library/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def _is_auto_default_from_env_enabled(field: FieldInfo) -> bool:
)


ENABLED: Final = {}
_MARKED_AS_UNSET: Final[dict] = {}


class EnvSettingsWithAutoDefaultSource(EnvSettingsSource):
Expand Down Expand Up @@ -89,7 +89,7 @@ def prepare_field_value(
_is_auto_default_from_env_enabled(field)
and field.default_factory
and field.default is None
and prepared_value == ENABLED
and prepared_value == _MARKED_AS_UNSET
):
prepared_value = field.default_factory()
return prepared_value
Expand Down
54 changes: 14 additions & 40 deletions packages/settings-library/src/settings_library/basic_types.py
Original file line number Diff line number Diff line change
@@ -1,57 +1,31 @@
#
# NOTE: This file copies some of the types from models_library.basic_types
# This is a minor evil to avoid the maintenance burden that creates
# an extra dependency to a larger models_library (intra-repo library)

from enum import StrEnum
from enum import Enum
from typing import Annotated, TypeAlias

from common_library.basic_types import BootModeEnum, BuildTargetEnum, LogLevel
from pydantic import Field, StringConstraints

assert issubclass(LogLevel, Enum) # nosec
assert issubclass(BootModeEnum, Enum) # nosec
assert issubclass(BuildTargetEnum, Enum) # nosec

__all__: tuple[str, ...] = (
"LogLevel",
"BootModeEnum",
"BuildTargetEnum",
)


# port number range
PortInt: TypeAlias = Annotated[int, Field(gt=0, lt=65535)]
RegisteredPortInt: TypeAlias = Annotated[int, Field(gt=1024, lt=65535)]


# e.g. 'v5'
VersionTag: TypeAlias = Annotated[str, StringConstraints(pattern=r"^v\d$")]


class LogLevel(StrEnum):
DEBUG = "DEBUG"
INFO = "INFO"
WARNING = "WARNING"
ERROR = "ERROR"


class BootMode(StrEnum):
"""
Values taken by SC_BOOT_MODE environment variable
set in Dockerfile and used during docker/boot.sh
"""

DEFAULT = "default"
LOCAL = "local-development"
DEBUG = "debug"
PRODUCTION = "production"
DEVELOPMENT = "development"


class BuildTargetEnum(StrEnum):
"""
Values taken by SC_BUILD_TARGET environment variable
set in Dockerfile that defines the stage targeted in the
docker image build
"""

BUILD = "build"
CACHE = "cache"
PRODUCTION = "production"
DEVELOPMENT = "development"


# non-empty bounded string used as identifier
# e.g. "123" or "name_123" or "fa327c73-52d8-462a-9267-84eeaf0f90e3" but NOT ""
IDStr: TypeAlias = Annotated[
str, StringConstraints(strip_whitespace=True, min_length=1, max_length=50)
]
RegisteredPortInt: TypeAlias = Annotated[int, Field(gt=1024, lt=65535)]
4 changes: 2 additions & 2 deletions packages/settings-library/tests/test_utils_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from pydantic import AliasChoices, Field, field_validator
from settings_library.base import BaseCustomSettings
from settings_library.basic_types import BootMode
from settings_library.basic_types import BootModeEnum
from settings_library.utils_logging import MixinLoggingSettings


Expand All @@ -14,7 +14,7 @@ def test_mixin_logging(monkeypatch):

class Settings(BaseCustomSettings, MixinLoggingSettings):
# DOCKER
SC_BOOT_MODE: BootMode | None = None
SC_BOOT_MODE: BootModeEnum | None = None

# LOGGING
LOG_LEVEL: str = Field(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,7 @@ async def test_list_service_usage(
assert mock_export_usage_services.called
args = mock_export_usage_services.call_args[1]

assert args["order_by"] == OrderBy.model_validate(_order_by)
assert (
args["order_by"].model_dump() == OrderBy.model_validate(_order_by).model_dump()
)
assert args["filters"] == ServiceResourceUsagesFilters.model_validate(_filter)
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ async def test_list_service_usage_with_order_by_query_param(
_, error = await assert_status(resp, status.HTTP_422_UNPROCESSABLE_ENTITY)
assert mock_list_usage_services.called
assert error["status"] == status.HTTP_422_UNPROCESSABLE_ENTITY
assert error["errors"][0]["message"].startswith("Invalid JSON")
assert "Invalid JSON" in error["errors"][0]["message"]

# with order by without direction
_filter = {"field": "started_at"}
Expand Down Expand Up @@ -249,7 +249,7 @@ async def test_list_service_usage_with_order_by_query_param(
errors = {(e["code"], e["field"]) for e in error["errors"]}
assert {
("value_error", "order_by.field"),
("type_error.enum", "order_by.direction"),
("enum", "order_by.direction"),
} == errors
assert len(errors) == 2

Expand All @@ -264,8 +264,8 @@ async def test_list_service_usage_with_order_by_query_param(
_, error = await assert_status(resp, status.HTTP_422_UNPROCESSABLE_ENTITY)
assert mock_list_usage_services.called
assert error["status"] == status.HTTP_422_UNPROCESSABLE_ENTITY
assert error["errors"][0]["message"].startswith("field required")
assert error["errors"][0]["code"] == "value_error.missing"
assert error["errors"][0]["message"].startswith("Field required")
assert error["errors"][0]["code"] == "missing"
assert error["errors"][0]["field"] == "order_by.field"


Expand Down

0 comments on commit c38b064

Please sign in to comment.