Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ source-roots=

# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode=yes
# suggestion-mode=yes # Deprecated option, removed

# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
Expand Down
2 changes: 1 addition & 1 deletion examples/b_end_2_end/requirements-dev.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
-r requirements.txt
python-dotenv
servey[server,serverless,web_page]~=2.6
servey[server,serverless,web_page]
2 changes: 1 addition & 1 deletion examples/b_end_2_end/requirements.in
Original file line number Diff line number Diff line change
@@ -1 +1 @@
servey~=2.6
servey
4 changes: 2 additions & 2 deletions examples/b_end_2_end/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#
# This file is autogenerated by pip-compile with Python 3.9
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --generate-hashes --no-emit-index-url --no-reuse-hashes requirements.in
# pip-compile --generate-hashes --no-emit-index-url requirements.in
#
attrs==22.2.0 \
--hash=sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836 \
Expand Down
93 changes: 93 additions & 0 deletions injecty_config_servey/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def configure(context: InjectyContext):
)

context.register_impl(MarshallerABC, ToSecondDatetimeMarshaller)
configure_schemey(context)
configure_finders(context)
configure_asyncio_invoker(context)
configure_auth(context)
Expand All @@ -30,6 +31,98 @@ def configure(context: InjectyContext):
configure_jinja2(context)


def configure_schemey(context: InjectyContext):
"""Configure schemey schema factories for dependency injection."""
_configure_schema_factories(context)
_configure_schema_validators(context)


def _configure_schema_factories(context: InjectyContext):
"""Configure schema factory implementations."""
from schemey.factory.schema_factory_abc import SchemaFactoryABC
from schemey.factory.simple_type_factory import SimpleTypeFactory

# Get all factory classes
simple_type_factories = _create_simple_type_factories(SimpleTypeFactory)
imported_factories = _import_schema_factories()
factory_classes = simple_type_factories + imported_factories

for factory_class in factory_classes:
context.register_impl(SchemaFactoryABC, factory_class)


def _import_schema_factories():
"""Import and return all schema factory classes."""
from schemey.factory.dataclass_schema_factory import DataclassSchemaFactory
from schemey.factory.enum_schema_factory import EnumSchemaFactory
from schemey.factory.array_schema_factory import ArraySchemaFactory
from schemey.factory.tuple_schema_factory import TupleSchemaFactory
from schemey.factory.datetime_factory import DatetimeFactory
from schemey.factory.uuid_factory import UuidFactory
from schemey.factory.external_type_factory import ExternalTypeFactory
from schemey.factory.any_of_schema_factory import AnyOfSchemaFactory
from schemey.factory.ref_schema_factory import RefSchemaFactory
from schemey.factory.impl_schema_factory import ImplSchemaFactory
from schemey.factory.factory_schema_factory import FactorySchemaFactory

return [
ExternalTypeFactory,
ArraySchemaFactory,
TupleSchemaFactory,
DataclassSchemaFactory,
EnumSchemaFactory,
DatetimeFactory,
UuidFactory,
AnyOfSchemaFactory,
RefSchemaFactory,
ImplSchemaFactory,
FactorySchemaFactory,
]


def _create_simple_type_factories(SimpleTypeFactory):
"""Create custom factory classes for simple types."""

class StrSchemaFactory(SimpleTypeFactory):
def __init__(self):
super().__init__(str, "string")

class IntSchemaFactory(SimpleTypeFactory):
def __init__(self):
super().__init__(int, "integer")

class FloatSchemaFactory(SimpleTypeFactory):
def __init__(self):
super().__init__(float, "number")

class BoolSchemaFactory(SimpleTypeFactory):
def __init__(self):
super().__init__(bool, "boolean")

class NoneSchemaFactory(SimpleTypeFactory):
def __init__(self):
super().__init__(type(None), "null")

return [
StrSchemaFactory,
IntSchemaFactory,
FloatSchemaFactory,
BoolSchemaFactory,
NoneSchemaFactory,
]


def _configure_schema_validators(context: InjectyContext):
"""Configure schema validator implementations."""
from schemey.json_schema.schema_validator_abc import SchemaValidatorABC
from schemey.json_schema.ranges_validator import RangesValidator
from schemey.json_schema.timestamp_validator import TimestampValidator

validator_classes = [RangesValidator, TimestampValidator]
for validator_class in validator_classes:
context.register_impl(SchemaValidatorABC, validator_class)


def configure_finders(context: InjectyContext):
from servey.finder.action_finder_abc import ActionFinderABC
from servey.finder.module_action_finder import ModuleActionFinder
Expand Down
68 changes: 34 additions & 34 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,63 +14,62 @@ classifiers = [
"Operating System :: OS Independent",
]
dependencies = [
"cryptography~=37.0",
"cryptography~=46.0",
"injecty~=0.0",
"json-urley~=1.0",
"marshy~=5.0",
"pyjwt~=2.4",
"python-dateutil~=2.8",
"schemey~=7.0",
"marshy~=6.0",
"pyjwt~=2.10",
"python-dateutil~=2.9",
"schemey~=8.0",
]

[project.urls]
Repository = "https://github.com/tofarr/servey"

[project.optional-dependencies]
dev = [
"black~=23.3",
"boto3~=1.26",
"pytest~=7.2",
"pytest-cov~=4.0",
"pytest-xdist~=3.2",
"pylint~=3.0",
"black~=25.11",
"boto3~=1.42",
"pytest~=9.0",
"pytest-cov~=7.0",
"pytest-xdist~=3.8",
"pylint~=4.0",
]
server = [
"starlette~=0.19",
"strawberry-graphql~=0.151",
"uvicorn[standard]~=0.18",
"pygments~=2.13",
"requests~=2.28",
"starlette~=0.50",
"strawberry-graphql~=0.287",
"uvicorn[standard]~=0.38",
"pygments~=2.19",
"requests~=2.32",
"python-multipart~=0.0",
]
scheduler = [
"celery~=5.2",
"celery~=5.6",
]
serverless = [
"pyyaml~=6.0",
"ruamel.yaml~=0.17",
"strawberry-graphql~=0.177",
"ruamel.yaml~=0.18",
"strawberry-graphql~=0.287",
]
web_page = [
"Jinja2~=3.1",
]
all = [
"black~=23.3",
"boto3~=1.26",
"pytest~=7.2",
"pytest-cov~=4.0",
"pytest-xdist~=3.2",
"pylint~=3.0",
"starlette~=0.19",
"strawberry-graphql~=0.151",
"uvicorn[standard]~=0.18",
"pygments~=2.13",
"requests~=2.28",
"black~=25.11",
"boto3~=1.42",
"pytest~=9.0",
"pytest-cov~=7.0",
"pytest-xdist~=3.8",
"pylint~=4.0",
"starlette~=0.50",
"strawberry-graphql~=0.287",
"uvicorn[standard]~=0.38",
"pygments~=2.19",
"requests~=2.32",
"python-multipart~=0.0",
"celery~=5.2",
"celery~=5.6",
"pyyaml~=6.0",
"ruamel.yaml~=0.17",
"strawberry-graphql~=0.177",
"ruamel.yaml~=0.18",
"Jinja2~=3.1",
]

Expand All @@ -95,6 +94,7 @@ extend-exclude = "_version.py"

[dependency-groups]
dev = [
"black>=25.11.0",
"hatch-vcs>=0.5.0",
"hatchling>=1.28.0",
]
]
Binary file added schemey-8.0.0-py3-none-any.whl
Binary file not shown.
6 changes: 3 additions & 3 deletions servey/servey_strawberry/entity_factory/enum_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ def create_type(
strawberry_enum = schema_factory.enums.get(annotation.__name__)
if not strawberry_enum:
# noinspection PyTypeChecker
strawberry_enum = schema_factory.enums[
annotation.__name__
] = strawberry.enum(annotation)
strawberry_enum = schema_factory.enums[annotation.__name__] = (
strawberry.enum(annotation)
)
return strawberry_enum

def create_input(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ class AuthorizationHandlerFilter(HandlerFilterABC):
priority: int = 120
authorizer: AuthorizerABC = field(default_factory=get_default_authorizer)
# What to name the authorization parameter if none exists.
info_kwarg_name: str = "info" # NOTE: It seems that strawberry reserves the name: Info for this parameter
info_kwarg_name: str = (
"info" # NOTE: It seems that strawberry reserves the name: Info for this parameter
)

def filter(
self,
Expand Down
6 changes: 3 additions & 3 deletions servey/servey_test/test_servey_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ def define_test_class():
for action in find_actions():
for example in action.examples or []:
if example.include_in_tests:
test_methods[
"test_" + action.name + "__" + example.name
] = _define_action_example_test(action, example)
test_methods["test_" + action.name + "__" + example.name] = (
_define_action_example_test(action, example)
)
test_class = type("TestServeyActions", (TestCase,), test_methods)
return test_class
4 changes: 2 additions & 2 deletions servey/util/singleton_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ def __marshaller_factory__(cls, marshaller_context):
class SingletonMarshaller(MarshallerABC[T]):
marshalled_type: T

def load(self, item: ExternalType) -> T:
def load(self, _item: ExternalType) -> T:
return self.marshalled_type()

def dump(self, item: T) -> ExternalType:
def dump(self, _item: T) -> ExternalType:
return self.marshalled_type.__name__
6 changes: 3 additions & 3 deletions servey_main/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def current_time() -> datetime:
@action(
triggers=(WEB_GET,),
examples=(
Example(name="usage", result=dict(scope=["root"]), include_in_tests=False),
Example(name="usage", result={"scope": ["root"]}, include_in_tests=False),
),
)
def current_user_info(
Expand All @@ -55,7 +55,7 @@ def auth_token(username: str, password: str) -> Optional[str]:

@action(
triggers=(WEB_GET,),
examples=(Example(name="world", params=dict(name="World"), result="Hello World!"),),
examples=(Example(name="world", params={"name": "World"}, result="Hello World!"),),
)
def say_hello(name: str) -> str:
"""
Expand Down Expand Up @@ -149,7 +149,7 @@ def get_node_by_name(name: str = "") -> Optional[Node]:
# noinspection PyUnusedLocal
@action(triggers=(WEB_POST,))
def put_root(node: Node) -> bool:
global _ROOT
global _ROOT # pylint: disable=global-statement
_ROOT = node
return True

Expand Down
32 changes: 30 additions & 2 deletions servey_main/event_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,36 @@
from servey.event_channel.websocket.websocket_event_channel import (
websocket_event_channel,
)
from servey_main.actions import print_consumer

# pylint: disable=cyclic-import

messenger = websocket_event_channel("messenger", str)

printer = background_action_channel(get_action(print_consumer))
# Lazy initialization to avoid cyclic import
_printer = None


def get_printer():
"""Get the printer event channel, initializing it if needed."""
global _printer # pylint: disable=global-statement
if _printer is None:
from servey_main.actions import (
print_consumer,
) # pylint: disable=import-outside-toplevel

_printer = background_action_channel(get_action(print_consumer))
return _printer


# For backward compatibility
class PrinterProxy:
"""Proxy object that delegates to the lazily-initialized printer."""

def publish(self, event):
return get_printer().publish(event)

def __getattr__(self, name):
return getattr(get_printer(), name)


printer = PrinterProxy()
Loading