extended-data-types 6.2.0__tar.gz → 6.2.2__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.
Files changed (55) hide show
  1. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/CHANGELOG.md +14 -0
  2. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/PKG-INFO +5 -8
  3. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/README.md +2 -2
  4. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/pyproject.toml +4 -10
  5. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/__init__.py +1 -17
  6. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/map_data_type.py +3 -1
  7. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/splitter_utils.py +10 -4
  8. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/stack_utils.py +2 -1
  9. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/type_utils.py +5 -4
  10. extended_data_types-6.2.0/src/extended_data_types/development_integration/__init__.py +0 -6
  11. extended_data_types-6.2.0/src/extended_data_types/development_integration/integration.py +0 -269
  12. extended_data_types-6.2.0/src/extended_data_types/ecosystem_status/__init__.py +0 -6
  13. extended_data_types-6.2.0/src/extended_data_types/ecosystem_status/monitor.py +0 -280
  14. extended_data_types-6.2.0/src/extended_data_types/mcp_server/__init__.py +0 -6
  15. extended_data_types-6.2.0/src/extended_data_types/mcp_server/server.py +0 -303
  16. extended_data_types-6.2.0/src/extended_data_types/package_discovery/__init__.py +0 -6
  17. extended_data_types-6.2.0/src/extended_data_types/package_discovery/discovery.py +0 -61
  18. extended_data_types-6.2.0/src/extended_data_types/release_coordination/__init__.py +0 -6
  19. extended_data_types-6.2.0/src/extended_data_types/release_coordination/coordinator.py +0 -178
  20. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/.gitignore +0 -0
  21. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/examples/README.md +0 -0
  22. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/examples/basic_usage.py +0 -0
  23. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/examples/composed_workflows.py +0 -0
  24. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/examples/file_operations.py +0 -0
  25. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/examples/serialization.py +0 -0
  26. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/examples/string_transformations.py +0 -0
  27. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/project.json +0 -0
  28. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/base64_utils.py +0 -0
  29. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/export_utils.py +0 -0
  30. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/file_data_type.py +0 -0
  31. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/hcl2_utils.py +0 -0
  32. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/import_utils.py +0 -0
  33. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/json_utils.py +0 -0
  34. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/list_data_type.py +0 -0
  35. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/matcher_utils.py +0 -0
  36. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/number_transformations.py +0 -0
  37. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/py.typed +0 -0
  38. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/serialization_utils.py +0 -0
  39. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/state_utils.py +0 -0
  40. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/string_data_type.py +0 -0
  41. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/string_transformations.py +0 -0
  42. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/toml_utils.py +0 -0
  43. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/transformations/__init__.py +0 -0
  44. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/transformations/numbers/__init__.py +0 -0
  45. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/transformations/numbers/notation.py +0 -0
  46. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/transformations/numbers/words.py +0 -0
  47. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/transformations/strings/__init__.py +0 -0
  48. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/transformations/strings/inflection.py +0 -0
  49. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/yaml_utils/__init__.py +0 -0
  50. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/yaml_utils/constructors.py +0 -0
  51. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/yaml_utils/dumpers.py +0 -0
  52. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/yaml_utils/loaders.py +0 -0
  53. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/yaml_utils/representers.py +0 -0
  54. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/yaml_utils/tag_classes.py +0 -0
  55. {extended_data_types-6.2.0 → extended_data_types-6.2.2}/src/extended_data_types/yaml_utils/utils.py +0 -0
@@ -4,6 +4,20 @@
4
4
 
5
5
  <!-- version list -->
6
6
 
7
+ ## [6.2.2](https://github.com/jbcom/extended-data-library/compare/edt-v6.2.1...edt-v6.2.2) (2026-04-16)
8
+
9
+
10
+ ### Bug Fixes
11
+
12
+ * **connectors:** align exports and clean api docs warnings ([#133](https://github.com/jbcom/extended-data-library/issues/133)) ([ea125f8](https://github.com/jbcom/extended-data-library/commit/ea125f8360026c7404f750f636d41345ef682a3f))
13
+
14
+ ## [6.2.1](https://github.com/jbcom/extended-data-library/compare/edt-v6.2.0...edt-v6.2.1) (2026-04-16)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **repo:** remediate dependency alerts and lock drift ([#117](https://github.com/jbcom/extended-data-library/issues/117)) ([664a62d](https://github.com/jbcom/extended-data-library/commit/664a62d1fbb5859206e3bdaf60e4bf4802104fc7))
20
+
7
21
  ## [6.2.0](https://github.com/jbcom/extended-data-library/compare/edt-v6.1.0...edt-v6.2.0) (2026-04-16)
8
22
 
9
23
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: extended-data-types
3
- Version: 6.2.0
3
+ Version: 6.2.2
4
4
  Summary: Extended functionality for data types
5
5
  Project-URL: Documentation, https://extendeddata.dev/core/data-types/
6
6
  Project-URL: Issues, https://github.com/jbcom/extended-data-library/issues
@@ -34,13 +34,10 @@ Requires-Dist: tomlkit>=0.13.2
34
34
  Requires-Dist: validators>=0.22.0
35
35
  Requires-Dist: wrapt>=1.16.0
36
36
  Provides-Extra: docs
37
- Requires-Dist: docutils>=0.17; extra == 'docs'
38
37
  Requires-Dist: myst-parser>=3.0.1; extra == 'docs'
39
- Requires-Dist: sphinx-autodoc-typehints>=2.0.0; extra == 'docs'
40
- Requires-Dist: sphinx-rtd-theme>=2.0.0; extra == 'docs'
38
+ Requires-Dist: sphinx-autodoc2>=0.5.0; extra == 'docs'
39
+ Requires-Dist: sphinx-markdown-builder>=0.6.0; extra == 'docs'
41
40
  Requires-Dist: sphinx>=7.0; extra == 'docs'
42
- Provides-Extra: mcp
43
- Requires-Dist: mcp>=1.0.0; (python_version >= '3.10') and extra == 'mcp'
44
41
  Provides-Extra: tests
45
42
  Requires-Dist: coverage[toml]>=7.6.0; extra == 'tests'
46
43
  Requires-Dist: hypothesis>=6.0.0; extra == 'tests'
@@ -112,8 +109,8 @@ print(hcl_text)
112
109
 
113
110
  ## Contributing
114
111
 
115
- Contributions are welcome. See the shared contributing docs in
116
- [docs/development/contributing.md](https://github.com/jbcom/extended-data-library/blob/main/docs/development/contributing.md).
112
+ Contributions are welcome. See the shared
113
+ [Contributing Guidelines](https://github.com/jbcom/extended-data-library/blob/main/CONTRIBUTING.md).
117
114
 
118
115
  ## Project Links
119
116
 
@@ -55,8 +55,8 @@ print(hcl_text)
55
55
 
56
56
  ## Contributing
57
57
 
58
- Contributions are welcome. See the shared contributing docs in
59
- [docs/development/contributing.md](https://github.com/jbcom/extended-data-library/blob/main/docs/development/contributing.md).
58
+ Contributions are welcome. See the shared
59
+ [Contributing Guidelines](https://github.com/jbcom/extended-data-library/blob/main/CONTRIBUTING.md).
60
60
 
61
61
  ## Project Links
62
62
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "extended-data-types"
7
- version = "6.2.0"
7
+ version = "6.2.2"
8
8
  description = "Extended functionality for data types"
9
9
  requires-python = ">=3.10"
10
10
  license = { text = "MIT" }
@@ -46,7 +46,6 @@ Source = "https://github.com/jbcom/extended-data-library/tree/main/packages/exte
46
46
  Changelog = "https://github.com/jbcom/extended-data-library/blob/main/packages/extended-data-types/CHANGELOG.md"
47
47
 
48
48
  [project.optional-dependencies]
49
- mcp = ["mcp>=1.0.0; python_version >= '3.10'"]
50
49
  tests = [
51
50
  "pytest>=8.2.2",
52
51
  "pytest-asyncio>=0.23.0",
@@ -63,17 +62,13 @@ typing = [
63
62
  ]
64
63
  docs = [
65
64
  "sphinx>=7.0",
66
- "sphinx-rtd-theme>=2.0.0",
67
- "sphinx-autodoc-typehints>=2.0.0",
68
65
  "myst-parser>=3.0.1",
69
- "docutils>=0.17",
66
+ "sphinx-autodoc2>=0.5.0",
67
+ "sphinx-markdown-builder>=0.6.0",
70
68
  ]
71
69
 
72
- [project.scripts]
73
- edt-mcp = "extended_data_types.mcp_server:main"
74
-
75
70
  [tool.hatch.build.targets.sdist]
76
- exclude = [".github", "/.cursor", "/.kiro", "/.ruler", "/docs", "/memory-bank", "/tests", "/tox.ini"]
71
+ exclude = [".github", "/docs", "/tests", "/tox.ini"]
77
72
 
78
73
  [tool.hatch.build.targets.wheel]
79
74
  packages = ["src/extended_data_types"]
@@ -95,7 +90,6 @@ source = ["src/extended_data_types"]
95
90
  branch = true
96
91
  parallel = true
97
92
  source = ["extended_data_types"]
98
- relative_files = true
99
93
 
100
94
  [tool.coverage.xml]
101
95
  output = "coverage.xml"
@@ -8,8 +8,6 @@ lists, maps, and more.
8
8
  from __future__ import annotations
9
9
 
10
10
  from extended_data_types.base64_utils import base64_decode, base64_encode
11
- from extended_data_types.development_integration import DevelopmentIntegration
12
- from extended_data_types.ecosystem_status import EcosystemStatusMonitor
13
11
  from extended_data_types.export_utils import (
14
12
  make_raw_data_export_safe,
15
13
  wrap_raw_data_for_export,
@@ -49,15 +47,6 @@ from extended_data_types.map_data_type import (
49
47
  zipmap,
50
48
  )
51
49
  from extended_data_types.matcher_utils import is_non_empty_match, is_partial_match
52
-
53
-
54
- try:
55
- from extended_data_types.mcp_server import main as mcp_server_main
56
- except ImportError:
57
- mcp_server_main = None # type: ignore[assignment]
58
-
59
- from extended_data_types.package_discovery import EcosystemPackageDiscovery
60
- from extended_data_types.release_coordination import ReleaseCoordinator
61
50
  from extended_data_types.splitter_utils import split_dict_by_type, split_list_by_type
62
51
  from extended_data_types.stack_utils import (
63
52
  filter_methods,
@@ -119,14 +108,10 @@ from extended_data_types.type_utils import (
119
108
  from extended_data_types.yaml_utils import decode_yaml, encode_yaml, is_yaml_data
120
109
 
121
110
 
122
- __version__ = "6.2.0"
111
+ __version__ = "6.2.2"
123
112
 
124
113
  __all__ = [
125
- "DevelopmentIntegration",
126
- "EcosystemPackageDiscovery",
127
- "EcosystemStatusMonitor",
128
114
  "FilePath",
129
- "ReleaseCoordinator",
130
115
  "SortedDefaultDict",
131
116
  "all_non_empty",
132
117
  "all_non_empty_in_dict",
@@ -183,7 +168,6 @@ __all__ = [
183
168
  "make_hashable",
184
169
  "make_raw_data_export_safe",
185
170
  "match_file_extensions",
186
- "mcp_server_main",
187
171
  "ordinalize",
188
172
  "pluralize",
189
173
  "read_file",
@@ -6,6 +6,8 @@ dictionaries, and to convert keys from camelCase to snake_case.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
+ import builtins
10
+
9
11
  from collections import defaultdict
10
12
  from collections.abc import Callable, Mapping, MutableMapping
11
13
  from typing import Any, TypeVar
@@ -296,7 +298,7 @@ class SortedDefaultDict(defaultdict[KT, VT], SortedDict[KT, VT]): # type: ignor
296
298
 
297
299
  def get_default_dict(
298
300
  use_sorted_dict: bool = False,
299
- default_type: type[dict[Any, Any]] = dict,
301
+ default_type: builtins.type[dict[Any, Any]] = dict,
300
302
  levels: int = 2,
301
303
  ) -> defaultdict[str, Any] | Any:
302
304
  """Create a nested `defaultdict` with the specified number of levels.
@@ -10,13 +10,17 @@ Functions:
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ import builtins
14
+
13
15
  from collections import defaultdict
14
16
  from typing import Any
15
17
 
16
18
  from extended_data_types.type_utils import typeof
17
19
 
18
20
 
19
- def split_list_by_type(input_list: list[Any], primitive_only: bool = False) -> defaultdict[type, list[Any]]:
21
+ def split_list_by_type(
22
+ input_list: list[Any], primitive_only: bool = False
23
+ ) -> defaultdict[builtins.type[Any], list[Any]]:
20
24
  """Split a list by the type of its items, with an option to categorize by primitive types only.
21
25
 
22
26
  Args:
@@ -27,13 +31,15 @@ def split_list_by_type(input_list: list[Any], primitive_only: bool = False) -> d
27
31
  Returns:
28
32
  DefaultDict[type, List[Any]]: A defaultdict storing lists of elements categorized by their type.
29
33
  """
30
- result: defaultdict[type, list[Any]] = defaultdict(list)
34
+ result: defaultdict[builtins.type[Any], list[Any]] = defaultdict(list)
31
35
  for item in input_list:
32
36
  result[typeof(item, primitive_only=primitive_only)].append(item)
33
37
  return result
34
38
 
35
39
 
36
- def split_dict_by_type(input_dict: dict[Any, Any], primitive_only: bool = False) -> defaultdict[type, dict[Any, Any]]:
40
+ def split_dict_by_type(
41
+ input_dict: dict[Any, Any], primitive_only: bool = False
42
+ ) -> defaultdict[builtins.type[Any], dict[Any, Any]]:
37
43
  """Split a dictionary by the type of its values, with an option to categorize by primitive types only.
38
44
 
39
45
  Args:
@@ -44,7 +50,7 @@ def split_dict_by_type(input_dict: dict[Any, Any], primitive_only: bool = False)
44
50
  Returns:
45
51
  DefaultDict[type, Dict[Any, Any]]: A defaultdict storing dictionaries of elements categorized by their type.
46
52
  """
47
- result: defaultdict[type, dict[Any, Any]] = defaultdict(dict)
53
+ result: defaultdict[builtins.type[Any], dict[Any, Any]] = defaultdict(dict)
48
54
  for key, value in input_dict.items():
49
55
  result[typeof(value, primitive_only=primitive_only)][key] = value
50
56
  return result
@@ -6,6 +6,7 @@ methods and their docstrings for a class.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
+ import builtins
9
10
  import re
10
11
  import sys
11
12
 
@@ -47,7 +48,7 @@ def filter_methods(methods: list[str]) -> list[str]:
47
48
  return [method for method in methods if not method.startswith("_")]
48
49
 
49
50
 
50
- def get_available_methods(cls: type[Any]) -> dict[str, str | None]:
51
+ def get_available_methods(cls: builtins.type[Any]) -> dict[str, str | None]:
51
52
  """Gets available methods and their docstrings for a class.
52
53
 
53
54
  An "available method" is a public method that:
@@ -31,6 +31,7 @@ Constants:
31
31
 
32
32
  from __future__ import annotations
33
33
 
34
+ import builtins
34
35
  import datetime
35
36
  import os
36
37
  import pathlib
@@ -88,7 +89,7 @@ class ConversionError(ValueError):
88
89
  in different Python versions.
89
90
  """
90
91
 
91
- def __init__(self, expected_type: type, value: Any):
92
+ def __init__(self, expected_type: builtins.type[Any], value: Any):
92
93
  """Initialize the ConversionError with expected type and value.
93
94
 
94
95
  Args:
@@ -311,7 +312,7 @@ def strtotime(val: str, raise_on_error: bool = False) -> datetime.time | None:
311
312
  return None
312
313
 
313
314
 
314
- def get_default_value_for_type(input_type: type) -> Any:
315
+ def get_default_value_for_type(input_type: builtins.type[Any]) -> Any:
315
316
  """Returns the default value for a given type."""
316
317
  if input_type is list:
317
318
  return []
@@ -322,7 +323,7 @@ def get_default_value_for_type(input_type: type) -> Any:
322
323
  return None
323
324
 
324
325
 
325
- def get_primitive_type_for_instance_type(value: Any) -> type:
326
+ def get_primitive_type_for_instance_type(value: Any) -> builtins.type[Any]:
326
327
  """Gets the primitive type for a given value."""
327
328
  if isinstance(value, (bool, int, float, str, bytes, bytearray)):
328
329
  return type(value)
@@ -335,7 +336,7 @@ def get_primitive_type_for_instance_type(value: Any) -> type:
335
336
  return type(None) if value is None else object
336
337
 
337
338
 
338
- def typeof(item: Any, primitive_only: bool = False) -> type:
339
+ def typeof(item: Any, primitive_only: bool = False) -> builtins.type[Any]:
339
340
  """Determines either the primitive or exact type of a given value."""
340
341
  return get_primitive_type_for_instance_type(item) if primitive_only else type(item)
341
342
 
@@ -1,6 +0,0 @@
1
- """Development Integration component."""
2
-
3
- from extended_data_types.development_integration.integration import DevelopmentIntegration
4
-
5
-
6
- __all__ = ["DevelopmentIntegration"]
@@ -1,269 +0,0 @@
1
- """Development Integration component for ecosystem project validation."""
2
-
3
- from __future__ import annotations
4
-
5
- from pathlib import Path
6
- from typing import Any
7
-
8
- import extended_data_types
9
-
10
-
11
- class DevelopmentIntegration:
12
- """Validates and inspects Python projects for ecosystem compliance.
13
-
14
- Checks that projects follow the extended-data-types ecosystem conventions:
15
- hatchling build backend, src layout, tests directory, and proper config.
16
- """
17
-
18
- def __init__(self, project_template_path: Path | None = None) -> None:
19
- """Initialize with optional project template path.
20
-
21
- Args:
22
- project_template_path: Path to template files for project generation.
23
- """
24
- self.project_template_path = project_template_path
25
-
26
- def configure_development_environment(self, project_path: Path) -> dict[str, Any]:
27
- """Validate that a project has the expected config files.
28
-
29
- Checks for pyproject.toml, ruff configuration (pyproject.toml,
30
- ruff.toml, or .ruff.toml), and mypy configuration (pyproject.toml,
31
- mypy.ini, or .mypy.ini).
32
-
33
- Args:
34
- project_path: Root path of the project.
35
-
36
- Returns:
37
- Dict with per-config validation results and overall status.
38
- """
39
- project_path = Path(project_path)
40
- configs: dict[str, dict[str, Any]] = {}
41
-
42
- # Check pyproject.toml
43
- pyproject = project_path / "pyproject.toml"
44
- configs["pyproject_toml"] = {
45
- "found": pyproject.is_file(),
46
- "path": str(pyproject),
47
- }
48
-
49
- # Load tool sections from pyproject.toml (reused for ruff/mypy checks)
50
- tools: dict[str, Any] = {}
51
- if pyproject.is_file():
52
- tools = self._load_tool_section(pyproject)
53
-
54
- # Check ruff config
55
- configs["ruff"] = self._find_ruff_config(project_path, tools)
56
-
57
- # Check mypy config
58
- configs["mypy"] = self._find_mypy_config(project_path, tools)
59
-
60
- all_found = all(cfg.get("found", False) for cfg in configs.values())
61
- issues: list[str] = []
62
- if not configs["pyproject_toml"]["found"]:
63
- issues.append("pyproject.toml not found")
64
- if not configs["ruff"]["found"]:
65
- issues.append("No ruff configuration found")
66
- if not configs["mypy"]["found"]:
67
- issues.append("No mypy configuration found")
68
-
69
- return {
70
- "configured": all_found,
71
- "configs": configs,
72
- "issues": issues,
73
- }
74
-
75
- def validate_project_structure(self, project_path: Path) -> dict[str, Any]:
76
- """Check that a project follows ecosystem conventions.
77
-
78
- Validates:
79
- - pyproject.toml exists with hatchling build backend
80
- - src/ layout is used
81
- - tests/ directory exists
82
- - Proper __init__.py files in src packages
83
-
84
- Args:
85
- project_path: Root path of the project to validate.
86
-
87
- Returns:
88
- Dict with validation results including passed checks and issues.
89
- """
90
- project_path = Path(project_path)
91
- checks: list[dict[str, Any]] = []
92
-
93
- # Check pyproject.toml exists
94
- pyproject = project_path / "pyproject.toml"
95
- checks.append(
96
- {
97
- "name": "pyproject.toml exists",
98
- "passed": pyproject.is_file(),
99
- }
100
- )
101
-
102
- # Check build backend if pyproject.toml exists
103
- if pyproject.is_file():
104
- info = self.get_project_info(project_path)
105
- build_backend = info.get("build_backend", "")
106
- checks.append(
107
- {
108
- "name": "hatchling build backend",
109
- "passed": build_backend.startswith("hatchling"),
110
- }
111
- )
112
-
113
- # Check src layout
114
- src_dir = project_path / "src"
115
- has_src = src_dir.is_dir()
116
- checks.append(
117
- {
118
- "name": "src/ layout",
119
- "passed": has_src,
120
- }
121
- )
122
-
123
- # Check tests directory
124
- tests_dir = project_path / "tests"
125
- checks.append(
126
- {
127
- "name": "tests/ directory",
128
- "passed": tests_dir.is_dir(),
129
- }
130
- )
131
-
132
- # Check __init__.py files in src packages
133
- if has_src:
134
- missing_inits = self._find_packages_missing_init(src_dir)
135
- checks.append(
136
- {
137
- "name": "__init__.py in src packages",
138
- "passed": len(missing_inits) == 0,
139
- "details": missing_inits or None,
140
- }
141
- )
142
-
143
- issues = [c["name"] for c in checks if not c["passed"]]
144
- return {
145
- "valid": len(issues) == 0,
146
- "checks": checks,
147
- "issues": issues,
148
- }
149
-
150
- def get_project_info(self, project_path: Path) -> dict[str, Any]:
151
- """Read pyproject.toml and return project metadata.
152
-
153
- Args:
154
- project_path: Root path of the project.
155
-
156
- Returns:
157
- Dict with project name, version, dependencies, and build backend.
158
- Returns an empty dict if pyproject.toml cannot be read.
159
- """
160
- project_path = Path(project_path)
161
- pyproject = project_path / "pyproject.toml"
162
- if not pyproject.exists():
163
- return {}
164
-
165
- try:
166
- content = extended_data_types.read_file(pyproject)
167
- if not isinstance(content, (str, bytes, bytearray, memoryview)):
168
- return {}
169
- data = extended_data_types.decode_toml(content)
170
- except (OSError, ValueError, TypeError):
171
- return {}
172
-
173
- project = data.get("project", {})
174
- build_system = data.get("build-system", {})
175
-
176
- return {
177
- "name": project.get("name", ""),
178
- "version": project.get("version", ""),
179
- "description": project.get("description", ""),
180
- "dependencies": project.get("dependencies", []),
181
- "optional_dependencies": project.get("optional-dependencies", {}),
182
- "build_backend": build_system.get("build-backend", ""),
183
- "build_requires": build_system.get("requires", []),
184
- "python_requires": project.get("requires-python", ""),
185
- }
186
-
187
- def _load_tool_section(self, pyproject_path: Path) -> dict[str, Any]:
188
- """Load the [tool] section from a pyproject.toml file.
189
-
190
- Args:
191
- pyproject_path: Path to pyproject.toml.
192
-
193
- Returns:
194
- The tool section as a dict, or empty dict on failure.
195
- """
196
- try:
197
- content = extended_data_types.read_file(pyproject_path)
198
- if not isinstance(content, (str, bytes, bytearray, memoryview)):
199
- return {}
200
- data = extended_data_types.decode_toml(content)
201
- return dict(data.get("tool", {}))
202
- except (OSError, ValueError):
203
- return {}
204
-
205
- def _find_ruff_config(self, project_path: Path, tools: dict[str, Any]) -> dict[str, Any]:
206
- """Locate ruff configuration across standard locations.
207
-
208
- Args:
209
- project_path: Root directory of the project.
210
- tools: Pre-loaded [tool] section from pyproject.toml.
211
-
212
- Returns:
213
- Status dict with found flag and source location.
214
- """
215
- if "ruff" in tools:
216
- return {
217
- "found": True,
218
- "source": "pyproject.toml [tool.ruff]",
219
- }
220
- for filename in ("ruff.toml", ".ruff.toml"):
221
- candidate = project_path / filename
222
- if candidate.is_file():
223
- return {"found": True, "source": filename}
224
- return {"found": False, "source": None}
225
-
226
- def _find_mypy_config(self, project_path: Path, tools: dict[str, Any]) -> dict[str, Any]:
227
- """Locate mypy configuration across standard locations.
228
-
229
- Args:
230
- project_path: Root directory of the project.
231
- tools: Pre-loaded [tool] section from pyproject.toml.
232
-
233
- Returns:
234
- Status dict with found flag and source location.
235
- """
236
- if "mypy" in tools:
237
- return {
238
- "found": True,
239
- "source": "pyproject.toml [tool.mypy]",
240
- }
241
- for filename in ("mypy.ini", ".mypy.ini", "setup.cfg"):
242
- candidate = project_path / filename
243
- if candidate.is_file():
244
- if filename == "setup.cfg":
245
- # Only count setup.cfg if it has a [mypy] section
246
- try:
247
- content = extended_data_types.read_file(candidate)
248
- if isinstance(content, str) and "[mypy]" in content:
249
- return {"found": True, "source": "setup.cfg [mypy]"}
250
- except OSError:
251
- continue
252
- else:
253
- return {"found": True, "source": filename}
254
- return {"found": False, "source": None}
255
-
256
- def _find_packages_missing_init(self, src_dir: Path) -> list[str]:
257
- """Find package directories under src/ that lack __init__.py.
258
-
259
- Args:
260
- src_dir: The src/ directory to inspect.
261
-
262
- Returns:
263
- List of directory names missing __init__.py.
264
- """
265
- missing: list[str] = []
266
- for item in sorted(src_dir.iterdir()):
267
- if item.is_dir() and not item.name.startswith((".", "_")) and not (item / "__init__.py").is_file():
268
- missing.append(item.name)
269
- return missing
@@ -1,6 +0,0 @@
1
- """Ecosystem Status component."""
2
-
3
- from extended_data_types.ecosystem_status.monitor import EcosystemStatusMonitor
4
-
5
-
6
- __all__ = ["EcosystemStatusMonitor"]