Skip to content

Commit

Permalink
Switch to google style docstring, enable pydoclint (#4202)
Browse files Browse the repository at this point in the history
- Switch exisitng sphinx docstring to goole style
- Switch ruff to google style doc strings
- Enable pydoclint precommit
- Add exceptions as needed
- Update test extras to reflect new dev tools
  • Loading branch information
cidrblock authored Jun 6, 2024
1 parent 9b64152 commit f7e0b8d
Show file tree
Hide file tree
Showing 37 changed files with 332 additions and 375 deletions.
5 changes: 5 additions & 0 deletions .config/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ defusedxml==0.7.1
dill==0.3.8
distlib==0.3.8
dnspython==2.6.1
docstring-parser-fork==0.0.5
enrich==1.2.7
exceptiongroup==1.2.1
execnet==2.1.1
filelock==3.14.0
flake8==7.0.0
ghp-import==2.1.0
griffe==0.45.1
htmlmin2==0.1.13
Expand Down Expand Up @@ -84,7 +86,10 @@ platformdirs==4.2.2
pluggy==1.5.0
pre-commit==3.7.1
ptyprocess==0.7.0
pycodestyle==2.11.1
pycparser==2.22
pydoclint==0.4.1
pyflakes==3.2.0
pygments==2.18.0
pylint==3.2.3
pymdown-extensions==10.8.1
Expand Down
2 changes: 2 additions & 0 deletions .config/requirements-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ black
check-jsonschema
coverage >= 7.0.3
filelock >= 3.9.0
flake8
mypy
pexpect >= 4.8.0, < 5
pre-commit
pydoclint[flake8]
pylint
pytest >= 7.2.0
pytest-mock >= 3.10.0
Expand Down
46 changes: 46 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,49 @@ filename =
*/src/**/*.py
*/tests/**/*.py
style = google
per-file-ignores =
src/molecule/api.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/command/base.py: DOC101,DOC103,DOC106,DOC107,DOC201,DOC302,DOC303,DOC501
src/molecule/command/check.py: DOC101,DOC103,DOC106,DOC107
src/molecule/command/cleanup.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/command/converge.py: DOC101,DOC103,DOC106,DOC107
src/molecule/command/create.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/command/dependency.py: DOC101,DOC103,DOC106,DOC107
src/molecule/command/destroy.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/command/drivers.py: DOC101,DOC103,DOC106,DOC107
src/molecule/command/idempotence.py: DOC101,DOC103,DOC106,DOC107
src/molecule/command/init/scenario.py: DOC101,DOC103,DOC106,DOC107
src/molecule/command/list.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/command/login.py: DOC101,DOC103,DOC106,DOC107
src/molecule/command/matrix.py: DOC101,DOC103,DOC106,DOC107
src/molecule/command/prepare.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/command/reset.py: DOC101,DOC103,DOC106,DOC107
src/molecule/command/side_effect.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/command/syntax.py: DOC101,DOC103,DOC106,DOC107
src/molecule/command/test.py: DOC101,DOC103,DOC106,DOC107
src/molecule/command/verify.py: DOC101,DOC103,DOC106,DOC107
src/molecule/config.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/console.py: DOC101,DOC103,DOC201
src/molecule/dependency/ansible_galaxy/__init__.py: DOC101,DOC103,DOC106,DOC107
src/molecule/dependency/ansible_galaxy/base.py: DOC101,DOC103,DOC106,DOC107
src/molecule/dependency/base.py: DOC101,DOC103,DOC106,DOC107,DOC201,DOC202
src/molecule/dependency/shell.py: DOC101,DOC103,DOC106,DOC107
src/molecule/driver/base.py: DOC101,DOC103,DOC106,DOC107,DOC201,DOC202
src/molecule/driver/delegated.py: DOC101,DOC103,DOC106,DOC107
src/molecule/interpolation.py: DOC101,DOC103
src/molecule/logger.py: DOC101,DOC103,DOC201
src/molecule/model/schema_v3.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/platforms.py: DOC106,DOC107
src/molecule/provisioner/ansible.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/provisioner/ansible_playbook.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/provisioner/ansible_playbooks.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/provisioner/base.py: DOC106,DOC107,DOC202
src/molecule/scenario.py: DOC101,DOC103,DOC106,DOC107,DOC201,DOC501
src/molecule/scenarios.py: DOC106,DOC107,DOC201
src/molecule/shell.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/state.py: DOC106,DOC107,DOC501
src/molecule/text.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/util.py: DOC001,DOC101,DOC103,DOC106,DOC107,DOC201,DOC402,DOC404,DOC501
src/molecule/verifier/base.py: DOC101,DOC103,DOC106,DOC107,DOC201
src/molecule/verifier/testinfra.py: DOC101,DOC103,DOC106,DOC107
tests/**: DOC101,DOC103,DOC106,DOC107,DOC201
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ repos:
- id: cspell
name: Spell check with cspell

- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks:
- id: flake8
name: flake8(pydoclint)
additional_dependencies:
- pydoclint[flake8]

- repo: https://github.com/pre-commit/mirrors-mypy.git
rev: v1.10.0
hooks:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ lines-between-types = 1 # Separate import/from with 1 line
"tests/**" = ["SLF001", "S101", "S602", "T201"]

[tool.ruff.lint.pydocstyle]
convention = "pep257"
convention = "google"

[tool.setuptools.dynamic]
optional-dependencies.docs = { file = [".config/requirements-docs.txt"] }
Expand Down
55 changes: 29 additions & 26 deletions src/molecule/command/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ class Base(metaclass=abc.ABCMeta):
def __init__(self, c: config.Config) -> None: # noqa: ANN101
"""Initialize code for all command classes.
:param c: An instance of a Molecule config.
:returns: None
Args:
c: An instance of a Molecule config.
Returns:
None
"""
self._config = c
self._setup()
Expand All @@ -71,10 +74,7 @@ def execute(self, action_args=None): # type: ignore[no-untyped-def] # pragma: n
pass

def _setup(self) -> None: # noqa: ANN101
"""Prepare Molecule's provisioner and returns None.
:return: None
"""
"""Prepare Molecule's provisioner and returns None."""
self._config.write()
self._config.provisioner.write_config()
self._config.provisioner.manage_inventory()
Expand All @@ -89,12 +89,11 @@ def execute_cmdline_scenarios(scenario_name, args, command_args, ansible_args=()
``args`` and ``command_args`` are combined using :func:`get_configs`
to generate the scenario(s) configuration.
:param scenario_name: Name of scenario to run, or ``None`` to run all.
:param args: ``args`` dict from ``click`` command context
:param command_args: dict of command arguments, including the target
subcommand to execute
:returns: None
Args:
scenario_name: Name of scenario to run, or ``None`` to run all.
args: ``args`` dict from ``click`` command context
command_args: dict of command arguments, including the target
ansible_args: Optional tuple of arguments to pass to the `ansible-playbook` command
"""
glob_str = MOLECULE_GLOB
if scenario_name:
Expand Down Expand Up @@ -164,8 +163,8 @@ def execute_subcommand(config, subcommand_and_args): # type: ignore[no-untyped-
def execute_scenario(scenario): # type: ignore[no-untyped-def] # noqa: ANN001, ANN201
"""Execute each command in the given scenario's configured sequence.
:param scenario: The scenario to execute.
:returns: None
Args:
scenario: The scenario to execute.
"""
for action in scenario.sequence:
execute_subcommand(scenario.config, action) # type: ignore[no-untyped-call]
Expand Down Expand Up @@ -199,16 +198,19 @@ def filter_ignored_scenarios(scenario_paths) -> list[str]: # type: ignore[no-un


def get_configs(args, command_args, ansible_args=(), glob_str=MOLECULE_GLOB): # type: ignore[no-untyped-def] # noqa: ANN001, ANN201
"""Glob the current directory for Molecule config files, instantiate config \
objects, and returns a list.
:param args: A dict of options, arguments and commands from the CLI.
:param command_args: A dict of options passed to the subcommand from
the CLI.
:param ansible_args: An optional tuple of arguments provided to the
`ansible-playbook` command.
:return: list
""" # noqa: D205
"""Glob the current directory for Molecule config files.
Instantiate config objects, and returns a list.
Args:
args: A dict of options, arguments and commands from the CLI.
command_args: A dict of options passed to the subcommand from the CLI.
ansible_args: An optional tuple of arguments provided to the `ansible-playbook` command.
glob_str: A string representing the glob used to find Molecule config files.
Returns:
A list of Config objects.
"""
scenario_paths = glob.glob(
glob_str,
flags=wcmatch.pathlib.GLOBSTAR | wcmatch.pathlib.BRACE | wcmatch.pathlib.DOTGLOB,
Expand All @@ -232,8 +234,9 @@ def get_configs(args, command_args, ansible_args=(), glob_str=MOLECULE_GLOB): #
def _verify_configs(configs, glob_str=MOLECULE_GLOB): # type: ignore[no-untyped-def] # noqa: ANN001, ANN202
"""Verify a Molecule config was found and returns None.
:param configs: A list containing absolute paths to Molecule config files.
:return: None
Args:
configs: A list containing absolute paths to Molecule config files.
glob_str: A string representing the glob used to find Molecule config files.
"""
if configs:
scenario_names = [c.scenario.name for c in configs]
Expand Down
10 changes: 2 additions & 8 deletions src/molecule/command/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ class Check(base.Base):
"""Check Command Class."""

def execute(self, action_args=None): # type: ignore[no-untyped-def] # noqa: ANN001, ANN101, ANN201, ARG002
"""Execute the actions necessary to perform a `molecule check` and \
returns None.
:return: None
""" # noqa: D205
"""Execute the actions necessary to perform a `molecule check` and returns None."""
self._config.provisioner.check()


Expand All @@ -58,9 +54,7 @@ def execute(self, action_args=None): # type: ignore[no-untyped-def] # noqa: AN
help="Enable or disable parallel mode. Default is disabled.",
)
def check(ctx, scenario_name, parallel): # type: ignore[no-untyped-def] # pragma: no cover # noqa: ANN001, ANN201
"""Use the provisioner to perform a Dry-Run (destroy, dependency, create, \
prepare, converge).
""" # noqa: D205
"""Use the provisioner to perform a Dry-Run (destroy, dependency, create, prepare, converge)."""
args = ctx.obj.get("args")
subcommand = base._get_subcommand(__name__) # type: ignore[no-untyped-call] # noqa: SLF001
command_args = {"parallel": parallel, "subcommand": subcommand}
Expand Down
13 changes: 5 additions & 8 deletions src/molecule/command/cleanup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ class Cleanup(base.Base):
"""Cleanup Command Class."""

def execute(self, action_args=None): # type: ignore[no-untyped-def] # noqa: ANN001, ANN101, ANN201, ARG002
"""Execute the actions necessary to cleanup the instances and returns \
None.
:return: None
""" # noqa: D205
"""Execute the actions necessary to cleanup the instances and returns None."""
if not self._config.provisioner.playbooks.cleanup:
msg = "Skipping, cleanup playbook not configured."
LOG.warning(msg)
Expand All @@ -55,9 +51,10 @@ def execute(self, action_args=None): # type: ignore[no-untyped-def] # noqa: AN
help=f"Name of the scenario to target. ({base.MOLECULE_DEFAULT_SCENARIO_NAME})",
)
def cleanup(ctx, scenario_name="default"): # type: ignore[no-untyped-def] # pragma: no cover # noqa: ANN001, ANN201
"""Use the provisioner to cleanup any changes made to external systems during \
the stages of testing.
""" # noqa: D205
"""Use the provisioner to cleanup any changes.
Any changes made to external systems during the stages of testing.
"""
args = ctx.obj.get("args")
subcommand = base._get_subcommand(__name__) # type: ignore[no-untyped-call] # noqa: SLF001
command_args = {"subcommand": subcommand}
Expand Down
6 changes: 1 addition & 5 deletions src/molecule/command/converge.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ class Converge(base.Base):
"""Converge Command Class."""

def execute(self, action_args: list[str] | None = None) -> None: # noqa: ANN101, ARG002
"""Execute the actions necessary to perform a `molecule converge` and \
returns None.
:return: None
""" # noqa: D205
"""Execute the actions necessary to perform a `molecule converge` and returns None."""
self._config.provisioner.converge()
self._config.state.change_state("converged", True) # noqa: FBT003

Expand Down
6 changes: 1 addition & 5 deletions src/molecule/command/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ class Create(base.Base):
"""Create Command Class."""

def execute(self, action_args=None): # type: ignore[no-untyped-def] # noqa: ANN001, ANN101, ANN201, ARG002
"""Execute the actions necessary to perform a `molecule create` and \
returns None.
:return: None
""" # noqa: D205
"""Execute the actions necessary to perform a `molecule create` and returns None."""
self._config.state.change_state("driver", self._config.driver.name)

if self._config.state.created:
Expand Down
6 changes: 1 addition & 5 deletions src/molecule/command/dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ class Dependency(base.Base):
"""Dependency Command Class."""

def execute(self, action_args=None): # type: ignore[no-untyped-def] # noqa: ANN001, ANN101, ANN201, ARG002
"""Execute the actions necessary to perform a `molecule dependency` and \
returns None.
:return: None
""" # noqa: D205
"""Execute the actions necessary to perform a `molecule dependency` and returns None."""
self._config.dependency.execute()


Expand Down
6 changes: 1 addition & 5 deletions src/molecule/command/destroy.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@ class Destroy(base.Base):
"""Destroy Command Class."""

def execute(self, action_args=None): # type: ignore[no-untyped-def] # noqa: ANN001, ANN101, ANN201, ARG002
"""Execute the actions necessary to perform a `molecule destroy` and \
returns None.
:return: None
""" # noqa: D205
"""Execute the actions necessary to perform a `molecule destroy` and returns None."""
if self._config.command_args.get("destroy") == "never":
msg = "Skipping, '--destroy=never' requested."
LOG.warning(msg)
Expand Down
28 changes: 16 additions & 12 deletions src/molecule/command/idempotence.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,7 @@ class Idempotence(base.Base):
"""

def execute(self, action_args=None): # type: ignore[no-untyped-def] # noqa: ANN001, ANN101, ANN201, ARG002
"""Execute the actions necessary to perform a `molecule idempotence` and \
returns None.
:return: None
""" # noqa: D205
"""Execute the actions necessary to perform a `molecule idempotence` and returns None."""
if not self._config.state.converged:
msg = "Instances not converged. Please converge instances first."
util.sysexit_with_message(msg)
Expand All @@ -63,8 +59,11 @@ def execute(self, action_args=None): # type: ignore[no-untyped-def] # noqa: AN
def _is_idempotent(self, output): # type: ignore[no-untyped-def] # noqa: ANN001, ANN101, ANN202
"""Parse the output of the provisioning for changed and returns a bool.
:param output: A string containing the output of the ansible run.
:return: bool
Args:
output: A string containing the output of the ansible run.
Returns:
bool: True if the output is idempotent, False otherwise.
"""
# Remove blank lines to make regex matches easier
output = re.sub(r"\n\s*\n*", "\n", output)
Expand All @@ -81,8 +80,12 @@ def _is_idempotent(self, output): # type: ignore[no-untyped-def] # noqa: ANN00
def _non_idempotent_tasks(self, output): # type: ignore[no-untyped-def] # noqa: ANN001, ANN101, ANN202
"""Parse the output to identify the non idempotent tasks.
:param (str) output: A string containing the output of the ansible run.
:return: A list containing the names of the non idempotent tasks.
Args:
output: A string containing the output of the ansible run.
Returns:
list: A list containing the names of the non idempotent tasks.
"""
# Remove blank lines to make regex matches easier.
output = re.sub(r"\n\s*\n*", "\n", output)
Expand Down Expand Up @@ -115,9 +118,10 @@ def _non_idempotent_tasks(self, output): # type: ignore[no-untyped-def] # noqa
)
@click.argument("ansible_args", nargs=-1, type=click.UNPROCESSED)
def idempotence(ctx, scenario_name, ansible_args): # type: ignore[no-untyped-def] # pragma: no cover # noqa: ANN001, ANN201
"""Use the provisioner to configure the instances and parse the output to \
determine idempotence.
""" # noqa: D205
"""Use the provisioner to configure the instances.
After parse the output to determine idempotence.
"""
args = ctx.obj.get("args")
subcommand = base._get_subcommand(__name__) # type: ignore[no-untyped-call] # noqa: SLF001
command_args = {"subcommand": subcommand}
Expand Down
9 changes: 2 additions & 7 deletions src/molecule/command/init/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@


class Scenario(base.Base):
"""
Scenario Class.
"""Scenario Class.
.. program:: molecule init scenario bar --role-name foo
Expand All @@ -64,11 +63,7 @@ def __init__(self, command_args: dict[str, str]) -> None: # noqa: ANN101
self._command_args = command_args

def execute(self, action_args=None): # type: ignore[no-untyped-def] # noqa: ANN001, ANN101, ANN201, ARG002
"""Execute the actions necessary to perform a `molecule init scenario` and \
returns None.
:return: None
""" # noqa: D205
"""Execute the actions necessary to perform a `molecule init scenario` and returns None."""
scenario_name = self._command_args["scenario_name"]

msg = f"Initializing new scenario {scenario_name}..."
Expand Down
Loading

0 comments on commit f7e0b8d

Please sign in to comment.