winipedia-utils 0.2.17__tar.gz → 0.2.22__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.

Potentially problematic release.


This version of winipedia-utils might be problematic. Click here for more details.

Files changed (82) hide show
  1. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/PKG-INFO +21 -6
  2. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/README.md +20 -5
  3. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/pyproject.toml +1 -1
  4. winipedia_utils-0.2.22/winipedia_utils/git/workflows/__init__.py +1 -0
  5. winipedia_utils-0.2.22/winipedia_utils/git/workflows/publish.py +76 -0
  6. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/setup.py +24 -14
  7. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/base/fixtures/scopes/session.py +20 -0
  8. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/LICENSE +0 -0
  9. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/__init__.py +0 -0
  10. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/concurrent/__init__.py +0 -0
  11. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/concurrent/concurrent.py +0 -0
  12. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/concurrent/multiprocessing.py +0 -0
  13. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/concurrent/multithreading.py +0 -0
  14. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/consts.py +0 -0
  15. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/data/__init__.py +0 -0
  16. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/data/dataframe/__init__.py +0 -0
  17. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/data/dataframe/cleaning.py +0 -0
  18. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/data/structures/__init__.py +0 -0
  19. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/data/structures/dicts.py +0 -0
  20. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/git/__init__.py +0 -0
  21. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/git/gitignore/__init__.py +0 -0
  22. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/git/gitignore/gitignore.py +0 -0
  23. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/git/pre_commit/__init__.py +0 -0
  24. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/git/pre_commit/config.py +0 -0
  25. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/git/pre_commit/hooks.py +0 -0
  26. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/git/pre_commit/run_hooks.py +0 -0
  27. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/iterating/__init__.py +0 -0
  28. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/iterating/iterate.py +0 -0
  29. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/logging/__init__.py +0 -0
  30. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/logging/ansi.py +0 -0
  31. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/logging/config.py +0 -0
  32. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/logging/logger.py +0 -0
  33. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/modules/__init__.py +0 -0
  34. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/modules/class_.py +0 -0
  35. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/modules/function.py +0 -0
  36. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/modules/module.py +0 -0
  37. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/modules/package.py +0 -0
  38. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/oop/__init__.py +0 -0
  39. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/oop/mixins/__init__.py +0 -0
  40. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/oop/mixins/meta.py +0 -0
  41. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/oop/mixins/mixin.py +0 -0
  42. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/os/__init__.py +0 -0
  43. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/os/os.py +0 -0
  44. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/projects/__init__.py +0 -0
  45. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/projects/poetry/__init__.py +0 -0
  46. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/projects/poetry/config.py +0 -0
  47. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/projects/poetry/poetry.py +0 -0
  48. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/projects/project.py +0 -0
  49. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/py.typed +0 -0
  50. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/resources/__init__.py +0 -0
  51. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/resources/svgs/__init__.py +0 -0
  52. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/resources/svgs/delete_garbage_can.svg +0 -0
  53. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/resources/svgs/download_arrow.svg +0 -0
  54. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/resources/svgs/exit_fullscreen_icon.svg +0 -0
  55. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/resources/svgs/fullscreen_icon.svg +0 -0
  56. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/resources/svgs/menu_icon.svg +0 -0
  57. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/resources/svgs/pause_icon.svg +0 -0
  58. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/resources/svgs/play_icon.svg +0 -0
  59. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/resources/svgs/plus_icon.svg +0 -0
  60. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/resources/svgs/svg.py +0 -0
  61. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/security/__init__.py +0 -0
  62. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/security/cryptography.py +0 -0
  63. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/security/keyring.py +0 -0
  64. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/__init__.py +0 -0
  65. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/assertions.py +0 -0
  66. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/convention.py +0 -0
  67. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/create_tests.py +0 -0
  68. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/fixtures.py +0 -0
  69. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/__init__.py +0 -0
  70. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/base/__init__.py +0 -0
  71. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/base/fixtures/__init__.py +0 -0
  72. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/base/fixtures/fixture.py +0 -0
  73. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/base/fixtures/scopes/__init__.py +0 -0
  74. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/base/fixtures/scopes/class_.py +0 -0
  75. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/base/fixtures/scopes/function.py +0 -0
  76. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/base/fixtures/scopes/module.py +0 -0
  77. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/base/fixtures/scopes/package.py +0 -0
  78. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/base/utils/__init__.py +0 -0
  79. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/base/utils/utils.py +0 -0
  80. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/testing/tests/conftest.py +0 -0
  81. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/text/__init__.py +0 -0
  82. {winipedia_utils-0.2.17 → winipedia_utils-0.2.22}/winipedia_utils/text/string.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: winipedia-utils
3
- Version: 0.2.17
3
+ Version: 0.2.22
4
4
  Summary: A package with many utility functions
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -126,10 +126,16 @@ Adds tool configurations in pyproject.toml for e.g.:
126
126
  - **pytest** - Test discovery and execution
127
127
  - **bandit** - Security scanning
128
128
 
129
- ### Step 6️⃣ - Create Project Root
129
+ ### Step 6️⃣ - Create GitHub Actions Workflow
130
+ Sets up `.github/workflows/publish.yaml` for automated PyPI publishing:
131
+ - Triggers on GitHub releases
132
+ - Configures Poetry with PyPI token
133
+ - Builds and publishes package automatically
134
+
135
+ ### Step 7️⃣ - Create Project Root
130
136
  Creates your project's root package directory with `py.typed` marker for type hint support.
131
137
 
132
- ### Step 7️⃣ - Run Pre-commit Hook
138
+ ### Step 8️⃣ - Run Pre-commit Hook
133
139
  Executes the complete quality pipeline (see below).
134
140
 
135
141
  ---
@@ -137,7 +143,6 @@ Executes the complete quality pipeline (see below).
137
143
  ## Pre-commit Hook Workflow
138
144
 
139
145
  When you commit code, the winipedia-utils hook automatically runs a few quality checks e.g.:
140
-
141
146
  ```
142
147
  ┌─────────────────────────────────────────────────────────┐
143
148
  │ Pre-commit Hook Execution Pipeline │
@@ -285,9 +290,9 @@ print(data.df) # Cleaned and validated dataframe
285
290
 
286
291
  ### 3. 🔧 Git Utilities
287
292
 
288
- Manage gitignore patterns and pre-commit configuration.
293
+ Manage gitignore patterns, pre-commit configuration, and GitHub Actions workflows.
289
294
 
290
- **Use Cases:** Project setup, git workflow automation
295
+ **Use Cases:** Project setup, git workflow automation, CI/CD pipeline setup
291
296
 
292
297
  ```python
293
298
  from winipedia_utils.git.gitignore.gitignore import (
@@ -295,6 +300,10 @@ from winipedia_utils.git.gitignore.gitignore import (
295
300
  walk_os_skipping_gitignore_patterns,
296
301
  add_patterns_to_gitignore
297
302
  )
303
+ from winipedia_utils.git.workflows.publish import (
304
+ load_publish_workflow,
305
+ dump_publish_workflow
306
+ )
298
307
 
299
308
  # Check if path is ignored
300
309
  if path_is_in_gitignore("dist/"):
@@ -306,12 +315,18 @@ for root, dirs, files in walk_os_skipping_gitignore_patterns("."):
306
315
 
307
316
  # Add patterns to gitignore
308
317
  add_patterns_to_gitignore(["*.log", "temp/"])
318
+
319
+ # Load and modify publish workflow
320
+ workflow = load_publish_workflow()
321
+ print(f"Workflow name: {workflow.get('name')}")
309
322
  ```
310
323
 
311
324
  **Key Functions:**
312
325
  - `path_is_in_gitignore()` - Check if path matches gitignore patterns
313
326
  - `walk_os_skipping_gitignore_patterns()` - Directory traversal respecting gitignore
314
327
  - `add_patterns_to_gitignore()` - Add patterns to .gitignore file
328
+ - `load_publish_workflow()` - Load GitHub Actions publish workflow
329
+ - `dump_publish_workflow()` - Save GitHub Actions publish workflow
315
330
  - Pre-commit configuration management
316
331
 
317
332
  ---
@@ -102,10 +102,16 @@ Adds tool configurations in pyproject.toml for e.g.:
102
102
  - **pytest** - Test discovery and execution
103
103
  - **bandit** - Security scanning
104
104
 
105
- ### Step 6️⃣ - Create Project Root
105
+ ### Step 6️⃣ - Create GitHub Actions Workflow
106
+ Sets up `.github/workflows/publish.yaml` for automated PyPI publishing:
107
+ - Triggers on GitHub releases
108
+ - Configures Poetry with PyPI token
109
+ - Builds and publishes package automatically
110
+
111
+ ### Step 7️⃣ - Create Project Root
106
112
  Creates your project's root package directory with `py.typed` marker for type hint support.
107
113
 
108
- ### Step 7️⃣ - Run Pre-commit Hook
114
+ ### Step 8️⃣ - Run Pre-commit Hook
109
115
  Executes the complete quality pipeline (see below).
110
116
 
111
117
  ---
@@ -113,7 +119,6 @@ Executes the complete quality pipeline (see below).
113
119
  ## Pre-commit Hook Workflow
114
120
 
115
121
  When you commit code, the winipedia-utils hook automatically runs a few quality checks e.g.:
116
-
117
122
  ```
118
123
  ┌─────────────────────────────────────────────────────────┐
119
124
  │ Pre-commit Hook Execution Pipeline │
@@ -261,9 +266,9 @@ print(data.df) # Cleaned and validated dataframe
261
266
 
262
267
  ### 3. 🔧 Git Utilities
263
268
 
264
- Manage gitignore patterns and pre-commit configuration.
269
+ Manage gitignore patterns, pre-commit configuration, and GitHub Actions workflows.
265
270
 
266
- **Use Cases:** Project setup, git workflow automation
271
+ **Use Cases:** Project setup, git workflow automation, CI/CD pipeline setup
267
272
 
268
273
  ```python
269
274
  from winipedia_utils.git.gitignore.gitignore import (
@@ -271,6 +276,10 @@ from winipedia_utils.git.gitignore.gitignore import (
271
276
  walk_os_skipping_gitignore_patterns,
272
277
  add_patterns_to_gitignore
273
278
  )
279
+ from winipedia_utils.git.workflows.publish import (
280
+ load_publish_workflow,
281
+ dump_publish_workflow
282
+ )
274
283
 
275
284
  # Check if path is ignored
276
285
  if path_is_in_gitignore("dist/"):
@@ -282,12 +291,18 @@ for root, dirs, files in walk_os_skipping_gitignore_patterns("."):
282
291
 
283
292
  # Add patterns to gitignore
284
293
  add_patterns_to_gitignore(["*.log", "temp/"])
294
+
295
+ # Load and modify publish workflow
296
+ workflow = load_publish_workflow()
297
+ print(f"Workflow name: {workflow.get('name')}")
285
298
  ```
286
299
 
287
300
  **Key Functions:**
288
301
  - `path_is_in_gitignore()` - Check if path matches gitignore patterns
289
302
  - `walk_os_skipping_gitignore_patterns()` - Directory traversal respecting gitignore
290
303
  - `add_patterns_to_gitignore()` - Add patterns to .gitignore file
304
+ - `load_publish_workflow()` - Load GitHub Actions publish workflow
305
+ - `dump_publish_workflow()` - Save GitHub Actions publish workflow
291
306
  - Pre-commit configuration management
292
307
 
293
308
  ---
@@ -1,7 +1,7 @@
1
1
  # Project section
2
2
  [project]
3
3
  name = "winipedia-utils"
4
- version = "0.2.17"
4
+ version = "0.2.22"
5
5
  description = "A package with many utility functions"
6
6
  readme = "README.md"
7
7
  requires-python = ">=3.12"
@@ -0,0 +1 @@
1
+ """__init__ module for winipedia_utils.git.workflows."""
@@ -0,0 +1,76 @@
1
+ """Contains the publish workflow.
2
+
3
+ This workflow is used to publish the package to PyPI with poetry.
4
+ """
5
+
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ import yaml
10
+
11
+ PUBLISH_WORKFLOW_PATH = Path(".github/workflows/publish.yaml")
12
+
13
+
14
+ def load_publish_workflow() -> dict[str, Any]:
15
+ """Load the publish workflow."""
16
+ path = PUBLISH_WORKFLOW_PATH
17
+ if not path.exists():
18
+ path.parent.mkdir(parents=True, exist_ok=True)
19
+ path.touch()
20
+ return yaml.safe_load(path.read_text()) or {}
21
+
22
+
23
+ def dump_publish_workflow(config: dict[str, Any]) -> None:
24
+ """Dump the publish workflow."""
25
+ path = PUBLISH_WORKFLOW_PATH
26
+ with path.open("w") as f:
27
+ yaml.safe_dump(config, f, sort_keys=False)
28
+
29
+
30
+ def _get_publish_config() -> dict[str, Any]:
31
+ """Dict that represents the publish workflow yaml."""
32
+ return {
33
+ "name": "Publish to PyPI",
34
+ "on": {"release": {"types": ["published"]}},
35
+ "jobs": {
36
+ "publish": {
37
+ "runs-on": "ubuntu-latest",
38
+ "steps": [
39
+ {"name": "Checkout repository", "uses": "actions/checkout@v4"},
40
+ {
41
+ "name": "Set up Python",
42
+ "uses": "actions/setup-python@v5",
43
+ "with": {"python-version": "3.x"},
44
+ },
45
+ {"name": "Install Poetry", "run": "pip install poetry"},
46
+ {
47
+ "name": "Configure Poetry",
48
+ "run": "poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }}", # noqa: E501
49
+ },
50
+ {
51
+ "name": "Build and publish to PyPI",
52
+ "run": "poetry publish --build",
53
+ },
54
+ ],
55
+ }
56
+ },
57
+ }
58
+
59
+
60
+ def _publish_config_is_correct() -> bool:
61
+ """Check if the publish workflow is correct."""
62
+ config = load_publish_workflow()
63
+ return bool(config == _get_publish_config())
64
+
65
+
66
+ def _add_publish_workflow() -> None:
67
+ """Add the publish workflow.
68
+
69
+ If you delete the .github/workflows/publish.yaml file, then the tests will not fail.
70
+ Not all projects need publishing to pypi. It is added on setup, but if you remove
71
+ the file, then the tests will not fail and the tests will assume you don't want it.
72
+ """
73
+ if _publish_config_is_correct():
74
+ return
75
+ config = _get_publish_config()
76
+ dump_publish_workflow(config)
@@ -6,12 +6,16 @@ This package assumes you are using poetry and pre-commit.
6
6
  This script is intended to be called once at the beginning of a project.
7
7
  """
8
8
 
9
+ from collections.abc import Callable
10
+ from typing import Any
11
+
9
12
  from winipedia_utils.git.gitignore.gitignore import _add_package_patterns_to_gitignore
10
13
  from winipedia_utils.git.pre_commit.config import (
11
14
  _add_package_hook_to_pre_commit_config,
12
15
  _pre_commit_install,
13
16
  )
14
17
  from winipedia_utils.git.pre_commit.run_hooks import _run_all_hooks
18
+ from winipedia_utils.git.workflows.publish import _add_publish_workflow
15
19
  from winipedia_utils.logging.logger import get_logger
16
20
  from winipedia_utils.projects.poetry.config import (
17
21
  _add_configurations_to_pyproject_toml,
@@ -24,22 +28,28 @@ from winipedia_utils.projects.project import _create_project_root
24
28
  logger = get_logger(__name__)
25
29
 
26
30
 
31
+ SETUP_STEPS = [
32
+ _install_dev_dependencies,
33
+ _add_package_hook_to_pre_commit_config,
34
+ _pre_commit_install,
35
+ _add_package_patterns_to_gitignore,
36
+ _add_publish_workflow,
37
+ _add_configurations_to_pyproject_toml,
38
+ _create_project_root,
39
+ _run_all_hooks,
40
+ ]
41
+
42
+
43
+ def _get_setup_steps() -> list[Callable[..., Any]]:
44
+ """Get the setup steps."""
45
+ return SETUP_STEPS
46
+
47
+
27
48
  def _setup() -> None:
28
49
  """Set up the project."""
29
- # install winipedia_utils dev dependencies as dev
30
- _install_dev_dependencies()
31
- # create pre-commit config
32
- _add_package_hook_to_pre_commit_config()
33
- # install pre-commit
34
- _pre_commit_install()
35
- # add patterns to .gitignore
36
- _add_package_patterns_to_gitignore()
37
- # add tool.* configurations to pyproject.toml
38
- _add_configurations_to_pyproject_toml()
39
- # create the project root
40
- _create_project_root()
41
- # run pre-commit once, create tests is included here
42
- _run_all_hooks()
50
+ for step in _get_setup_steps():
51
+ logger.info("Running setup step: %s", step.__name__)
52
+ step()
43
53
  logger.info("Setup complete!")
44
54
 
45
55
 
@@ -14,6 +14,10 @@ from winipedia_utils.git.gitignore.gitignore import _gitignore_is_correct
14
14
  from winipedia_utils.git.pre_commit.config import (
15
15
  _pre_commit_config_is_correct,
16
16
  )
17
+ from winipedia_utils.git.workflows.publish import (
18
+ PUBLISH_WORKFLOW_PATH,
19
+ _publish_config_is_correct,
20
+ )
17
21
  from winipedia_utils.modules.module import to_path
18
22
  from winipedia_utils.modules.package import (
19
23
  find_packages,
@@ -164,6 +168,22 @@ def _test_gitignore_is_correct() -> None:
164
168
  )
165
169
 
166
170
 
171
+ @autouse_session_fixture
172
+ def _test_publish_workflow_is_correct() -> None:
173
+ """Verify that the publish workflow is correctly defined.
174
+
175
+ If the file does not exist, we skip this test bc not all projects necessarily
176
+ need to publish to pypi, e.g. they are binaries or private usage only or for profit.
177
+ """
178
+ path = PUBLISH_WORKFLOW_PATH
179
+ if not path.exists():
180
+ return
181
+ assert_with_msg(
182
+ _publish_config_is_correct(),
183
+ "Publish workflow is not correct.",
184
+ )
185
+
186
+
167
187
  @autouse_session_fixture
168
188
  def _test_no_namespace_packages() -> None:
169
189
  """Verify that there are no namespace packages in the project.