invoke-tasklib 0.0.3a0__tar.gz → 0.0.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: invoke-tasklib
3
- Version: 0.0.3a0
3
+ Version: 0.0.6
4
4
  Summary: Reusable Invoke tasks shared across Python projects.
5
5
  Project-URL: Homepage, https://github.com/durandtibo/invoke-tasklib
6
6
  Project-URL: Repository, https://github.com/durandtibo/invoke-tasklib
@@ -154,6 +154,7 @@ Tasks are grouped into namespaces, one per module. Each task either
154
154
  | `format` | `format.fix-shell` | Format shell scripts with shfmt | ✅ |
155
155
  | `lint` | `lint.check-lint` | Check linting with ruff | ❌ |
156
156
  | `lint` | `lint.fix` | Fix auto-fixable linting issues with ruff | ✅ |
157
+ | `imports` | `imports.check-cycles` | Check for cyclic import dependencies | ❌ |
157
158
  | `types` | `types.check` | Check type hints with pyright | ❌ |
158
159
  | `test` | `test.doctest` | Run doctests on source code and markdown files | ❌ |
159
160
  | `test` | `test.doctest-src` | Run doctests on source code | ❌ |
@@ -126,6 +126,7 @@ Tasks are grouped into namespaces, one per module. Each task either
126
126
  | `format` | `format.fix-shell` | Format shell scripts with shfmt | ✅ |
127
127
  | `lint` | `lint.check-lint` | Check linting with ruff | ❌ |
128
128
  | `lint` | `lint.fix` | Fix auto-fixable linting issues with ruff | ✅ |
129
+ | `imports` | `imports.check-cycles` | Check for cyclic import dependencies | ❌ |
129
130
  | `types` | `types.check` | Check type hints with pyright | ❌ |
130
131
  | `test` | `test.doctest` | Run doctests on source code and markdown files | ❌ |
131
132
  | `test` | `test.doctest-src` | Run doctests on source code | ❌ |
@@ -28,6 +28,7 @@ from invoke_tasklib import (
28
28
  doc,
29
29
  env,
30
30
  format, # noqa: A004
31
+ imports,
31
32
  lint,
32
33
  release,
33
34
  security,
@@ -40,6 +41,7 @@ __all__ = [
40
41
  "doc",
41
42
  "env",
42
43
  "format",
44
+ "imports",
43
45
  "lint",
44
46
  "ns",
45
47
  "release",
@@ -51,6 +53,7 @@ __all__ = [
51
53
  ns: Collection = Collection()
52
54
  ns.add_collection(Collection.from_module(format), name="format")
53
55
  ns.add_collection(Collection.from_module(lint), name="lint")
56
+ ns.add_collection(Collection.from_module(imports), name="imports")
54
57
  ns.add_collection(Collection.from_module(types), name="types")
55
58
  ns.add_collection(Collection.from_module(test), name="test")
56
59
  ns.add_collection(Collection.from_module(env), name="env")
@@ -0,0 +1,47 @@
1
+ r"""Import-graph tasks."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import shlex
7
+ from typing import TYPE_CHECKING
8
+
9
+ from invoke.tasks import task
10
+
11
+ from invoke_tasklib.config import get_config
12
+
13
+ if TYPE_CHECKING:
14
+ from invoke.context import Context
15
+
16
+ logger: logging.Logger = logging.getLogger(__name__)
17
+
18
+
19
+ @task
20
+ def check_cycles(c: Context) -> None:
21
+ r"""Check for cyclic import dependencies by importing each subpackage
22
+ in isolation.
23
+
24
+ Subpackages are discovered dynamically instead of relying on a hand-
25
+ maintained list, so newly added subpackages are automatically
26
+ covered.
27
+ """
28
+ cfg = get_config(c)
29
+ name = cfg["package"]["name"]
30
+ logger.info(f"🔍 Discovering subpackages of {name}...")
31
+ discover_script = (
32
+ "import importlib, pkgutil, sys\n"
33
+ "name = sys.argv[1]\n"
34
+ "package = importlib.import_module(name)\n"
35
+ "names = [name] + sorted(\n"
36
+ " n for _, n, ispkg in pkgutil.walk_packages(package.__path__, prefix=f'{name}.')\n"
37
+ " if ispkg\n"
38
+ ")\n"
39
+ "print('\\n'.join(names))\n"
40
+ )
41
+ discover = c.run(f"python -c {shlex.quote(discover_script)} {name}", hide=True)
42
+ modules = [line for line in discover.stdout.splitlines() if line]
43
+ logger.info(f"🔍 Checking {len(modules)} module(s) for cyclic imports...")
44
+ for module in modules:
45
+ logger.info(f"🔍 Checking: {module}")
46
+ c.run(f"python -c {shlex.quote(f'import {module}')}", pty=True)
47
+ logger.info(f"✅ All {len(modules)} module(s) imported without cyclic dependency errors")
@@ -10,7 +10,7 @@ only-include = ["src"]
10
10
 
11
11
  [project]
12
12
  name = "invoke-tasklib"
13
- version = "0.0.3a0"
13
+ version = "0.0.6"
14
14
  description = "Reusable Invoke tasks shared across Python projects."
15
15
  readme = "README.md"
16
16
  authors = [
File without changes