pyrig 2.2.6__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.
Files changed (102) hide show
  1. pyrig/__init__.py +1 -0
  2. pyrig/dev/__init__.py +6 -0
  3. pyrig/dev/builders/__init__.py +1 -0
  4. pyrig/dev/builders/base/__init__.py +5 -0
  5. pyrig/dev/builders/base/base.py +256 -0
  6. pyrig/dev/builders/pyinstaller.py +229 -0
  7. pyrig/dev/cli/__init__.py +5 -0
  8. pyrig/dev/cli/cli.py +95 -0
  9. pyrig/dev/cli/commands/__init__.py +1 -0
  10. pyrig/dev/cli/commands/build_artifacts.py +16 -0
  11. pyrig/dev/cli/commands/create_root.py +25 -0
  12. pyrig/dev/cli/commands/create_tests.py +244 -0
  13. pyrig/dev/cli/commands/init_project.py +160 -0
  14. pyrig/dev/cli/commands/make_inits.py +27 -0
  15. pyrig/dev/cli/commands/protect_repo.py +145 -0
  16. pyrig/dev/cli/shared_subcommands.py +20 -0
  17. pyrig/dev/cli/subcommands.py +73 -0
  18. pyrig/dev/configs/__init__.py +1 -0
  19. pyrig/dev/configs/base/__init__.py +5 -0
  20. pyrig/dev/configs/base/base.py +826 -0
  21. pyrig/dev/configs/containers/__init__.py +1 -0
  22. pyrig/dev/configs/containers/container_file.py +111 -0
  23. pyrig/dev/configs/dot_env.py +95 -0
  24. pyrig/dev/configs/dot_python_version.py +88 -0
  25. pyrig/dev/configs/git/__init__.py +5 -0
  26. pyrig/dev/configs/git/gitignore.py +181 -0
  27. pyrig/dev/configs/git/pre_commit.py +170 -0
  28. pyrig/dev/configs/licence.py +112 -0
  29. pyrig/dev/configs/markdown/__init__.py +1 -0
  30. pyrig/dev/configs/markdown/docs/__init__.py +1 -0
  31. pyrig/dev/configs/markdown/docs/index.py +38 -0
  32. pyrig/dev/configs/markdown/readme.py +132 -0
  33. pyrig/dev/configs/py_typed.py +28 -0
  34. pyrig/dev/configs/pyproject.py +436 -0
  35. pyrig/dev/configs/python/__init__.py +5 -0
  36. pyrig/dev/configs/python/builders_init.py +27 -0
  37. pyrig/dev/configs/python/configs_init.py +28 -0
  38. pyrig/dev/configs/python/dot_experiment.py +46 -0
  39. pyrig/dev/configs/python/main.py +59 -0
  40. pyrig/dev/configs/python/resources_init.py +27 -0
  41. pyrig/dev/configs/python/shared_subcommands.py +29 -0
  42. pyrig/dev/configs/python/src_init.py +27 -0
  43. pyrig/dev/configs/python/subcommands.py +27 -0
  44. pyrig/dev/configs/testing/__init__.py +5 -0
  45. pyrig/dev/configs/testing/conftest.py +64 -0
  46. pyrig/dev/configs/testing/fixtures_init.py +27 -0
  47. pyrig/dev/configs/testing/main_test.py +74 -0
  48. pyrig/dev/configs/testing/zero_test.py +43 -0
  49. pyrig/dev/configs/workflows/__init__.py +5 -0
  50. pyrig/dev/configs/workflows/base/__init__.py +5 -0
  51. pyrig/dev/configs/workflows/base/base.py +1662 -0
  52. pyrig/dev/configs/workflows/build.py +106 -0
  53. pyrig/dev/configs/workflows/health_check.py +133 -0
  54. pyrig/dev/configs/workflows/publish.py +68 -0
  55. pyrig/dev/configs/workflows/release.py +90 -0
  56. pyrig/dev/tests/__init__.py +5 -0
  57. pyrig/dev/tests/conftest.py +40 -0
  58. pyrig/dev/tests/fixtures/__init__.py +1 -0
  59. pyrig/dev/tests/fixtures/assertions.py +147 -0
  60. pyrig/dev/tests/fixtures/autouse/__init__.py +5 -0
  61. pyrig/dev/tests/fixtures/autouse/class_.py +42 -0
  62. pyrig/dev/tests/fixtures/autouse/module.py +40 -0
  63. pyrig/dev/tests/fixtures/autouse/session.py +589 -0
  64. pyrig/dev/tests/fixtures/factories.py +118 -0
  65. pyrig/dev/utils/__init__.py +1 -0
  66. pyrig/dev/utils/cli.py +17 -0
  67. pyrig/dev/utils/git.py +312 -0
  68. pyrig/dev/utils/packages.py +93 -0
  69. pyrig/dev/utils/resources.py +77 -0
  70. pyrig/dev/utils/testing.py +66 -0
  71. pyrig/dev/utils/versions.py +268 -0
  72. pyrig/main.py +9 -0
  73. pyrig/py.typed +0 -0
  74. pyrig/resources/GITIGNORE +216 -0
  75. pyrig/resources/LATEST_PYTHON_VERSION +1 -0
  76. pyrig/resources/MIT_LICENSE_TEMPLATE +21 -0
  77. pyrig/resources/__init__.py +1 -0
  78. pyrig/src/__init__.py +1 -0
  79. pyrig/src/git/__init__.py +6 -0
  80. pyrig/src/git/git.py +146 -0
  81. pyrig/src/graph.py +255 -0
  82. pyrig/src/iterate.py +107 -0
  83. pyrig/src/modules/__init__.py +22 -0
  84. pyrig/src/modules/class_.py +369 -0
  85. pyrig/src/modules/function.py +189 -0
  86. pyrig/src/modules/inspection.py +148 -0
  87. pyrig/src/modules/module.py +658 -0
  88. pyrig/src/modules/package.py +452 -0
  89. pyrig/src/os/__init__.py +6 -0
  90. pyrig/src/os/os.py +121 -0
  91. pyrig/src/project/__init__.py +5 -0
  92. pyrig/src/project/mgt.py +83 -0
  93. pyrig/src/resource.py +58 -0
  94. pyrig/src/string.py +100 -0
  95. pyrig/src/testing/__init__.py +6 -0
  96. pyrig/src/testing/assertions.py +66 -0
  97. pyrig/src/testing/convention.py +203 -0
  98. pyrig-2.2.6.dist-info/METADATA +174 -0
  99. pyrig-2.2.6.dist-info/RECORD +102 -0
  100. pyrig-2.2.6.dist-info/WHEEL +4 -0
  101. pyrig-2.2.6.dist-info/entry_points.txt +3 -0
  102. pyrig-2.2.6.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,112 @@
1
+ """Configuration management for LICENSE files.
2
+
3
+ This module provides the LicenceConfigFile class for managing the
4
+ project's LICENSE file. The file is created empty and users are
5
+ expected to add their own license text.
6
+ """
7
+
8
+ from datetime import UTC, datetime
9
+ from pathlib import Path
10
+
11
+ import requests
12
+
13
+ from pyrig.dev.configs.base.base import TextConfigFile
14
+ from pyrig.dev.utils.resources import return_resource_content_on_fetch_error
15
+ from pyrig.src.git.git import get_repo_owner_and_name_from_git
16
+
17
+
18
+ class LicenceConfigFile(TextConfigFile):
19
+ """Configuration file manager for LICENSE.
20
+
21
+ Creates an empty LICENSE file in the project root. Users should
22
+ add their preferred license text manually.
23
+ It defaults to the MIT license the file does not exist.
24
+ """
25
+
26
+ @classmethod
27
+ def get_filename(cls) -> str:
28
+ """Get the LICENSE filename.
29
+
30
+ Returns:
31
+ The string "LICENSE".
32
+ """
33
+ return "LICENSE"
34
+
35
+ @classmethod
36
+ def get_path(cls) -> Path:
37
+ """Get the path to the LICENSE file.
38
+
39
+ Returns:
40
+ Path to LICENSE in the project root.
41
+ """
42
+ return Path(cls.get_filename())
43
+
44
+ @classmethod
45
+ def get_parent_path(cls) -> Path:
46
+ """Get the project root directory.
47
+
48
+ Returns:
49
+ Path to the project root.
50
+ """
51
+ return Path()
52
+
53
+ @classmethod
54
+ def get_file_extension(cls) -> str:
55
+ """Get an empty file extension.
56
+
57
+ Returns:
58
+ Empty string (LICENSE has no extension).
59
+ """
60
+ return ""
61
+
62
+ @classmethod
63
+ def get_content_str(cls) -> str:
64
+ """Get the initial content (empty).
65
+
66
+ Returns:
67
+ Empty string.
68
+ """
69
+ return cls.get_mit_license_with_year_and_owner()
70
+
71
+ @classmethod
72
+ def is_correct(cls) -> bool:
73
+ """Check if the LICENSE file is valid.
74
+
75
+ Returns:
76
+ True if the file exists and is non-empty.
77
+ """
78
+ return super().is_correct() or (
79
+ cls.get_path().exists()
80
+ and bool(cls.get_path().read_text(encoding="utf-8").strip())
81
+ )
82
+
83
+ @classmethod
84
+ @return_resource_content_on_fetch_error(resource_name="MIT_LICENSE_TEMPLATE")
85
+ def get_mit_license(cls) -> str:
86
+ """Get the MIT license text.
87
+
88
+ Fetch the MIT license text from GitHub's SPDX license API.
89
+ On exception returns a default MIT license text.
90
+
91
+ Returns:
92
+ The MIT license text.
93
+ """
94
+ url = "https://api.github.com/licenses/mit"
95
+ resp = requests.get(url, timeout=10)
96
+ resp.raise_for_status()
97
+ data = resp.json()
98
+ mit_license: str = data["body"]
99
+ return mit_license
100
+
101
+ @classmethod
102
+ def get_mit_license_with_year_and_owner(cls) -> str:
103
+ """Get the MIT license text with year and owner.
104
+
105
+ Returns:
106
+ The MIT license text with year and owner.
107
+ """
108
+ mit_license = cls.get_mit_license()
109
+ year = datetime.now(tz=UTC).year
110
+ owner, _ = get_repo_owner_and_name_from_git(check_repo_url=False)
111
+ mit_license = mit_license.replace("[year]", str(year))
112
+ return mit_license.replace("[fullname]", owner)
@@ -0,0 +1 @@
1
+ """__init__ module."""
@@ -0,0 +1 @@
1
+ """__init__ module."""
@@ -0,0 +1,38 @@
1
+ """Configuration management for docs/index.md files.
2
+
3
+ This module provides the IndexConfigFile class for creating and
4
+ managing the project's docs/index.md file with a standard header.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ from pyrig.dev.configs.base.base import MarkdownConfigFile
10
+ from pyrig.dev.configs.pyproject import PyprojectConfigFile
11
+ from pyrig.src.modules.package import DOCS_DIR_NAME
12
+
13
+
14
+ class IndexConfigFile(MarkdownConfigFile):
15
+ """Configuration file manager for docs/index.md.
16
+
17
+ Creates a docs/index.md file with a standard header and
18
+ instructions for users to add their own content.
19
+ """
20
+
21
+ @classmethod
22
+ def get_parent_path(cls) -> Path:
23
+ """Get the docs directory path.
24
+
25
+ Returns:
26
+ Path to the docs directory.
27
+ """
28
+ return Path(DOCS_DIR_NAME)
29
+
30
+ @classmethod
31
+ def get_content_str(cls) -> str:
32
+ """Get the index file content.
33
+
34
+ Returns:
35
+ Markdown content with a standard header and instructions.
36
+ """
37
+ return f"""# {PyprojectConfigFile.get_project_name()} Documentation
38
+ """
@@ -0,0 +1,132 @@
1
+ """Configuration management for README.md files.
2
+
3
+ This module provides the ReadmeConfigFile class for creating and
4
+ managing the project's README.md file with a standard header.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ import pyrig
10
+ from pyrig.dev.configs.base.base import MarkdownConfigFile
11
+ from pyrig.dev.configs.pyproject import PyprojectConfigFile
12
+ from pyrig.dev.utils.git import DEFAULT_BRANCH
13
+ from pyrig.src.git.git import get_repo_owner_and_name_from_git
14
+
15
+
16
+ class ReadmeConfigFile(MarkdownConfigFile):
17
+ """Configuration file manager for README.md.
18
+
19
+ Creates a README.md file with the project name as a header.
20
+ For projects using pyrig, includes a reference link to pyrig.
21
+ """
22
+
23
+ @classmethod
24
+ def get_filename(cls) -> str:
25
+ """Get the README filename.
26
+
27
+ Returns:
28
+ The string "README".
29
+ """
30
+ return "README"
31
+
32
+ @classmethod
33
+ def get_parent_path(cls) -> Path:
34
+ """Get the project root directory.
35
+
36
+ Returns:
37
+ Path to the project root.
38
+ """
39
+ return Path()
40
+
41
+ @classmethod
42
+ def get_content_str(cls) -> str:
43
+ """Generate the README content with project header.
44
+
45
+ Returns:
46
+ Markdown content with project name and optional pyrig reference.
47
+ """
48
+ project_name = PyprojectConfigFile.get_project_name()
49
+ badges = cls.get_badges()
50
+ badges_str = ""
51
+ for badge_category, badge_list in badges.items():
52
+ badges_str += f"<!-- {badge_category} -->\n"
53
+ badges_str += "\n".join(badge_list) + "\n"
54
+ badges_str = badges_str.removesuffix("\n")
55
+ description = PyprojectConfigFile.get_project_description()
56
+ return f"""# {project_name}
57
+
58
+ {badges_str}
59
+
60
+ ---
61
+
62
+ > {description}
63
+
64
+ ---
65
+ """
66
+
67
+ @classmethod
68
+ def is_unwanted(cls) -> bool:
69
+ """Check if README is unwanted (always False).
70
+
71
+ Returns:
72
+ False, as README.md is always required.
73
+ """
74
+ # README.md is never unwanted
75
+ return False
76
+
77
+ @classmethod
78
+ def is_correct(cls) -> bool:
79
+ """Check if the README.md file is valid.
80
+
81
+ Returns:
82
+ True if the file has required structure.
83
+ """
84
+ file_content = cls.get_file_content()
85
+ badges = [
86
+ badge for _group, badges in cls.get_badges().items() for badge in badges
87
+ ]
88
+ all_badges_in_file = all(badge in file_content for badge in badges)
89
+ description_in_file = (
90
+ PyprojectConfigFile.get_project_description() in file_content
91
+ )
92
+ project_name_in_file = PyprojectConfigFile.get_project_name() in file_content
93
+ return super().is_correct() or (
94
+ all_badges_in_file and description_in_file and project_name_in_file
95
+ )
96
+
97
+ @classmethod
98
+ def get_badges(cls) -> dict[str, list[str]]:
99
+ """Get the badges for the README.md file.
100
+
101
+ Returns:
102
+ List of badge markdown strings.
103
+ """
104
+ repo_owner, repo_name = get_repo_owner_and_name_from_git(check_repo_url=False)
105
+ project_name = PyprojectConfigFile.get_project_name()
106
+ python_versions = PyprojectConfigFile.get_supported_python_versions()
107
+ joined_python_versions = "|".join(str(v) for v in python_versions)
108
+ return {
109
+ "tooling": [
110
+ rf"[![{pyrig.__name__}](https://img.shields.io/badge/built%20with-{pyrig.__name__}-3776AB?logo=buildkite&logoColor=black)](https://github.com/Winipedia/{pyrig.__name__})",
111
+ r"[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)",
112
+ r"[![Container](https://img.shields.io/badge/Container-Podman-A23CD6?logo=podman&logoColor=grey&colorA=0D1F3F&colorB=A23CD6)](https://podman.io/)",
113
+ r"[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://pre-commit.com/)",
114
+ ],
115
+ "code-quality": [
116
+ r"[![ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)",
117
+ r"[![ty](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ty/main/assets/badge/v0.json)](https://github.com/astral-sh/ty)"
118
+ r"[![mypy](https://img.shields.io/badge/type%20checked-mypy-039dfc.svg)](https://mypy-lang.org/)",
119
+ r"[![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)",
120
+ r"[![pytest](https://img.shields.io/badge/tested%20with-pytest-46a2f1.svg?logo=pytest)](https://pytest.org/)",
121
+ rf"[![codecov](https://codecov.io/gh/{repo_owner}/{repo_name}/branch/{DEFAULT_BRANCH}/graph/badge.svg)](https://codecov.io/gh/{repo_owner}/{repo_name})",
122
+ ],
123
+ "package-info": [
124
+ rf"[![PyPI](https://img.shields.io/pypi/v/{project_name}?logo=pypi&logoColor=white)](https://pypi.org/project/{project_name}/)",
125
+ rf"[![Python](https://img.shields.io/badge/python-{joined_python_versions}-blue.svg?logo=python&logoColor=white)](https://www.python.org/)",
126
+ rf"[![License](https://img.shields.io/github/license/{repo_owner}/{repo_name})](https://github.com/{repo_owner}/{repo_name}/blob/main/LICENSE)",
127
+ ],
128
+ "ci/cd": [
129
+ rf"[![CI](https://img.shields.io/github/actions/workflow/status/{repo_owner}/{repo_name}/health_check.yaml?label=CI&logo=github)](https://github.com/{repo_owner}/{repo_name}/actions/workflows/health_check.yaml)",
130
+ rf"[![CD](https://img.shields.io/github/actions/workflow/status/{repo_owner}/{repo_name}/release.yaml?label=CD&logo=github)](https://github.com/{repo_owner}/{repo_name}/actions/workflows/release.yaml)",
131
+ ],
132
+ }
@@ -0,0 +1,28 @@
1
+ """Configuration management for py.typed marker files.
2
+
3
+ This module provides the PyTypedConfigFile class for creating the
4
+ py.typed marker file that indicates PEP 561 compliance for type
5
+ checkers like mypy.
6
+ """
7
+
8
+ from pathlib import Path
9
+
10
+ from pyrig.dev.configs.base.base import TypedConfigFile
11
+ from pyrig.dev.configs.pyproject import PyprojectConfigFile
12
+
13
+
14
+ class PyTypedConfigFile(TypedConfigFile):
15
+ """Configuration file manager for py.typed.
16
+
17
+ Creates the py.typed marker file in the source package to indicate
18
+ that the package supports type checking (PEP 561).
19
+ """
20
+
21
+ @classmethod
22
+ def get_parent_path(cls) -> Path:
23
+ """Get the source package directory.
24
+
25
+ Returns:
26
+ Path to the source package.
27
+ """
28
+ return Path(PyprojectConfigFile.get_package_name())