wexample-wex-addon-dev-python 0.0.63__py3-none-any.whl → 0.1.0__py3-none-any.whl

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.
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING
4
4
 
5
+ from wexample_wex_core.const.globals import COMMAND_TYPE_ADDON
5
6
  from wexample_wex_core.const.middleware import (
6
7
  MIDDLEWARE_OPTION_VALUE_ALLWAYS,
7
8
  MIDDLEWARE_OPTION_VALUE_OPTIONAL,
@@ -32,8 +33,9 @@ if TYPE_CHECKING:
32
33
  show_progress=MIDDLEWARE_OPTION_VALUE_ALLWAYS,
33
34
  )
34
35
  @command(
36
+ type=COMMAND_TYPE_ADDON,
35
37
  description="Check python code on every file: "
36
- "bash cli/wex python::code/check --file ../../pip/wex-core/wexample_wex_core/ -sof"
38
+ "python::code/check --file ../../pip/wex-core/wexample_wex_core/ -sof",
37
39
  )
38
40
  def python__code__check(
39
41
  context: ExecutionContext,
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING
4
4
 
5
+ from wexample_wex_core.const.globals import COMMAND_TYPE_ADDON
5
6
  from wexample_wex_core.decorator.command import command
6
7
  from wexample_wex_core.decorator.middleware import middleware
7
8
  from wexample_wex_core.decorator.option import option
@@ -26,7 +27,7 @@ if TYPE_CHECKING:
26
27
  @middleware(
27
28
  name="each_python_file", should_exist=True, expand_glob=True, recursive=True
28
29
  )
29
- @command()
30
+ @command(type=COMMAND_TYPE_ADDON)
30
31
  def python__code__format(
31
32
  kernel: Kernel,
32
33
  file: str,
@@ -2,13 +2,14 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING
4
4
 
5
+ from wexample_wex_core.const.globals import COMMAND_TYPE_ADDON
5
6
  from wexample_wex_core.decorator.command import command
6
7
 
7
8
  if TYPE_CHECKING:
8
9
  from wexample_wex_core.context.execution_context import ExecutionContext
9
10
 
10
11
 
11
- @command(description="Check python code on every file.")
12
+ @command(type=COMMAND_TYPE_ADDON, description="Check python code on every file.")
12
13
  def python__examples__validate(
13
14
  context: ExecutionContext,
14
15
  ) -> None:
@@ -5,18 +5,20 @@ from typing import TYPE_CHECKING
5
5
  from wexample_filestate.item.file.toml_file import TomlFile
6
6
  from wexample_helpers.decorator.base_class import base_class
7
7
  from wexample_wex_addon_app.const.path import APP_PATH_README
8
+ from wexample_wex_addon_app.item.file.mixin.app_dependencies_config_file_mixin import (
9
+ AppDependenciesConfigFileMixin,
10
+ )
8
11
 
9
12
  if TYPE_CHECKING:
13
+ from packaging.requirements import Requirement
10
14
  from tomlkit import TOMLDocument
11
15
 
12
16
 
13
17
  @base_class
14
- class PythonPyprojectTomlFile(TomlFile):
15
- def add_dependency(
18
+ class PythonPyprojectTomlFile(AppDependenciesConfigFileMixin, TomlFile):
19
+ def add_dependency_from_spec(
16
20
  self,
17
- package_name: str,
18
- version: str,
19
- operator: str = "==",
21
+ spec: Requirement,
20
22
  optional: bool = False,
21
23
  group: None | str = None,
22
24
  ) -> bool:
@@ -24,13 +26,11 @@ class PythonPyprojectTomlFile(TomlFile):
24
26
  from packaging.utils import canonicalize_name
25
27
  from wexample_filestate_python.helpers.toml import toml_sort_string_array
26
28
 
27
- spec = f"{package_name}{operator}{version}"
28
- new_req = Requirement(spec)
29
- new_name = canonicalize_name(new_req.name)
29
+ new_name = canonicalize_name(spec.name)
30
30
 
31
31
  deps = self._get_deps_array(optional=optional, group=group)
32
32
 
33
- # Look for existing dependency
33
+ # Look for existing dependency (string-based)
34
34
  old_spec = next(
35
35
  (d for d in deps if canonicalize_name(Requirement(d).name) == new_name),
36
36
  None,
@@ -40,8 +40,11 @@ class PythonPyprojectTomlFile(TomlFile):
40
40
  if old_spec:
41
41
  deps.remove(old_spec)
42
42
 
43
+ # Convert Requirement → string
44
+ new_spec_str = str(spec)
45
+
43
46
  # Add new version
44
- deps.append(spec)
47
+ deps.append(new_spec_str)
45
48
 
46
49
  # Sort array
47
50
  toml_sort_string_array(deps)
@@ -49,7 +52,23 @@ class PythonPyprojectTomlFile(TomlFile):
49
52
  # Save file
50
53
  self.write_parsed()
51
54
 
52
- return old_spec != spec
55
+ return old_spec != new_spec_str
56
+
57
+ def add_dependency_from_string(
58
+ self,
59
+ package_name: str,
60
+ version: str,
61
+ operator: str = "==",
62
+ optional: bool = False,
63
+ group: None | str = None,
64
+ ) -> bool:
65
+ from packaging.requirements import Requirement
66
+
67
+ return self.add_dependency_from_spec(
68
+ spec=Requirement(f"{package_name}{operator}{version}"),
69
+ optional=optional,
70
+ group=group,
71
+ )
53
72
 
54
73
  def dumps(self, content: TOMLDocument | dict | None = None) -> str:
55
74
  """Serialize a TOMLDocument (preferred) or a plain dict to TOML.
@@ -0,0 +1,8 @@
1
+ publish:
2
+ stage: deploy
3
+ image: python:3.12-slim
4
+ script:
5
+ - pip install pdm --quiet
6
+ - pdm publish --repository "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi" --username gitlab-ci-token --password "${CI_JOB_TOKEN}"
7
+ rules:
8
+ - if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/'
@@ -27,10 +27,34 @@ class PythonPackageWorkdir(PythonWorkdir):
27
27
 
28
28
  def prepare_value(self, raw_value: DictConfig | None = None) -> DictConfig:
29
29
  from wexample_helpers.helpers.array import array_dict_get_by
30
+ from wexample_helpers.helpers.file import file_read
31
+ from wexample_helpers.helpers.module import module_get_path
32
+
33
+ import wexample_wex_addon_dev_python
30
34
 
31
35
  raw_value = super().prepare_value(raw_value=raw_value)
32
36
  children = raw_value.get("children")
33
37
 
38
+ # Add .gitlab-ci.yml for private GitLab registry packages.
39
+ # Both callbacks are evaluated after configure() completes, so base_name
40
+ # and runtime config are fully available at that point.
41
+ children.append(
42
+ {
43
+ "name": ".gitlab-ci.yml",
44
+ "type": DiskItemType.FILE,
45
+ "should_exist": lambda _target, _self=self: bool(
46
+ _self.search_app_or_suite_runtime_config(
47
+ "pdm.repository.url", default=None
48
+ ).get_str_or_none()
49
+ ),
50
+ "content": lambda _: file_read(
51
+ module_get_path(wexample_wex_addon_dev_python)
52
+ / "resources"
53
+ / "package_publish_gitlab.yml"
54
+ ),
55
+ }
56
+ )
57
+
34
58
  children.append(
35
59
  {
36
60
  "name": "examples",
@@ -139,6 +163,42 @@ class PythonPackageWorkdir(PythonWorkdir):
139
163
 
140
164
  return found
141
165
 
166
+ def _classify_version_bump(self, last_tag: str) -> str:
167
+ from wexample_helpers.const.types import (
168
+ UPGRADE_TYPE_INTERMEDIATE,
169
+ UPGRADE_TYPE_MAJOR,
170
+ UPGRADE_TYPE_MINOR,
171
+ )
172
+ from wexample_helpers_git.helpers.git import git_has_changes_since_tag
173
+
174
+ if not git_has_changes_since_tag(last_tag, "src", cwd=self.get_path()):
175
+ return UPGRADE_TYPE_MINOR
176
+
177
+ try:
178
+ import griffe
179
+
180
+ module_name = self.get_package_name().replace("-", "_")
181
+ repo_path = str(self.get_path())
182
+
183
+ previous = griffe.load_git(
184
+ module_name,
185
+ ref=last_tag,
186
+ repo=repo_path,
187
+ search_paths=["src"],
188
+ )
189
+ current = griffe.load(
190
+ module_name,
191
+ search_paths=[str(self.get_path() / "src")],
192
+ )
193
+
194
+ if list(griffe.find_breaking_changes(previous, current)):
195
+ return UPGRADE_TYPE_MAJOR
196
+
197
+ return UPGRADE_TYPE_INTERMEDIATE
198
+
199
+ except Exception:
200
+ return UPGRADE_TYPE_MAJOR
201
+
142
202
  def _collect_suite_dependencies(
143
203
  self,
144
204
  direct_dependencies: list[str],
@@ -164,7 +224,7 @@ class PythonPackageWorkdir(PythonWorkdir):
164
224
  pkg = suite_workdir.get_package(dep_name)
165
225
  if pkg:
166
226
  # Get dependencies of this suite package and recurse
167
- pkg_dependencies = pkg.list_dependencies_names()
227
+ pkg_dependencies = pkg.get_dependencies_versions().keys()
168
228
  collect_recursive(pkg_dependencies)
169
229
 
170
230
  # Start with direct dependencies from pyproject.toml
@@ -180,6 +240,9 @@ class PythonPackageWorkdir(PythonWorkdir):
180
240
 
181
241
  return suite_deps_ordered
182
242
 
243
+ def _get_critical_directories(self) -> list[str]:
244
+ return ["src"]
245
+
183
246
  def _get_readme_content(self) -> ReadmeContentConfigValue | None:
184
247
  from wexample_wex_addon_dev_python.config_value.python_package_readme_config_value import (
185
248
  PythonPackageReadmeContentConfigValue,
@@ -187,7 +250,7 @@ class PythonPackageWorkdir(PythonWorkdir):
187
250
 
188
251
  return PythonPackageReadmeContentConfigValue(workdir=self)
189
252
 
190
- def _get_suite_package_workdir_class(self) -> type[FrameworkPackageSuiteWorkdir]:
253
+ def _get_suite_workdir_class(self) -> type[FrameworkPackageSuiteWorkdir]:
191
254
  from wexample_wex_addon_dev_python.workdir.python_packages_suite_workdir import (
192
255
  PythonPackagesSuiteWorkdir,
193
256
  )
@@ -210,7 +273,9 @@ class PythonPackageWorkdir(PythonWorkdir):
210
273
  # Package is part of a suite that may have a venv configured.
211
274
  if suite_workdir:
212
275
  # Get all dependencies from pyproject.toml
213
- pyproject_toml_dependencies = toml_file.list_dependencies_names()
276
+ pyproject_toml_dependencies = (
277
+ toml_file.get_dependencies_versions().keys()
278
+ )
214
279
 
215
280
  # Get all packages from the suite ordered by dependencies (leaf -> trunk)
216
281
  suite_packages = suite_workdir.get_ordered_packages()
@@ -289,25 +354,131 @@ class PythonPackageWorkdir(PythonWorkdir):
289
354
  def _publish(self, force: bool = False) -> None:
290
355
  from wexample_filestate_python.common.pipy_gateway import PipyGateway
291
356
  from wexample_helpers.helpers.shell import shell_run
357
+ from wexample_helpers_git.helpers.git import (
358
+ git_push_tag,
359
+ git_tag_annotated,
360
+ git_tag_exists,
361
+ )
292
362
 
293
- client = PipyGateway(parent_io_handler=self)
363
+ repository_url = self.search_app_or_suite_runtime_config(
364
+ "pdm.repository.url", default=None
365
+ ).get_str_or_none()
294
366
 
295
367
  package_name = self.get_package_name()
296
368
  version = self.get_project_version()
369
+
370
+ # Private GitLab registry: trigger CI by pushing a git tag
371
+ if repository_url:
372
+ remote = self._get_deployment_remote_name()
373
+ tag = f"v{version}"
374
+ cwd = self.get_path()
375
+
376
+ if git_tag_exists(tag, cwd=cwd, inherit_stdio=False):
377
+ self.log(f"Tag {tag} already exists, skipping creation.")
378
+ else:
379
+ git_tag_annotated(tag, f"Release {tag}", cwd=cwd, inherit_stdio=True)
380
+
381
+ git_push_tag(tag, cwd=cwd, remote=remote, inherit_stdio=True)
382
+ return
383
+
384
+ # TODO: align public PyPI packages with the private registry approach — publish
385
+ # via a GitLab CI pipeline triggered by a git tag rather than running
386
+ # `pdm publish` locally.
387
+ # PyPI public: publish locally
388
+ client = PipyGateway(parent_io_handler=self)
297
389
  if client.package_release_exists(package_name=package_name, version=version):
298
390
  self.warning(
299
391
  f'Trying to publish an existing release for package "{package_name}" version {version}'
300
392
  )
301
- else:
302
- # Map token to PyPI's token-based authentication if provided
303
- username = "__token__"
304
- password = self.get_env_parameter_or_suite_fallback("PIPY_TOKEN")
305
-
306
- # Build the publish command, adding credentials only when given
307
- publish_cmd = ["pdm", "publish"]
308
- if username is not None:
309
- publish_cmd += ["--username", username]
310
- if password is not None:
311
- publish_cmd += ["--password", password]
312
-
313
- shell_run(publish_cmd, inherit_stdio=True, cwd=self.get_path())
393
+ if not force:
394
+ return
395
+
396
+ repository_token = self.search_app_or_suite_runtime_config(
397
+ "pdm.repository.token", default=None
398
+ ).get_str_or_none()
399
+
400
+ repository_username = self.search_app_or_suite_runtime_config(
401
+ "pdm.repository.username", default="__token__"
402
+ ).get_str_or_none()
403
+
404
+ self.subtitle("Publishing to PyPI")
405
+ publish_cmd = ["pdm", "publish"]
406
+
407
+ username = repository_username or "__token__"
408
+ password = repository_token or self.get_env_parameter_or_suite_fallback(
409
+ "PIPY_TOKEN"
410
+ )
411
+
412
+ if username:
413
+ publish_cmd += ["--username", username]
414
+ if password:
415
+ publish_cmd += ["--password", password]
416
+
417
+ shell_run(publish_cmd, inherit_stdio=True, cwd=self.get_path())
418
+
419
+ def _wait_for_registry(self) -> None:
420
+ import time
421
+ import urllib.error
422
+ import urllib.request
423
+
424
+ repository_url = self.search_app_or_suite_runtime_config(
425
+ "pdm.repository.url", default=None
426
+ ).get_str_or_none()
427
+
428
+ if not repository_url:
429
+ return # PyPI public — published locally, no polling needed
430
+
431
+ token = self.search_app_or_suite_runtime_config(
432
+ "pdm.repository.token", default=None
433
+ ).get_str_or_none()
434
+
435
+ username = (
436
+ self.search_app_or_suite_runtime_config(
437
+ "pdm.repository.username", default="__token__"
438
+ ).get_str_or_none()
439
+ or "__token__"
440
+ )
441
+
442
+ package = self.get_package_name()
443
+ version = self.get_project_version()
444
+
445
+ base = repository_url.rstrip("/")
446
+ url = f"{base}/simple/{package}/"
447
+
448
+ max_attempts = 40
449
+ delay = 30.0
450
+
451
+ self.log(f"Waiting for {package}=={version} to appear on registry…")
452
+
453
+ for attempt in range(1, max_attempts + 1):
454
+ try:
455
+ req = urllib.request.Request(url)
456
+ if token:
457
+ import base64
458
+
459
+ credentials = base64.b64encode(
460
+ f"{username}:{token}".encode()
461
+ ).decode()
462
+ req.add_header("Authorization", f"Basic {credentials}")
463
+ with urllib.request.urlopen(req, timeout=10) as resp:
464
+ if resp.status == 200:
465
+ content = resp.read().decode()
466
+ if version in content:
467
+ self.success(f"{package}=={version} is available.")
468
+ return
469
+ except urllib.error.HTTPError as e:
470
+ if e.code != 404:
471
+ raise
472
+ except Exception:
473
+ pass
474
+
475
+ self.log(
476
+ f"Not yet available (attempt {attempt}/{max_attempts}), "
477
+ f"retrying in {int(delay)}s…"
478
+ )
479
+ time.sleep(delay)
480
+
481
+ raise RuntimeError(
482
+ f"Timed out waiting for {package}=={version} on registry after "
483
+ f"{max_attempts * int(delay) // 60} minutes."
484
+ )
@@ -243,15 +243,15 @@ class PythonWorkdir(CodeBaseWorkdir):
243
243
 
244
244
  return raw_value
245
245
 
246
- def save_dependency(self, package_name: str, version: str) -> bool:
247
- """Add or update a dependency with strict version."""
246
+ def save_dependency(
247
+ self, package: CodeBaseWorkdir, version: str, operator: str = "=="
248
+ ) -> bool:
248
249
  config = self.get_app_config_file()
249
- updated = config.add_dependency(package_name=package_name, version=version)
250
-
251
- if updated:
252
- config.write_parsed()
253
-
254
- return updated
250
+ return config.add_dependency_from_string(
251
+ package_name=package.get_package_name(),
252
+ version=version,
253
+ operator=operator,
254
+ )
255
255
 
256
256
  def save_project_config_file(self, config: StructuredData) -> None:
257
257
  """Save the project configuration to pyproject.toml."""
@@ -298,47 +298,6 @@ class PythonWorkdir(CodeBaseWorkdir):
298
298
  if report_path.exists():
299
299
  self.info(f"Report: @path{{{report_path}}}")
300
300
 
301
- def update_dependencies(self, dependencies_map: dict[str, str]) -> None:
302
- """Update dependencies versions based on the provided map.
303
-
304
- Args:
305
- dependencies_map: Dictionary mapping package names to their new versions.
306
- Example: {"wexample-helpers": "0.2.3", "attrs": "23.1.0"}
307
- """
308
- from packaging.requirements import Requirement
309
- from packaging.utils import canonicalize_name
310
-
311
- config_file = self.get_app_config_file()
312
-
313
- # Canonicalize the keys in dependencies_map for consistent matching
314
- canonical_map = {
315
- canonicalize_name(name): version
316
- for name, version in dependencies_map.items()
317
- }
318
-
319
- # Get current dependencies
320
- current_deps = config_file.list_dependencies_names()
321
-
322
- # Update each dependency if it's in the map
323
- for dep_spec in current_deps:
324
- try:
325
- req = Requirement(dep_spec)
326
- canonical_name = canonicalize_name(req.name)
327
-
328
- # If this dependency is in our update map, update it
329
- if canonical_name in canonical_map:
330
- new_version = canonical_map[canonical_name]
331
- # Use add_dependency which handles removal of old version
332
- config_file.add_dependency(
333
- package_name=req.name, version=new_version
334
- )
335
- except Exception:
336
- # Skip unparsable dependencies
337
- continue
338
-
339
- # Save the updated config
340
- config_file.write_parsed()
341
-
342
301
  def _create_init_children_factory(self) -> ChildrenFileFactoryOption:
343
302
  from wexample_filestate.const.disk import DiskItemType
344
303
  from wexample_filestate.const.globals import NAME_PATTERN_NO_LEADING_DOT
@@ -517,7 +476,7 @@ class PythonWorkdir(CodeBaseWorkdir):
517
476
  toml_file = self.get_app_config_file()
518
477
  # Get all dependencies from pyproject.toml
519
478
  python_install_dependencies_in_venv(
520
- venv_path=venv_path, names=toml_file.list_dependencies_names()
479
+ venv_path=venv_path, names=toml_file.get_dependencies_versions().keys()
521
480
  )
522
481
 
523
482
  def _on_test_event(self, event: Event) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wexample-wex-addon-dev-python
3
- Version: 0.0.63
3
+ Version: 0.1.0
4
4
  Summary: Python dev addon for wex
5
5
  Author-Email: weeger <contact@wexample.com>
6
6
  License: MIT
@@ -11,61 +11,36 @@ Project-URL: homepage, https://github.com/wexample/python-wex-dev-python
11
11
  Requires-Python: >=3.10
12
12
  Requires-Dist: attrs>=23.1.0
13
13
  Requires-Dist: cattrs>=23.1.0
14
+ Requires-Dist: griffe>=2.0.2
14
15
  Requires-Dist: networkx
15
16
  Requires-Dist: pylint
16
17
  Requires-Dist: pyright
17
- Requires-Dist: wexample-filestate-python==0.0.58
18
- Requires-Dist: wexample-wex-addon-app==0.0.55
19
- Requires-Dist: wexample-wex-core==6.0.67
18
+ Requires-Dist: wexample-filestate-python>=0.1.0
19
+ Requires-Dist: wexample-wex-addon-app>=1.0.0
20
20
  Provides-Extra: dev
21
21
  Requires-Dist: pytest; extra == "dev"
22
22
  Requires-Dist: pytest-cov; extra == "dev"
23
23
  Description-Content-Type: text/markdown
24
24
 
25
- # wexample-wex-addon-dev-python
25
+ # wex_addon_dev_python
26
26
 
27
- Version: 0.0.63
27
+ Version: 0.1.0
28
28
 
29
29
  Python dev addon for wex
30
30
 
31
31
  ## Table of Contents
32
32
 
33
- - [Status Compatibility](#status-compatibility)
34
- - [Api Reference](#api-reference)
35
33
  - [Tests](#tests)
36
- - [Code Quality](#code-quality)
34
+ - [Suite Integration](#suite-integration)
35
+ - [Dependencies](#dependencies)
37
36
  - [Versioning](#versioning)
38
- - [Changelog](#changelog)
39
- - [Migration Notes](#migration-notes)
40
- - [Roadmap](#roadmap)
41
- - [Security](#security)
42
- - [Privacy](#privacy)
43
- - [Support](#support)
44
- - [Contribution Guidelines](#contribution-guidelines)
45
- - [Maintainers](#maintainers)
46
37
  - [License](#license)
47
- - [Useful Links](#useful-links)
48
38
  - [Suite Integration](#suite-integration)
49
- - [Compatibility Matrix](#compatibility-matrix)
50
- - [Dependencies](#dependencies)
51
39
  - [Suite Signature](#suite-signature)
52
-
53
-
54
- ## Status & Compatibility
55
-
56
- **Maturity**: Production-ready
57
-
58
- **Python Support**: >=3.10
59
-
60
- **OS Support**: Linux, macOS, Windows
61
-
62
- **Status**: Actively maintained
63
-
64
- ## API Reference
65
-
66
- Full API documentation is available in the source code docstrings.
67
-
68
- Key modules and classes are documented with type hints for better IDE support.
40
+ - [Roadmap](#roadmap)
41
+ - [Status Compatibility](#status-compatibility)
42
+ - [Useful Links](#useful-links)
43
+ - [Migration Notes](#migration-notes)
69
44
 
70
45
  ## Tests
71
46
 
@@ -116,16 +91,26 @@ To enforce a minimum coverage percentage:
116
91
 
117
92
  This will cause the test suite to fail if coverage drops below 80%.
118
93
 
119
- ## Code Quality & Typing
94
+ ## Integration in the Suite
120
95
 
121
- All the suite packages follow strict quality standards:
96
+ This package is part of the Wexample Suite a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
122
97
 
123
- - **Type hints**: Full type coverage with mypy validation
124
- - **Code formatting**: Enforced with black and isort
125
- - **Linting**: Comprehensive checks with custom scripts and tools
126
- - **Testing**: High test coverage requirements
98
+ ### Related Packages
127
99
 
128
- These standards ensure reliability and maintainability across the suite.
100
+ The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
101
+
102
+ Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
103
+
104
+ ## Dependencies
105
+
106
+ - attrs: >=23.1.0
107
+ - cattrs: >=23.1.0
108
+ - griffe: >=2.0.2
109
+ - networkx:
110
+ - pylint:
111
+ - pyright:
112
+ - wexample-filestate-python: >=0.1.0
113
+ - wexample-wex-addon-app: >=1.0.0
129
114
 
130
115
  ## Versioning & Compatibility Policy
131
116
 
@@ -137,72 +122,45 @@ Wexample packages follow **Semantic Versioning** (SemVer):
137
122
 
138
123
  We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
139
124
 
140
- ## Changelog
141
-
142
- See [CHANGELOG.md](CHANGELOG.md) for detailed version history and release notes.
143
-
144
- Major changes are documented with migration guides when applicable.
145
-
146
- ## Migration Notes
147
-
148
- When upgrading between major versions, refer to the migration guides in the documentation.
149
-
150
- Breaking changes are clearly documented with upgrade paths and examples.
151
-
152
- ## Known Limitations & Roadmap
153
-
154
- Current limitations and planned features are tracked in the GitHub issues.
155
-
156
- See the [project roadmap](https://github.com/wexample/python-wex_addon_dev_python/issues) for upcoming features and improvements.
157
-
158
- ## Security Policy
159
-
160
- ### Reporting Vulnerabilities
125
+ ## License
161
126
 
162
- If you discover a security vulnerability, please email contact@wexample.com.
127
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
163
128
 
164
- **Do not** open public issues for security vulnerabilities.
129
+ Free to use in both personal and commercial projects.
165
130
 
166
- We take security seriously and will respond promptly to verified reports.
131
+ ## Integration in the Suite
167
132
 
168
- ## Privacy & Telemetry
133
+ This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
169
134
 
170
- This package does **not** collect any telemetry or usage data.
135
+ ### Related Packages
171
136
 
172
- Your privacy is respected no data is transmitted to external services.
137
+ The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
173
138
 
174
- ## Support Channels
139
+ Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
175
140
 
176
- - **GitHub Issues**: Bug reports and feature requests
177
- - **GitHub Discussions**: Questions and community support
178
- - **Documentation**: Comprehensive guides and API reference
179
- - **Email**: contact@wexample.com for general inquiries
141
+ # About us
180
142
 
181
- Community support is available through GitHub Discussions.
143
+ [Wexample](https://wexample.com) stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
182
144
 
183
- ## Contribution Guidelines
145
+ This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
184
146
 
185
- We welcome contributions to the Wexample suite!
147
+ Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
186
148
 
187
- ### How to Contribute
149
+ ## Known Limitations & Roadmap
188
150
 
189
- 1. **Fork** the repository
190
- 2. **Create** a feature branch
191
- 3. **Make** your changes
192
- 4. **Test** thoroughly
193
- 5. **Submit** a pull request
151
+ Current limitations and planned features are tracked in the GitHub issues.
194
152
 
195
- ## Maintainers & Authors
153
+ See the [project roadmap](https://github.com/wexample/python-wex_addon_dev_python/issues) for upcoming features and improvements.
196
154
 
197
- Maintained by the Wexample team and community contributors.
155
+ ## Status & Compatibility
198
156
 
199
- See [CONTRIBUTORS.md](CONTRIBUTORS.md) for the full list of contributors.
157
+ **Maturity**: Production-ready
200
158
 
201
- ## License
159
+ **Python Support**: >=3.10
202
160
 
203
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
161
+ **OS Support**: Linux, macOS, Windows
204
162
 
205
- Free to use in both personal and commercial projects.
163
+ **Status**: Actively maintained
206
164
 
207
165
  ## Useful Links
208
166
 
@@ -210,41 +168,10 @@ Free to use in both personal and commercial projects.
210
168
  - **Documentation**: [docs.wexample.com](https://docs.wexample.com)
211
169
  - **Issue Tracker**: https://github.com/wexample/python-wex-addon-dev-python/issues
212
170
  - **Discussions**: https://github.com/wexample/python-wex-addon-dev-python/discussions
213
- - **PyPI**: [pypi.org/project/wexample-wex-addon-dev-python](https://pypi.org/project/wexample-wex-addon-dev-python/)
214
-
215
- ## Integration in the Suite
216
-
217
- This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
171
+ - **PyPI**: [pypi.org/project/wex_addon_dev_python](https://pypi.org/project/wex_addon_dev_python/)
218
172
 
219
- ### Related Packages
220
-
221
- The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
222
-
223
- Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
224
-
225
- ## Compatibility Matrix
226
-
227
- This package is part of the Wexample suite and is compatible with other suite packages.
228
-
229
- Refer to each package's documentation for specific version compatibility requirements.
230
-
231
- ## Dependencies
232
-
233
- - attrs: >=23.1.0
234
- - cattrs: >=23.1.0
235
- - networkx:
236
- - pylint:
237
- - pyright:
238
- - wexample-filestate-python: ==0.0.58
239
- - wexample-wex-addon-app: ==0.0.55
240
- - wexample-wex-core: ==6.0.67
241
-
242
-
243
- # About us
244
-
245
- [Wexample](https://wexample.com) stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
246
-
247
- This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
173
+ ## Migration Notes
248
174
 
249
- Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
175
+ When upgrading between major versions, refer to the migration guides in the documentation.
250
176
 
177
+ Breaking changes are clearly documented with upgrade paths and examples.
@@ -1,23 +1,23 @@
1
- wexample_wex_addon_dev_python-0.0.63.dist-info/METADATA,sha256=PLQFvaRQQdEWjXJqFeaka-gjx7ip9AJwkVG1yVnEqJM,8124
2
- wexample_wex_addon_dev_python-0.0.63.dist-info/WHEEL,sha256=tsUv_t7BDeJeRHaSrczbGeuK-TtDpGsWi_JfpzD255I,90
3
- wexample_wex_addon_dev_python-0.0.63.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
1
+ wexample_wex_addon_dev_python-0.1.0.dist-info/METADATA,sha256=Fc49_n_IPbkQvqXpmsXHCGnZL5WqcwMiuDcYJIOmIVQ,6259
2
+ wexample_wex_addon_dev_python-0.1.0.dist-info/WHEEL,sha256=Z36eTX6lG3PITRleSd5hAZHCcz52yg3c0JQVxKBbLW0,90
3
+ wexample_wex_addon_dev_python-0.1.0.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
4
4
  wexample_wex_addon_dev_python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  wexample_wex_addon_dev_python/__pycache__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  wexample_wex_addon_dev_python/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  wexample_wex_addon_dev_python/commands/code/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- wexample_wex_addon_dev_python/commands/code/check.py,sha256=wCL9KM64kCJ76OaxVDus7fjqiEhtLI8jUHFtSLG89u4,3324
8
+ wexample_wex_addon_dev_python/commands/code/check.py,sha256=Bm5ON0UA7QmFTfO70QkfkqjzpGJu3fAw3tQjzdxbW7I,3404
9
9
  wexample_wex_addon_dev_python/commands/code/check/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  wexample_wex_addon_dev_python/commands/code/check/mypy.py,sha256=hZ1taOAofaFgqhtbHLXA14-4cFkVcw6QUi9PmpbEKuk,1401
11
11
  wexample_wex_addon_dev_python/commands/code/check/pylint.py,sha256=cSnirIVrMH9-_ETAiIVdjCvHQWcNJzCwwAfvcxNBodM,3328
12
12
  wexample_wex_addon_dev_python/commands/code/check/pyright.py,sha256=jCKZxQ5Ln2Vh1QlhKqz3i0djnQwWbNHzDcttu41jhsI,3619
13
- wexample_wex_addon_dev_python/commands/code/format.py,sha256=7Xep5RCgbt_JNKM9FROipuEFYfXojJjJDRNRKfqTkoM,2444
13
+ wexample_wex_addon_dev_python/commands/code/format.py,sha256=7HnXLl2-b_ZYsuj45wDr1ue9AL7g7gOo12fLkV1dilE,2530
14
14
  wexample_wex_addon_dev_python/commands/code/format/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
15
15
  wexample_wex_addon_dev_python/commands/code/format/black.py,sha256=wo3BEODFD6BUrmnfheESMyLppLPwtvcgkOVfvHWdAZs,1462
16
16
  wexample_wex_addon_dev_python/commands/code/format/isort.py,sha256=pRYYPZWFza6e_HgKYpYplzV5hwJvbM3NNJ_-A3x1yV8,1540
17
17
  wexample_wex_addon_dev_python/commands/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  wexample_wex_addon_dev_python/commands/examples/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  wexample_wex_addon_dev_python/commands/examples/utils/some_example_type.py,sha256=zusGlLOLkt2EpPFk38FIRA6d_5Q92Y7-TLj8ofHhQk0,121
20
- wexample_wex_addon_dev_python/commands/examples/validate.py,sha256=jHiWkEtETkVSYJKuvUJRNqd9Ag81z3sPdUbX6FUpEng,664
20
+ wexample_wex_addon_dev_python/commands/examples/validate.py,sha256=IgUHNpkdc_Z76HGDWmCvztP7B3ars0Cu2Yknq9MGt0o,752
21
21
  wexample_wex_addon_dev_python/commands/release/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  wexample_wex_addon_dev_python/config_value/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  wexample_wex_addon_dev_python/config_value/__pycache__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -29,18 +29,19 @@ wexample_wex_addon_dev_python/const/python.py,sha256=jxdPt5CnD0dcp4SmobEc_c7XcCk
29
29
  wexample_wex_addon_dev_python/file/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
30
  wexample_wex_addon_dev_python/file/__pycache__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  wexample_wex_addon_dev_python/file/python_app_iml_file.py,sha256=l6YHEILxSGFjOvYWY20zIyAODjOIfuyHsuCfSMw0jVE,1201
32
- wexample_wex_addon_dev_python/file/python_pyproject_toml_file.py,sha256=GM89r1ZwN88MUMysItqlIrPCN-r-Rc9hvahRMjA2Ny0,15323
32
+ wexample_wex_addon_dev_python/file/python_pyproject_toml_file.py,sha256=31KcRaewYzK1mHYFLSltyZ9WhuEzV98I5vllmmGWGkU,15952
33
33
  wexample_wex_addon_dev_python/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  wexample_wex_addon_dev_python/middleware/__pycache__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  wexample_wex_addon_dev_python/middleware/each_python_file_middleware.py,sha256=UzNEpedCYf31aNONFl0SuSJnoXRzhJhgEiTCaPark6E,2311
36
36
  wexample_wex_addon_dev_python/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  wexample_wex_addon_dev_python/python_addon_manager.py,sha256=Mmr9F5lOS2gbb8JTB4-vTri4Qn5Cd2Jukjk7uiTr1Hs,582
38
38
  wexample_wex_addon_dev_python/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
+ wexample_wex_addon_dev_python/resources/package_publish_gitlab.yml,sha256=WVMj-DeFedQak5s5FraEnM1Rx1-ut4KgPodvAVv25ZM,304
39
40
  wexample_wex_addon_dev_python/resources/readme_templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
41
  wexample_wex_addon_dev_python/resources/readme_templates/tests.md.j2,sha256=tKLcDwx7jhQkryXIxWr12AK-hKEaP6Rusu2MrluiABs,1289
41
42
  wexample_wex_addon_dev_python/workdir/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
43
  wexample_wex_addon_dev_python/workdir/__pycache__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- wexample_wex_addon_dev_python/workdir/python_package_workdir.py,sha256=djUfgI1MCn9KOgYCYiwFIpZaGQ28spaiOz6t8gL6FoA,11780
44
+ wexample_wex_addon_dev_python/workdir/python_package_workdir.py,sha256=Fd2A7Qpsy_jstE4zj6AD4PPbMSOGkoBibhCFLDAZrXo,17637
44
45
  wexample_wex_addon_dev_python/workdir/python_packages_suite_workdir.py,sha256=ICHHewLpsXiheYzGDEahphBryH98ZVezWzSAy6A5w5I,2874
45
- wexample_wex_addon_dev_python/workdir/python_workdir.py,sha256=ERpSw5qti1NmHiufOix6bS5lW2vIvclr82SKwlWOhKk,19681
46
- wexample_wex_addon_dev_python-0.0.63.dist-info/RECORD,,
46
+ wexample_wex_addon_dev_python/workdir/python_workdir.py,sha256=tx6UcaBHnrq9khQ6ndG14BzFPNOlqhl-626iNoL6T1o,18078
47
+ wexample_wex_addon_dev_python-0.1.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: pdm-backend (2.4.6)
2
+ Generator: pdm-backend (2.4.8)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any