diff --git a/.config/pydoclint-baseline.txt b/.config/pydoclint-baseline.txt index 72c4d5fdc..67d627e91 100644 --- a/.config/pydoclint-baseline.txt +++ b/.config/pydoclint-baseline.txt @@ -42,52 +42,6 @@ src/molecule/dependency/shell.py DOC107: Method `Shell.__init__`: The option `--arg-type-hints-in-signature` is `True` but not all args in the signature have type hints DOC103: Method `Shell.__init__`: Docstring arguments are different from function arguments. (Or could be other formatting issues: https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ). Arguments in the function signature but not in the docstring: [config: ]. -------------------- -src/molecule/driver/base.py - DOC601: Class `Driver`: Class docstring contains fewer class attributes than actual class attributes. (Please read https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to correctly document class attributes.) - DOC603: Class `Driver`: Class docstring attributes are different from actual class attributes. (Or could be other formatting issues: https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ). Attributes in the class definition but not in the docstring: [__metaclass__: ]. (Please read https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to correctly document class attributes.) - DOC106: Method `Driver.__init__`: The option `--arg-type-hints-in-signature` is `True` but there are no argument type hints in the signature - DOC107: Method `Driver.__init__`: The option `--arg-type-hints-in-signature` is `True` but not all args in the signature have type hints - DOC101: Method `Driver.name`: Docstring contains fewer arguments than in function signature. - DOC106: Method `Driver.name`: The option `--arg-type-hints-in-signature` is `True` but there are no argument type hints in the signature - DOC107: Method `Driver.name`: The option `--arg-type-hints-in-signature` is `True` but not all args in the signature have type hints - DOC103: Method `Driver.name`: Docstring arguments are different from function arguments. (Or could be other formatting issues: https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ). Arguments in the function signature but not in the docstring: [value: ]. - DOC202: Method `Driver.login_cmd_template` has a return section in docstring, but there are no return statements or annotations - DOC106: Method `Driver.login_options`: The option `--arg-type-hints-in-signature` is `True` but there are no argument type hints in the signature - DOC107: Method `Driver.login_options`: The option `--arg-type-hints-in-signature` is `True` but not all args in the signature have type hints - DOC202: Method `Driver.login_options` has a return section in docstring, but there are no return statements or annotations - DOC106: Method `Driver.ansible_connection_options`: The option `--arg-type-hints-in-signature` is `True` but there are no argument type hints in the signature - DOC107: Method `Driver.ansible_connection_options`: The option `--arg-type-hints-in-signature` is `True` but not all args in the signature have type hints - DOC202: Method `Driver.ansible_connection_options` has a return section in docstring, but there are no return statements or annotations - DOC201: Method `Driver.status` does not have a return section in docstring - DOC101: Method `Driver.__eq__`: Docstring contains fewer arguments than in function signature. - DOC106: Method `Driver.__eq__`: The option `--arg-type-hints-in-signature` is `True` but there are no argument type hints in the signature - DOC107: Method `Driver.__eq__`: The option `--arg-type-hints-in-signature` is `True` but not all args in the signature have type hints - DOC103: Method `Driver.__eq__`: Docstring arguments are different from function arguments. (Or could be other formatting issues: https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ). Arguments in the function signature but not in the docstring: [other: ]. - DOC201: Method `Driver.__eq__` does not have a return section in docstring - DOC101: Method `Driver.__lt__`: Docstring contains fewer arguments than in function signature. - DOC106: Method `Driver.__lt__`: The option `--arg-type-hints-in-signature` is `True` but there are no argument type hints in the signature - DOC107: Method `Driver.__lt__`: The option `--arg-type-hints-in-signature` is `True` but not all args in the signature have type hints - DOC103: Method `Driver.__lt__`: Docstring arguments are different from function arguments. (Or could be other formatting issues: https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ). Arguments in the function signature but not in the docstring: [other: ]. - DOC201: Method `Driver.__lt__` does not have a return section in docstring - DOC201: Method `Driver.__hash__` does not have a return section in docstring - DOC201: Method `Driver.__str__` does not have a return section in docstring - DOC201: Method `Driver.__repr__` does not have a return section in docstring - DOC201: Method `Driver.__rich__` does not have a return section in docstring - DOC101: Method `Driver.get_playbook`: Docstring contains fewer arguments than in function signature. - DOC106: Method `Driver.get_playbook`: The option `--arg-type-hints-in-signature` is `True` but there are no argument type hints in the signature - DOC107: Method `Driver.get_playbook`: The option `--arg-type-hints-in-signature` is `True` but not all args in the signature have type hints - DOC103: Method `Driver.get_playbook`: Docstring arguments are different from function arguments. (Or could be other formatting issues: https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ). Arguments in the function signature but not in the docstring: [step: ]. - DOC201: Method `Driver.get_playbook` does not have a return section in docstring - DOC201: Method `Driver.modules_dir` does not have a return section in docstring --------------------- -src/molecule/driver/delegated.py - DOC601: Class `Delegated`: Class docstring contains fewer class attributes than actual class attributes. (Please read https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to correctly document class attributes.) - DOC603: Class `Delegated`: Class docstring attributes are different from actual class attributes. (Or could be other formatting issues: https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ). Attributes in the class definition but not in the docstring: [title: ]. (Please read https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to correctly document class attributes.) - DOC101: Method `Delegated.__init__`: Docstring contains fewer arguments than in function signature. - DOC106: Method `Delegated.__init__`: The option `--arg-type-hints-in-signature` is `True` but there are no argument type hints in the signature - DOC107: Method `Delegated.__init__`: The option `--arg-type-hints-in-signature` is `True` but not all args in the signature have type hints - DOC103: Method `Delegated.__init__`: Docstring arguments are different from function arguments. (Or could be other formatting issues: https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ). Arguments in the function signature but not in the docstring: [config: ]. --------------------- src/molecule/model/schema_v3.py DOC101: Function `validate`: Docstring contains fewer arguments than in function signature. DOC106: Function `validate`: The option `--arg-type-hints-in-signature` is `True` but there are no argument type hints in the signature diff --git a/src/molecule/command/list.py b/src/molecule/command/list.py index 3b88f38c8..89027e526 100644 --- a/src/molecule/command/list.py +++ b/src/molecule/command/list.py @@ -59,7 +59,7 @@ def execute( # type: ignore[override] Returns: List of statuses. """ - return self._config.driver.status() # type: ignore[no-untyped-call, no-any-return] + return self._config.driver.status() @base.click_command_ex(name="list") diff --git a/src/molecule/command/login.py b/src/molecule/command/login.py index 70de8b2d1..fee7d825e 100644 --- a/src/molecule/command/login.py +++ b/src/molecule/command/login.py @@ -105,7 +105,7 @@ def _get_hostname(self, hosts: list[str]) -> str: def _get_login(self, hostname: str) -> None: # pragma: no cover # ruff: noqa: S605,S607 lines, columns = os.popen("stty size", "r").read().split() - login_options = self._config.driver.login_options(hostname) # type: ignore[no-untyped-call] + login_options = self._config.driver.login_options(hostname) login_options["columns"] = columns login_options["lines"] = lines if not self._config.driver.login_cmd_template: diff --git a/src/molecule/driver/__init__.py b/src/molecule/driver/__init__.py index d2583e366..6e031999e 100644 --- a/src/molecule/driver/__init__.py +++ b/src/molecule/driver/__init__.py @@ -1 +1 @@ -# D104 # noqa: D104, ERA001 +# noqa: D104 diff --git a/src/molecule/driver/base.py b/src/molecule/driver/base.py index 318104307..3f8282f35 100644 --- a/src/molecule/driver/base.py +++ b/src/molecule/driver/base.py @@ -23,23 +23,29 @@ import inspect import os -from abc import ABCMeta, abstractmethod +from abc import ABC, abstractmethod from importlib.metadata import version +from pathlib import Path +from typing import TYPE_CHECKING from molecule.status import Status -class Driver: +if TYPE_CHECKING: + from molecule.config import Config + from molecule.types import DriverOptions + + +class Driver(ABC): """Driver Class. Attributes: title: Short description of the driver. """ - __metaclass__ = ABCMeta title = "" - def __init__(self, config=None) -> None: # type: ignore[no-untyped-def] # noqa: ANN001 + def __init__(self, config: Config) -> None: """Initialize code for all :ref:`Driver` classes. Args: @@ -55,32 +61,35 @@ def __init__(self, config=None) -> None: # type: ignore[no-untyped-def] # noqa @property @abstractmethod def name(self) -> str: # pragma: no cover - """Name of the driver and returns a string. + """Name of the driver. - :returns: str + Returns: + Name of the driver. """ @name.setter - def name(self, value): # type: ignore[no-untyped-def] # pragma: no cover # noqa: ANN001, ANN202 - """Driver name setter and returns None. + @abstractmethod + def name(self, value: str) -> None: # pragma: no cover + """Driver name setter. - :returns: None + Args: + value: New driver name. """ @property - def testinfra_options(self): # type: ignore[no-untyped-def] # noqa: ANN201 + def testinfra_options(self) -> dict[str, str]: """Testinfra specific options and returns a dict. :returns: dict """ return { "connection": "ansible", - "ansible-inventory": self._config.provisioner.inventory_directory, + "ansible-inventory": self._config.provisioner.inventory_directory, # type: ignore[union-attr] } @property @abstractmethod - def login_cmd_template(self): # type: ignore[no-untyped-def] # pragma: no cover # noqa: ANN201 + def login_cmd_template(self) -> str: # pragma: no cover """Get the login command template to be populated by ``login_options`` as a string. Returns: @@ -89,7 +98,7 @@ def login_cmd_template(self): # type: ignore[no-untyped-def] # pragma: no cover @property @abstractmethod - def default_ssh_connection_options(self): # type: ignore[no-untyped-def] # pragma: no cover # noqa: ANN201 + def default_ssh_connection_options(self) -> list[str]: # pragma: no cover """SSH client options and returns a list. :returns: list @@ -97,14 +106,17 @@ def default_ssh_connection_options(self): # type: ignore[no-untyped-def] # prag @property @abstractmethod - def default_safe_files(self): # type: ignore[no-untyped-def] # pragma: no cover # noqa: ANN201 + def default_safe_files(self) -> list[str]: # pragma: no cover """Generate files to be preserved. :returns: list """ @abstractmethod - def login_options(self, instance_name): # type: ignore[no-untyped-def] # pragma: no cover # noqa: ANN001, ANN201 + def login_options( + self, + instance_name: str, + ) -> dict[str, str]: # pragma: no cover """Options used in the login command and returns a dict. Args: @@ -115,7 +127,10 @@ def login_options(self, instance_name): # type: ignore[no-untyped-def] # pragma """ @abstractmethod - def ansible_connection_options(self, instance_name): # type: ignore[no-untyped-def] # pragma: no cover # noqa: ANN001, ANN201 + def ansible_connection_options( + self, + instance_name: str, + ) -> dict[str, str]: # pragma: no cover """Ansible specific connection options supplied to inventory and returns a dict. Args: @@ -134,48 +149,70 @@ def sanity_checks(self) -> None: daemon is running and we have the correct Docker Python dependency. Each driver implementation can decide what is the most stable sanity check for itself. - - :returns: None """ @property - def options(self): # type: ignore[no-untyped-def] # noqa: ANN201, D102 + def options(self) -> DriverOptions: + """Driver options. + + Returns: + Dictionary of driver options. + """ return self._config.config["driver"]["options"] @property - def instance_config(self): # type: ignore[no-untyped-def] # noqa: ANN201, D102 - return os.path.join( # noqa: PTH118 - self._config.scenario.ephemeral_directory, - "instance_config.yml", + def instance_config(self) -> str: + """Instance config file location. + + Returns: + Path to instance_config.yml. + """ + return str( + Path( + self._config.scenario.ephemeral_directory, + "instance_config.yml", + ), ) @property - def ssh_connection_options(self): # type: ignore[no-untyped-def] # noqa: ANN201, D102 + def ssh_connection_options(self) -> list[str]: + """SSH connection options. + + Returns: + List of ssh connection options. + """ if self._config.config["driver"]["ssh_connection_options"]: return self._config.config["driver"]["ssh_connection_options"] return self.default_ssh_connection_options @property - def safe_files(self): # type: ignore[no-untyped-def] # noqa: ANN201, D102 + def safe_files(self) -> list[str]: + """Safe files. + + Returns: + List of safe files. + """ return self.default_safe_files + self._config.config["driver"]["safe_files"] @property - def delegated(self): # type: ignore[no-untyped-def] # noqa: ANN201 - """Is the dedriver delegated and returns a bool. + def delegated(self) -> bool: + """Is the driver delegated. - :returns: bool + Returns: + Whether the driver is delegated. """ return self.name == "default" @property - def managed(self): # type: ignore[no-untyped-def] # noqa: ANN201 - """Is the driver is managed and returns a bool. + def managed(self) -> bool: + """Is the driver is managed. - :returns: bool + Returns: + Whether the driver is managed. """ return self.options["managed"] - def status(self): # type: ignore[no-untyped-def] # noqa: ANN201 + def status(self) -> list[Status]: """Collect the instances state and returns a list. !!! note @@ -186,13 +223,15 @@ def status(self): # type: ignore[no-untyped-def] # noqa: ANN201 driver to match the options passed to the playbook may prove difficult. Especially in cases where the user is provisioning instances off localhost. - :returns: list + + Returns: + Status for each instance. """ status_list = [] for platform in self._config.platforms.instances: instance_name = platform["name"] driver_name = self.name - provisioner_name = self._config.provisioner.name + provisioner_name = self._config.provisioner.name if self._config.provisioner else "" scenario_name = self._config.scenario.name status_list.append( @@ -201,14 +240,14 @@ def status(self): # type: ignore[no-untyped-def] # noqa: ANN201 driver_name=driver_name, provisioner_name=provisioner_name, scenario_name=scenario_name, - created=self._created(), # type: ignore[no-untyped-call] - converged=self._converged(), # type: ignore[no-untyped-call] + created=self._created(), + converged=self._converged(), ), ) return status_list - def _get_ssh_connection_options(self): # type: ignore[no-untyped-def] # noqa: ANN202 + def _get_ssh_connection_options(self) -> list[str]: # LogLevel=ERROR is needed in order to avoid warnings like: # Warning: Permanently added ... to the list of known hosts. return [ @@ -221,62 +260,107 @@ def _get_ssh_connection_options(self): # type: ignore[no-untyped-def] # noqa: "-o StrictHostKeyChecking=no", ] - def _created(self): # type: ignore[no-untyped-def] # noqa: ANN202 + def _created(self) -> str: return str(self._config.state.created).lower() - def _converged(self): # type: ignore[no-untyped-def] # noqa: ANN202 + def _converged(self) -> str: return str(self._config.state.converged).lower() - def __eq__(self, other): # type: ignore[no-untyped-def] # noqa: ANN001, ANN204 - """Implement equality comparison.""" + def __eq__(self, other: object) -> bool: + """Implement equality comparison. + + Args: + other: object to compare against this one. + + Returns: + Whether other matches the name of this driver. + """ # trick that allows us to test if a driver is loaded via: # if 'driver-name' in drivers() return str(self) == str(other) - def __lt__(self, other): # type: ignore[no-untyped-def] # noqa: ANN001, ANN204 - """Implement lower than comparison.""" + def __lt__(self, other: object) -> bool: + """Implement lower than comparison. + + Args: + other: object to compare against this one. + + Returns: + Whether other is less than the name of this driver. + """ return str.__lt__(str(self), str(other)) - def __hash__(self): # type: ignore[no-untyped-def] # noqa: ANN204 - """Perform object hash.""" + def __hash__(self) -> int: + """Perform object hash. + + Returns: + Hash of driver name. + """ return self.name.__hash__() def __str__(self) -> str: - """Return readable string representation of object.""" + """Return readable string representation of object. + + Returns: + Driver name. + """ return self.name def __repr__(self) -> str: - """Return detailed string representation of object.""" + """Return detailed string representation of object. + + Returns: + Driver name. + """ return self.name - def __rich__(self): # type: ignore[no-untyped-def] # noqa: ANN204 - """Return rich representation of object.""" + def __rich__(self) -> str: + """Return rich representation of object. + + Returns: + Driver name. + """ return self.__str__() - def get_playbook(self, step): # type: ignore[no-untyped-def] # noqa: ANN001, ANN201 + def get_playbook(self, step: str) -> str | None: """Return embedded playbook location or None. The default location is relative to the file implementing the driver class, allowing driver writers to define playbooks without having to override this method. + + Args: + step: The step to look for a playbook for. + + Returns: + The playbook file path, if any. """ - p = os.path.join( # noqa: PTH118 + p = Path( self._path, "playbooks", step + ".yml", ) - if os.path.isfile(p): # noqa: PTH113 - return p + if p.is_file(): + return str(p) return None - def schema_file(self) -> None | str: # noqa: D102 - return None + @abstractmethod + def schema_file(self) -> str: + """Return schema file path. + + Returns: + Path to schema file. + """ def modules_dir(self) -> str | None: - """Return path to ansible modules included with driver.""" - p = os.path.join(self._path, "modules") # noqa: PTH118 - if os.path.isdir(p): # noqa: PTH112 - return p + """Return path to ansible modules included with driver. + + Returns: + Path to modules dir if one exists. + """ + p = Path(self._path, "modules") + if p.is_dir(): + return str(p) return None def reset(self) -> None: @@ -286,6 +370,7 @@ def reset(self) -> None: by molecule, regardless the scenario name. Molecule will use metadata like labels or tags to annotate resources allocated by it. """ + return @property def required_collections(self) -> dict[str, str]: diff --git a/src/molecule/driver/delegated.py b/src/molecule/driver/delegated.py index 0c40365e5..31a1b04d5 100644 --- a/src/molecule/driver/delegated.py +++ b/src/molecule/driver/delegated.py @@ -23,11 +23,17 @@ import logging import os +from typing import TYPE_CHECKING, Any + from molecule import util from molecule.api import Driver from molecule.data import __file__ as data_module +if TYPE_CHECKING: + from molecule.config import Config + + LOG = logging.getLogger(__name__) @@ -138,25 +144,47 @@ class Delegated(Driver): ansible_connection_options: ansible_connection: local ``` + + Attributes: + title: Short description of the driver. """ title = "Default driver, user is expected to manage provisioning of test resources." - def __init__(self, config=None) -> None: # type: ignore[no-untyped-def] # noqa: ANN001 - """Construct Delegated.""" + def __init__(self, config: Config) -> None: + """Construct Delegated. + + Args: + config: An instance of a Molecule config. + """ super().__init__(config) self._name = "default" @property - def name(self): # type: ignore[no-untyped-def] # noqa: ANN201, D102 + def name(self) -> str: + """Name of the driver. + + Returns: + Name of the driver. + """ return self._name @name.setter - def name(self, value): # type: ignore[no-untyped-def] # noqa: ANN001, ANN202 + def name(self, value: str) -> None: + """Driver name setter. + + Args: + value: New name of the driver. + """ self._name = value @property - def login_cmd_template(self): # type: ignore[no-untyped-def] # noqa: ANN201, D102 + def login_cmd_template(self) -> str: + """Get the login command template to be populated by ``login_options`` as a string. + + Returns: + The login command template, if any. + """ if "login_cmd_template" in self.options: return self.options["login_cmd_template"] @@ -170,36 +198,62 @@ def login_cmd_template(self): # type: ignore[no-untyped-def] # noqa: ANN201, D "-i {identity_file} " f"{connection_options}" ) - return None + return "" @property - def default_safe_files(self): # type: ignore[no-untyped-def] # noqa: ANN201, D102 + def default_safe_files(self) -> list[str]: + """Generate files to be preserved. + + Returns: + List of files to be preserved. + """ return [] @property - def default_ssh_connection_options(self): # type: ignore[no-untyped-def] # noqa: ANN201, D102 + def default_ssh_connection_options(self) -> list[str]: + """SSH client options. + + Returns: + List of SSH connection options. + """ if self.managed: - ssh_connopts = self._get_ssh_connection_options() # type: ignore[no-untyped-call] - if self.options.get("ansible_connection_options", {}).get( + ssh_connopts = self._get_ssh_connection_options() + if config_connopts := self.options.get("ansible_connection_options", {}).get( "ansible_ssh_common_args", - None, ): ssh_connopts.append( - self.options.get("ansible_connection_options").get( - "ansible_ssh_common_args", - ), + config_connopts, ) return ssh_connopts return [] - def login_options(self, instance_name): # type: ignore[no-untyped-def] # noqa: ANN001, ANN201, D102 + def login_options(self, instance_name: str) -> dict[str, str]: + """Login options. + + Args: + instance_name: The name of the instance to look up login options for. + + Returns: + Dictionary of options related to logging into the instance. + """ if self.managed: d = {"instance": instance_name} - return util.merge_dicts(d, self._get_instance_config(instance_name)) # type: ignore[no-untyped-call] + return util.merge_dicts(d, self._get_instance_config(instance_name)) return {"instance": instance_name} - def ansible_connection_options(self, instance_name): # type: ignore[no-untyped-def] # noqa: ANN001, ANN201, D102 + def ansible_connection_options( + self, + instance_name: str, + ) -> dict[str, str]: + """Ansible connection options. + + Args: + instance_name: The name of the instance to look up Ansible connection options for. + + Returns: + Dictionary of options related to ansible connection to the instance. + """ # list of tuples describing mappable instance params and default values instance_params = [ ("become_pass", None), @@ -213,7 +267,7 @@ def ansible_connection_options(self, instance_name): # type: ignore[no-untyped- ] if self.managed: try: - d = self._get_instance_config(instance_name) # type: ignore[no-untyped-call] + d = self._get_instance_config(instance_name) conn_dict = {} # Check if optional mappable params are in the instance config for i in instance_params: @@ -246,19 +300,24 @@ def ansible_connection_options(self, instance_name): # type: ignore[no-untyped- return {} return self.options.get("ansible_connection_options", {}) - def _created(self): # type: ignore[no-untyped-def] # noqa: ANN202 + def _created(self) -> str: if self.managed: - return super()._created() # type: ignore[no-untyped-call] + return super()._created() return "unknown" - def _get_instance_config(self, instance_name): # type: ignore[no-untyped-def] # noqa: ANN001, ANN202 + def _get_instance_config(self, instance_name: str) -> dict[str, Any]: instance_config_dict = util.safe_load_file(self._config.driver.instance_config) return next(item for item in instance_config_dict if item["instance"] == instance_name) - def sanity_checks(self): # type: ignore[no-untyped-def] # noqa: ANN201, D102 + def sanity_checks(self) -> None: + """Run sanity checks.""" # Note(decentral1se): Cannot implement driver specifics are unknown - pass - def schema_file(self): # type: ignore[no-untyped-def] # noqa: ANN201, D102 + def schema_file(self) -> str: + """Return schema file path. + + Returns: + Path to schema file. + """ return os.path.join(os.path.dirname(data_module), "driver.json") # noqa: PTH118, PTH120 diff --git a/src/molecule/provisioner/ansible.py b/src/molecule/provisioner/ansible.py index f59c66415..ee5439dd9 100644 --- a/src/molecule/provisioner/ansible.py +++ b/src/molecule/provisioner/ansible.py @@ -727,7 +727,7 @@ def connection_options( Returns: The combined connection options. """ - d = self._config.driver.ansible_connection_options(instance_name) # type: ignore[no-untyped-call] + d = self._config.driver.ansible_connection_options(instance_name) return util.merge_dicts( d, diff --git a/src/molecule/provisioner/ansible_playbooks.py b/src/molecule/provisioner/ansible_playbooks.py index dd794bcd1..b3ec4f673 100644 --- a/src/molecule/provisioner/ansible_playbooks.py +++ b/src/molecule/provisioner/ansible_playbooks.py @@ -175,9 +175,9 @@ def _get_playbook(self, section: Section) -> str | None: return None def _get_bundled_driver_playbook(self, section: Section) -> str: - path = self._config.driver.get_playbook(section) # type: ignore[no-untyped-call] - if path: - return path # type: ignore[no-any-return] + driver_path = self._config.driver.get_playbook(section) + if driver_path: + return driver_path path = Path( self._get_playbook_directory(), diff --git a/src/molecule/types.py b/src/molecule/types.py index 052b9d1b2..0cf902809 100644 --- a/src/molecule/types.py +++ b/src/molecule/types.py @@ -27,6 +27,20 @@ class DependencyData(TypedDict, total=False): env: dict[str, Any] +class DriverOptions(TypedDict, total=False): + """Config options for molecule drivers. + + Attributes: + ansible_connection_options: Options to use with ansible connection plugin. + login_cmd_template: Template with which to generate login commands. + managed: Whether the driver is managed. + """ + + ansible_connection_options: dict[str, str] + login_cmd_template: str + managed: bool + + class DriverData(TypedDict, total=False): """Molecule driver configuration. @@ -40,7 +54,7 @@ class DriverData(TypedDict, total=False): name: str provider: dict[str, Any] - options: dict[str, Any] + options: DriverOptions ssh_connection_options: list[str] safe_files: list[str]