From b5f579a499fbac1c581376643566cd7f052f4490 Mon Sep 17 00:00:00 2001 From: BJ Dierkes Date: Sun, 23 Jun 2024 19:57:25 -0500 Subject: [PATCH] Type Annotations: core.interface, core.arg - Resolves Issue #692 - Resolves Issue #702 - Related to PR #628 --- CHANGELOG.md | 3 +++ cement/core/arg.py | 10 ++++++---- cement/core/interface.py | 30 ++++++++++++++++++++++-------- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64197944..f62ed2a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,9 @@ Refactoring: - `[dev]` Remove Python 3.5, 3.6, 3.7 Docker Dev Targets - `[dev]` Added Python 3.13 Dev Target - Type Annotations (related: [PR #628](https://github.com/datafolklabs/cement/pull/628)) + - `[core.arg]` [Issue #692](https://github.com/datafolklabs/cement/issues/692) - `[core.exc]` [Issue #697](https://github.com/datafolklabs/cement/issues/697) + - `[core.interface]` [Issue #702](https://github.com/datafolklabs/cement/issues/702) - `[core.meta]` [Issue #705](https://github.com/datafolklabs/cement/issues/705) - `[utils.fs]` [Issue #688](https://github.com/datafolklabs/cement/issues/688) - `[utils.misc]` [Issue #689](https://github.com/datafolklabs/cement/issues/689) @@ -31,6 +33,7 @@ Refactoring: - `[utils.version]` [Issue #691](https://github.com/datafolklabs/cement/issues/691) + Misc: - ? diff --git a/cement/core/arg.py b/cement/core/arg.py index 833db9c3..eb08b216 100644 --- a/cement/core/arg.py +++ b/cement/core/arg.py @@ -4,6 +4,7 @@ Cement core argument module. """ from abc import abstractmethod +from typing import Any, List from ..core.interface import Interface from ..core.handler import Handler from ..utils.misc import minimal_logger @@ -28,7 +29,7 @@ class ArgumentInterface(Interface): interface = 'argument' @abstractmethod - def add_argument(self, *args, **kw): + def add_argument(self, *args: str, **kw: Any) -> None: """Add arguments to the parser. This should be ``-o/--option`` or positional. Note that the interface @@ -60,7 +61,7 @@ class ArgumentInterface(Interface): pass # pragma: nocover @abstractmethod - def parse(self, *args): + def parse(self, *args: List[str]) -> object: """ Parse the argument list (i.e. ``sys.argv``). Can return any object as long as its' members contain those of the added arguments. For @@ -71,7 +72,7 @@ class ArgumentInterface(Interface): args (list): A list of command line arguments Returns: - object: A callable object whose member reprisent the available + object: A callable object whose members reprisent the available arguments """ @@ -82,4 +83,5 @@ class ArgumentHandler(ArgumentInterface, Handler): """Argument handler implementation""" - pass # pragma: nocover + class Meta: + pass # pragma: nocover diff --git a/cement/core/interface.py b/cement/core/interface.py index 375dae7e..9b4e3b1e 100644 --- a/cement/core/interface.py +++ b/cement/core/interface.py @@ -2,13 +2,20 @@ Cement core interface module. """ +from __future__ import annotations from abc import ABC +from typing import Any, Dict, Optional, Type, TYPE_CHECKING +from typing_extensions import Self from ..core import exc, meta from ..utils.misc import minimal_logger LOG = minimal_logger(__name__) +if TYPE_CHECKING: + from ..core.foundation import App # pragma: nocover + + class Interface(ABC, meta.MetaMixin): """Base interface class that all Cement Interfaces should subclass from.""" @@ -21,10 +28,12 @@ class Interface(ABC, meta.MetaMixin): """ - interface = NotImplemented + interface: str = NotImplemented """The string identifier of this interface.""" - def __init__(self, **kw): + _meta: Self + + def __init__(self, **kw: Any) -> None: super(Interface, self).__init__(**kw) try: assert self._meta.interface, \ @@ -32,7 +41,7 @@ class Interface(ABC, meta.MetaMixin): except AssertionError as e: raise exc.InterfaceError(e.args[0]) - def _validate(self): + def _validate(self) -> None: """ Perform any validation to ensure proper data, meta-data, etc. """ @@ -46,11 +55,16 @@ class InterfaceManager(object): """ - def __init__(self, app): + __interfaces__: Dict[str, Type[Interface]] + + def __init__(self, app: App) -> None: self.app = app self.__interfaces__ = {} - def get(self, interface, fallback=None, **kwargs): + def get(self, + interface: str, + fallback: Optional[Type[Interface]] = None, + **kwargs: Any) -> Type[Interface]: """ Get an interface class. @@ -82,7 +96,7 @@ class InterfaceManager(object): raise exc.InterfaceError("interface '%s' does not exist!" % interface) - def list(self): + def list(self) -> list[str]: """ Return a list of defined interfaces. @@ -98,7 +112,7 @@ class InterfaceManager(object): """ return list(self.__interfaces__.keys()) - def define(self, ibc): + def define(self, ibc: Type[Interface]) -> None: """ Define an ``ibc`` (interface base class). @@ -125,7 +139,7 @@ class InterfaceManager(object): raise exc.InterfaceError(msg) self.__interfaces__[ibc.Meta.interface] = ibc - def defined(self, interface): + def defined(self, interface: str) -> bool: """ Test whether ``interface`` is defined.