apexcodexpy 0.4.2__tar.gz → 0.4.4__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,16 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apexcodexpy
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: The Non-Destructive Configuration Steward for Python Projects.
5
5
  License-File: LICENSE
6
6
  Author: Apex Dev
7
7
  Author-email: dev@apex.ge
8
- Requires-Python: >=3.11
8
+ Requires-Python: >=3.11,<4
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Programming Language :: Python :: 3.11
11
11
  Classifier: Programming Language :: Python :: 3.12
12
12
  Classifier: Programming Language :: Python :: 3.13
13
13
  Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Dist: deptry
14
15
  Requires-Dist: mypy
15
16
  Requires-Dist: pyyaml
16
17
  Requires-Dist: ruff
@@ -62,8 +62,13 @@ class Command:
62
62
  return self
63
63
 
64
64
  def append(self, argument: Any) -> Command:
65
- if argument is not None:
66
- self._arguments.extend(str(argument).split())
65
+ match argument:
66
+ case None:
67
+ pass
68
+ case str(text) if not text.startswith("'"):
69
+ self._arguments.extend(argument.split())
70
+ case _:
71
+ self._arguments.append(str(argument))
67
72
 
68
73
  return self
69
74
 
@@ -72,9 +77,7 @@ class Command:
72
77
 
73
78
  def __iter__(self) -> Iterator[str]:
74
79
  yield from self.name.split()
75
-
76
- for argument in self._arguments:
77
- yield from str(argument).split()
80
+ yield from self._arguments
78
81
 
79
82
 
80
83
  class Executable(Protocol):
@@ -7,6 +7,23 @@ from codex.infra.result import Reporter
7
7
  from codex.infra.typer.device import TyperDevice
8
8
 
9
9
 
10
+ @dataclass(frozen=True)
11
+ class SimpleReporter:
12
+ device: _Device = field(default_factory=TyperDevice)
13
+
14
+ def success_of(self, name: str) -> None:
15
+ pass
16
+
17
+ def failure_of(self, name: str) -> None:
18
+ pass
19
+
20
+ def out(self, message: str) -> None:
21
+ self.device.echo(message)
22
+
23
+ def error(self, message: str) -> None:
24
+ self.device.echo(message)
25
+
26
+
10
27
  @dataclass(frozen=True)
11
28
  class DefaultReporter:
12
29
  device: _Device = field(default_factory=TyperDevice)
@@ -6,8 +6,17 @@ from time import time
6
6
 
7
7
  from codex.infra.program import Command, Executable, MultiProgram, Program
8
8
  from codex.infra.pyproject import PyProjectToml
9
- from codex.infra.result import TaskResult
10
- from codex.infra.tools import MyPy, Pip, Poetry, PoetryRun, Pytest, Ruff
9
+ from codex.infra.result import ProgramResult, TaskResult
10
+ from codex.infra.tools import (
11
+ Deptry,
12
+ MyPy,
13
+ Pip,
14
+ Poetry,
15
+ PoetryRun,
16
+ Pytest,
17
+ Ruff,
18
+ Version,
19
+ )
11
20
  from codex.infra.workflows import CheckCodeWorkflow, DependabotWorkflow
12
21
 
13
22
 
@@ -25,6 +34,10 @@ class Codex:
25
34
 
26
35
  return self
27
36
 
37
+ @staticmethod
38
+ def version() -> TaskResult:
39
+ return ProgramResult(name="version").success(message=str(Version()))
40
+
28
41
  def sync(self) -> TaskResult:
29
42
  return self.tools.sync().execute()
30
43
 
@@ -143,6 +156,12 @@ class CodexTools:
143
156
  command=Ruff(on=self.target).format().flag(check=True),
144
157
  )
145
158
  )
159
+ .attach(
160
+ Program(
161
+ name="dependencies",
162
+ command=Deptry(on=self.target).lint(),
163
+ )
164
+ )
146
165
  .attach(
147
166
  Program(
148
167
  name="ruff",
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass, field
4
+ from importlib import metadata
4
5
  from pathlib import Path
5
6
 
6
7
  from codex.infra.program import (
@@ -98,6 +99,14 @@ class Ruff:
98
99
  return Command("ruff format").append(self.on)
99
100
 
100
101
 
102
+ @dataclass(frozen=True, kw_only=True)
103
+ class Deptry:
104
+ on: Path
105
+
106
+ def lint(self) -> Command:
107
+ return Command("deptry").append(self.on).append("||").append("True")
108
+
109
+
101
110
  @dataclass(frozen=True, kw_only=True)
102
111
  class MyPy:
103
112
  on: Path
@@ -116,3 +125,19 @@ class Pytest:
116
125
 
117
126
  def run(self) -> Command:
118
127
  return Command("pytest").append(self.target)
128
+
129
+
130
+ @dataclass(frozen=True)
131
+ class Version:
132
+ @staticmethod
133
+ def of(package: str) -> str | None:
134
+ try:
135
+ return metadata.version(package)
136
+ except metadata.PackageNotFoundError:
137
+ return None
138
+
139
+ def is_installed(self, package: str) -> bool:
140
+ return self.of(package) is not None
141
+
142
+ def __str__(self) -> str:
143
+ return self.of("apexcodexpy") or "unknown"
@@ -2,12 +2,20 @@ from pathlib import Path
2
2
 
3
3
  import typer
4
4
 
5
- from codex.infra.reporters import DefaultReporter
5
+ from codex.infra.reporters import DefaultReporter, SimpleReporter
6
6
  from codex.infra.service import Codex, Git
7
7
 
8
8
  cli = typer.Typer(no_args_is_help=True)
9
9
 
10
10
 
11
+ @cli.command(
12
+ name="version",
13
+ help="Show the codex version and exit.",
14
+ )
15
+ def _() -> None:
16
+ Codex.version().report(using=SimpleReporter()).exit(using=typer.Exit)
17
+
18
+
11
19
  @cli.command(
12
20
  name="sync",
13
21
  help="Inject standards into pyproject TOML file.",
@@ -13,6 +13,7 @@ from yaml import MappingNode
13
13
 
14
14
  from codex.infra.program import Executable
15
15
  from codex.infra.result import ProgramResult
16
+ from codex.infra.tools import Version
16
17
 
17
18
 
18
19
  @dataclass(frozen=True, kw_only=True)
@@ -90,8 +91,16 @@ class CheckCodeWorkflow(YamlWorkflow):
90
91
  "jobs": self._jobs(
91
92
  lint="codex lint --ci",
92
93
  test_unit="codex test unit --ci",
93
- test_integration="codex test integration --ci",
94
- test_behaviour="codex test behaviour --ci",
94
+ test_integration=(
95
+ "codex test integration --ci"
96
+ if Version().is_installed("pytest-docker")
97
+ else ""
98
+ ),
99
+ test_behaviour=(
100
+ "codex test behaviour --ci"
101
+ if Version().is_installed("behave")
102
+ else ""
103
+ ),
95
104
  ),
96
105
  }
97
106
 
@@ -109,6 +118,7 @@ class CheckCodeWorkflow(YamlWorkflow):
109
118
  ],
110
119
  }
111
120
  for name, value in commands.items()
121
+ if value
112
122
  }
113
123
 
114
124
  @cached_property
@@ -122,7 +132,7 @@ class CheckCodeWorkflow(YamlWorkflow):
122
132
  "uses": "actions/setup-python@v6",
123
133
  "with": {
124
134
  "python-version": self.python_version,
125
- "pip-install": "apexcodexpy",
135
+ "pip-install": f"apexcodexpy=={Version()}",
126
136
  },
127
137
  }
128
138
 
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "apexcodexpy"
3
- version = "0.4.2"
3
+ version = "0.4.4"
4
4
  description = "The Non-Destructive Configuration Steward for Python Projects."
5
5
  readme = "README.md"
6
6
  authors = [
7
7
  { name = "Apex Dev", email = "dev@apex.ge" }
8
8
  ]
9
9
  dynamic = ["dependencies"]
10
- requires-python = ">=3.11"
10
+ requires-python = ">=3.11,<4"
11
11
 
12
12
  [project.scripts]
13
13
  codex = "codex.runner:cli"
@@ -23,6 +23,7 @@ tomlkit = "*"
23
23
  mypy = "*"
24
24
  ruff = "*"
25
25
  pyyaml = "*"
26
+ deptry = "*"
26
27
 
27
28
  [tool.poetry.group.dev.dependencies]
28
29
  behave = "*"
@@ -61,6 +62,13 @@ select = [
61
62
  [tool.ruff.lint.mccabe]
62
63
  max-complexity = 10
63
64
 
65
+ [tool.deptry.per_rule_ignores]
66
+ DEP002 = [
67
+ "mypy",
68
+ "ruff",
69
+ "deptry",
70
+ ]
71
+
64
72
  [tool.coverage.run]
65
73
  branch = true
66
74
  source = [
File without changes
File without changes
File without changes