-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PROTOTYPE: Use dynamic types and mapping with a factory
- Loading branch information
Showing
14 changed files
with
244 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
47 changes: 15 additions & 32 deletions
47
lib/openstack_query/query_methods.py → lib/openstack_query/api/query_api.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import types | ||
from typing import Type, TypeVar, List | ||
|
||
from openstack_query.api.query_api import QueryAPI | ||
from openstack_query.mappings import MappingInterface, MAPPING_REGISTRY | ||
from openstack_query.queries.query_factory import QueryFactory | ||
from structs.query.query_impl import QueryImpl | ||
|
||
# Hide the fact that a mapping interface is being used | ||
# which also decouples the mapping from the dynamic query | ||
# type in the IDE inspection | ||
QueryT = TypeVar("QueryT", bound=MappingInterface) | ||
|
||
|
||
def export_query_types() -> list[type]: | ||
""" | ||
Exports a list of callable methods dynamically, e.g. ServerQuery, UserQuery, etc. | ||
These will use the factory to inject their implementation on the fly, separating | ||
the implementation from the public API. | ||
""" | ||
registered_mappings = [] | ||
for mapping_cls in MAPPING_REGISTRY: | ||
|
||
def _inject_deps() -> QueryImpl: | ||
return QueryFactory.build_query_deps(mapping_cls) | ||
|
||
mapping_name = mapping_cls.__name__.replace("Mapping", "") | ||
new_type = type( | ||
f"{mapping_name}Query", (QueryAPI,), {"_inject_deps": _inject_deps} | ||
) | ||
registered_mappings.append(new_type) | ||
|
||
return registered_mappings |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from .mapping_interface import MappingInterface | ||
from .mapping_registry import MAPPING_REGISTRY |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import abc | ||
from typing import Type | ||
|
||
from enums.query.props.prop_enum import PropEnum | ||
from openstack_query.handlers.server_side_handler import ServerSideHandler | ||
from structs.query.query_client_side_handlers import QueryClientSideHandlers | ||
|
||
|
||
class MappingInterface(abc.ABC): | ||
@staticmethod | ||
@abc.abstractmethod | ||
def get_prop_mapping() -> Type[PropEnum]: | ||
""" | ||
Returns a mapping of valid presets for server side attributes | ||
""" | ||
|
||
@staticmethod | ||
@abc.abstractmethod | ||
def get_server_side_handler() -> ServerSideHandler: | ||
""" | ||
Returns a mapping of valid presets for server side attributes | ||
""" | ||
|
||
@staticmethod | ||
@abc.abstractmethod | ||
def get_client_side_handlers() -> QueryClientSideHandlers: | ||
""" | ||
Returns a mapping of valid presets for client side attributes | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from typing import Dict, TypeVar, List, Type | ||
|
||
from openstack_query.mappings.mapping_interface import MappingInterface | ||
from openstack_query.mappings.server_mapping import ServerMapping | ||
|
||
MappingType = TypeVar("MappingType", bound=Type[MappingInterface]) | ||
|
||
MAPPING_REGISTRY: List[MappingType] = [ServerMapping] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
from typing import Type | ||
|
||
from enums.query.props.server_properties import ServerProperties | ||
from enums.query.query_presets import ( | ||
QueryPresetsGeneric, | ||
QueryPresetsDateTime, | ||
QueryPresetsString, | ||
) | ||
from openstack_query.handlers.client_side_handler_datetime import ( | ||
ClientSideHandlerDateTime, | ||
) | ||
from openstack_query.handlers.client_side_handler_generic import ( | ||
ClientSideHandlerGeneric, | ||
) | ||
from openstack_query.handlers.client_side_handler_string import ClientSideHandlerString | ||
from openstack_query.handlers.server_side_handler import ServerSideHandler | ||
from openstack_query.mappings import MappingInterface | ||
from openstack_query.time_utils import TimeUtils | ||
from structs.query.query_client_side_handlers import QueryClientSideHandlers | ||
|
||
|
||
class ServerMapping(MappingInterface): | ||
@staticmethod | ||
def get_prop_mapping() -> Type[ServerProperties]: | ||
return ServerProperties | ||
|
||
@staticmethod | ||
def get_server_side_handler() -> ServerSideHandler: | ||
""" | ||
method to configure a server handler which can be used to get 'filter' keyword arguments that | ||
can be passed to openstack function conn.compute.servers() to filter results for a valid preset-property pair | ||
valid filters documented here: | ||
https://docs.openstack.org/openstacksdk/latest/user/proxies/compute.html | ||
https://docs.openstack.org/api-ref/compute/?expanded=list-servers-detail#list-server-request | ||
""" | ||
|
||
return ServerSideHandler( | ||
{ | ||
QueryPresetsGeneric.EQUAL_TO: { | ||
ServerProperties.USER_ID: lambda value: {"user_id": value}, | ||
ServerProperties.SERVER_ID: lambda value: {"uuid": value}, | ||
ServerProperties.SERVER_NAME: lambda value: {"hostname": value}, | ||
ServerProperties.SERVER_DESCRIPTION: lambda value: { | ||
"description": value | ||
}, | ||
ServerProperties.SERVER_STATUS: lambda value: {"vm_state": value}, | ||
ServerProperties.SERVER_CREATION_DATE: lambda value: { | ||
"created_at": value | ||
}, | ||
ServerProperties.FLAVOR_ID: lambda value: {"flavor": value}, | ||
ServerProperties.IMAGE_ID: lambda value: {"image": value}, | ||
ServerProperties.PROJECT_ID: lambda value: {"project_id": value}, | ||
}, | ||
QueryPresetsDateTime.OLDER_THAN_OR_EQUAL_TO: { | ||
ServerProperties.SERVER_LAST_UPDATED_DATE: lambda **kwargs: { | ||
"changes-before": TimeUtils.convert_to_timestamp(**kwargs) | ||
} | ||
}, | ||
QueryPresetsDateTime.YOUNGER_THAN_OR_EQUAL_TO: { | ||
ServerProperties.SERVER_LAST_UPDATED_DATE: lambda **kwargs: { | ||
"changes-since": TimeUtils.convert_to_timestamp(**kwargs) | ||
} | ||
}, | ||
} | ||
) | ||
|
||
@staticmethod | ||
def get_client_side_handlers() -> QueryClientSideHandlers: | ||
""" | ||
method to configure a set of client-side handlers which can be used to get local filter functions | ||
corresponding to valid preset-property pairs. These filter functions can be used to filter results after | ||
listing all servers. | ||
""" | ||
return QueryClientSideHandlers( | ||
# set generic query preset mappings | ||
generic_handler=ClientSideHandlerGeneric( | ||
{ | ||
QueryPresetsGeneric.EQUAL_TO: ["*"], | ||
QueryPresetsGeneric.NOT_EQUAL_TO: ["*"], | ||
} | ||
), | ||
# set string query preset mappings | ||
string_handler=ClientSideHandlerString( | ||
{QueryPresetsString.MATCHES_REGEX: [ServerProperties.SERVER_NAME]} | ||
), | ||
# set datetime query preset mappings | ||
datetime_handler=ClientSideHandlerDateTime( | ||
{ | ||
QueryPresetsDateTime.OLDER_THAN: [ | ||
ServerProperties.SERVER_CREATION_DATE, | ||
ServerProperties.SERVER_LAST_UPDATED_DATE, | ||
], | ||
QueryPresetsDateTime.YOUNGER_THAN: [ | ||
ServerProperties.SERVER_CREATION_DATE, | ||
ServerProperties.SERVER_LAST_UPDATED_DATE, | ||
], | ||
QueryPresetsDateTime.YOUNGER_THAN_OR_EQUAL_TO: [ | ||
ServerProperties.SERVER_CREATION_DATE, | ||
ServerProperties.SERVER_LAST_UPDATED_DATE, | ||
], | ||
QueryPresetsDateTime.OLDER_THAN_OR_EQUAL_TO: [ | ||
ServerProperties.SERVER_CREATION_DATE, | ||
ServerProperties.SERVER_LAST_UPDATED_DATE, | ||
], | ||
} | ||
), | ||
# set integer query preset mappings | ||
integer_handler=None, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from openstack_query.mappings import MappingInterface | ||
from openstack_query.query_builder import QueryBuilder | ||
from openstack_query.query_output import QueryOutput | ||
from openstack_query.query_parser import QueryParser | ||
from structs.query.query_impl import QueryImpl | ||
|
||
|
||
class QueryFactory: | ||
@staticmethod | ||
def build_query_deps(mapping_cls: MappingInterface) -> QueryImpl: | ||
prop_mapping = mapping_cls.get_prop_mapping() | ||
|
||
output = QueryOutput(prop_mapping) | ||
parser = QueryParser(prop_mapping) | ||
builder = QueryBuilder( | ||
mapping_cls.get_prop_mapping(), | ||
mapping_cls.get_client_side_handlers(), | ||
mapping_cls.get_server_side_handler(), | ||
) | ||
return QueryImpl(output, parser, builder) |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.