winipedia-utils 0.4.41__tar.gz → 0.4.46__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.
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/PKG-INFO +7 -1
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/README.md +5 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/pyproject.toml +4 -1
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/pre_commit/hooks.py +1 -1
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/iterating/iterate.py +6 -1
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/modules/module.py +22 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/modules/package.py +81 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/projects/poetry/config.py +4 -1
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/text/config.py +9 -4
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/LICENSE +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/concurrent/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/concurrent/concurrent.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/concurrent/multiprocessing.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/concurrent/multithreading.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/data/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/data/dataframe/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/data/dataframe/cleaning.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/data/structures/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/data/structures/dicts.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/github.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/repo/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/repo/protect.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/repo/repo.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/workflows/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/workflows/base/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/workflows/base/base.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/workflows/health_check.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/workflows/publish.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/workflows/release.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/gitignore/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/gitignore/config.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/gitignore/gitignore.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/pre_commit/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/pre_commit/config.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/pre_commit/run_hooks.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/iterating/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/logging/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/logging/ansi.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/logging/config.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/logging/logger.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/modules/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/modules/class_.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/modules/function.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/oop/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/oop/mixins/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/oop/mixins/meta.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/oop/mixins/mixin.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/os/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/os/os.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/projects/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/projects/poetry/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/projects/poetry/poetry.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/projects/project.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/py.typed +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/delete_garbage_can.svg +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/download_arrow.svg +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/exit_fullscreen_icon.svg +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/fullscreen_icon.svg +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/menu_icon.svg +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/pause_icon.svg +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/play_icon.svg +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/plus_icon.svg +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/svg.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/security/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/security/cryptography.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/security/keyring.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/setup.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/assertions.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/config.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/convention.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/create_tests.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/fixtures.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/skip.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/fixtures/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/fixtures/fixture.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/fixtures/scopes/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/fixtures/scopes/class_.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/fixtures/scopes/function.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/fixtures/scopes/module.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/fixtures/scopes/package.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/fixtures/scopes/session.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/utils/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/utils/utils.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/conftest.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/text/__init__.py +0 -0
- {winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/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.4.
|
|
3
|
+
Version: 0.4.46
|
|
4
4
|
Summary: A package with many utility functions
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -15,6 +15,7 @@ Requires-Dist: cryptography
|
|
|
15
15
|
Requires-Dist: defusedxml
|
|
16
16
|
Requires-Dist: dotenv
|
|
17
17
|
Requires-Dist: keyring
|
|
18
|
+
Requires-Dist: networkx
|
|
18
19
|
Requires-Dist: pathspec
|
|
19
20
|
Requires-Dist: polars
|
|
20
21
|
Requires-Dist: pygithub
|
|
@@ -152,6 +153,10 @@ my_project/
|
|
|
152
153
|
|
|
153
154
|
For each function, class, and method, skeleton tests are created with `NotImplementedError` placeholders for you to implement.
|
|
154
155
|
|
|
156
|
+
If you have autosuse fixtures just write and add them to the `tests/base/fixtures` directory. They will be automatically discovered, plugged into conftest and used in all tests according to defined scope.
|
|
157
|
+
The filenames in the fixtures folder are just for organisation purposes for your convenience. You still have to
|
|
158
|
+
apply the pytest.fixture decorator to the fixture function and define the scope. So a session scoped function defined on function.py will still run as a session scoped fixture.
|
|
159
|
+
|
|
155
160
|
## Configuration Files
|
|
156
161
|
|
|
157
162
|
Configuration files are managed automatically by the setup system:
|
|
@@ -160,6 +165,7 @@ Configuration files are managed automatically by the setup system:
|
|
|
160
165
|
- **Empty files** - If you want to disable a config file, make it empty. This signals that the file is unwanted and won't be modified
|
|
161
166
|
- **Custom additions** - You can add custom configurations as long as the standard configurations remain intact
|
|
162
167
|
- **Modified standards** - If you modify the standard configurations, they will be restored on the next setup run
|
|
168
|
+
- **Subclasses** - You can create custom config files by subclassing the standard ones. They will be automatically created and managed when you commit or run pytest. winipedia_utils automatically discovers and calls them. This way you can adjust or add some settings. It is however important the parent class stays a subset of the child class according to the description in the function `nested_structure_is_subset` in `winipedia_utils.iterating.iterate`.
|
|
163
169
|
|
|
164
170
|
## Branch Protection
|
|
165
171
|
|
|
@@ -126,6 +126,10 @@ my_project/
|
|
|
126
126
|
|
|
127
127
|
For each function, class, and method, skeleton tests are created with `NotImplementedError` placeholders for you to implement.
|
|
128
128
|
|
|
129
|
+
If you have autosuse fixtures just write and add them to the `tests/base/fixtures` directory. They will be automatically discovered, plugged into conftest and used in all tests according to defined scope.
|
|
130
|
+
The filenames in the fixtures folder are just for organisation purposes for your convenience. You still have to
|
|
131
|
+
apply the pytest.fixture decorator to the fixture function and define the scope. So a session scoped function defined on function.py will still run as a session scoped fixture.
|
|
132
|
+
|
|
129
133
|
## Configuration Files
|
|
130
134
|
|
|
131
135
|
Configuration files are managed automatically by the setup system:
|
|
@@ -134,6 +138,7 @@ Configuration files are managed automatically by the setup system:
|
|
|
134
138
|
- **Empty files** - If you want to disable a config file, make it empty. This signals that the file is unwanted and won't be modified
|
|
135
139
|
- **Custom additions** - You can add custom configurations as long as the standard configurations remain intact
|
|
136
140
|
- **Modified standards** - If you modify the standard configurations, they will be restored on the next setup run
|
|
141
|
+
- **Subclasses** - You can create custom config files by subclassing the standard ones. They will be automatically created and managed when you commit or run pytest. winipedia_utils automatically discovers and calls them. This way you can adjust or add some settings. It is however important the parent class stays a subset of the child class according to the description in the function `nested_structure_is_subset` in `winipedia_utils.iterating.iterate`.
|
|
137
142
|
|
|
138
143
|
## Branch Protection
|
|
139
144
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Project section
|
|
2
2
|
[project]
|
|
3
3
|
name = "winipedia-utils"
|
|
4
|
-
version = "0.4.
|
|
4
|
+
version = "0.4.46"
|
|
5
5
|
description = "A package with many utility functions"
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
requires-python = ">=3.12"
|
|
@@ -32,6 +32,7 @@ cryptography = "*"
|
|
|
32
32
|
polars = "*"
|
|
33
33
|
pygithub = "*"
|
|
34
34
|
dotenv = "*"
|
|
35
|
+
networkx = "*"
|
|
35
36
|
|
|
36
37
|
[tool.poetry.group.dev.dependencies]
|
|
37
38
|
ruff = "*"
|
|
@@ -44,6 +45,7 @@ types-tqdm = "*"
|
|
|
44
45
|
types-defusedxml = "*"
|
|
45
46
|
types-pyyaml = "*"
|
|
46
47
|
pytest-mock = "*"
|
|
48
|
+
types-networkx = "*"
|
|
47
49
|
|
|
48
50
|
[tool.ruff]
|
|
49
51
|
exclude = [ ".*", "**/migrations/*.py",]
|
|
@@ -64,3 +66,4 @@ files = "."
|
|
|
64
66
|
testpaths = [ "tests",]
|
|
65
67
|
|
|
66
68
|
[tool.bandit]
|
|
69
|
+
exclude_dirs = ["experiment.py"]
|
|
@@ -127,7 +127,7 @@ def check_static_types() -> list[str | Path]:
|
|
|
127
127
|
|
|
128
128
|
This function returns the input for subprocess.run() to check the static types.
|
|
129
129
|
"""
|
|
130
|
-
return ["mypy"]
|
|
130
|
+
return ["mypy", "--exclude-gitignore"]
|
|
131
131
|
|
|
132
132
|
|
|
133
133
|
def check_security() -> list[str | Path]:
|
|
@@ -49,7 +49,7 @@ def nested_structure_is_subset(
|
|
|
49
49
|
Each value of a key must be equal to the value of the same key in the superset.
|
|
50
50
|
If the value is dictionary, the function is called recursively.
|
|
51
51
|
If the value is list, each item must be in the list of the same key in the superset.
|
|
52
|
-
The order in lists
|
|
52
|
+
The order in lists does not matter.
|
|
53
53
|
|
|
54
54
|
Returns:
|
|
55
55
|
True if subset is a nested subset of superset, False otherwise
|
|
@@ -68,6 +68,11 @@ def nested_structure_is_subset(
|
|
|
68
68
|
|
|
69
69
|
def get_actual(key_or_index: Any) -> Any:
|
|
70
70
|
"""Get actual value from superset."""
|
|
71
|
+
subset_val = subset[key_or_index]
|
|
72
|
+
for superset_val in superset:
|
|
73
|
+
if nested_structure_is_subset(subset_val, superset_val):
|
|
74
|
+
return superset_val
|
|
75
|
+
|
|
71
76
|
return superset[key_or_index] if key_or_index < len(superset) else None
|
|
72
77
|
else:
|
|
73
78
|
return subset == superset
|
|
@@ -379,3 +379,25 @@ def get_unwrapped_obj(obj: Any) -> Any:
|
|
|
379
379
|
if isinstance(obj, property):
|
|
380
380
|
obj = obj.fget # get the getter function of the property
|
|
381
381
|
return inspect.unwrap(obj)
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def get_executing_module() -> ModuleType:
|
|
385
|
+
"""Get the module where execution has started.
|
|
386
|
+
|
|
387
|
+
The executing module is the module that contains the __main__ attribute as __name__
|
|
388
|
+
E.g. if you run `python -m winipedia_utils.setup` from the command line,
|
|
389
|
+
then the executing module is winipedia_utils.modules.setup
|
|
390
|
+
|
|
391
|
+
Returns:
|
|
392
|
+
The module where execution has started
|
|
393
|
+
|
|
394
|
+
Raises:
|
|
395
|
+
ValueError: If no __main__ module is found or if the executing module
|
|
396
|
+
cannot be determined
|
|
397
|
+
|
|
398
|
+
"""
|
|
399
|
+
main = sys.modules.get("__main__")
|
|
400
|
+
if main is None:
|
|
401
|
+
msg = "No __main__ module found"
|
|
402
|
+
raise ValueError(msg)
|
|
403
|
+
return main
|
|
@@ -9,17 +9,23 @@ The utilities support both static package analysis and dynamic package manipulat
|
|
|
9
9
|
making them suitable for code generation, testing frameworks, and package management.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
+
import importlib.metadata
|
|
13
|
+
import importlib.util
|
|
12
14
|
import os
|
|
13
15
|
import pkgutil
|
|
16
|
+
import re
|
|
14
17
|
import sys
|
|
15
18
|
from collections.abc import Generator, Iterable
|
|
16
19
|
from importlib import import_module
|
|
17
20
|
from pathlib import Path
|
|
18
21
|
from types import ModuleType
|
|
22
|
+
from typing import Any
|
|
19
23
|
|
|
24
|
+
import networkx as nx
|
|
20
25
|
from setuptools import find_namespace_packages as _find_namespace_packages
|
|
21
26
|
from setuptools import find_packages as _find_packages
|
|
22
27
|
|
|
28
|
+
import winipedia_utils
|
|
23
29
|
from winipedia_utils.logging.logger import get_logger
|
|
24
30
|
|
|
25
31
|
logger = get_logger(__name__)
|
|
@@ -428,3 +434,78 @@ def make_name_from_package(
|
|
|
428
434
|
if capitalize:
|
|
429
435
|
parts = [part.capitalize() for part in parts]
|
|
430
436
|
return join_on.join(parts)
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
class DependencyGraph(nx.DiGraph): # type: ignore [type-arg]
|
|
440
|
+
"""A directed graph representing Python package dependencies."""
|
|
441
|
+
|
|
442
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
443
|
+
"""Initialize the dependency graph and build it immediately."""
|
|
444
|
+
super().__init__(*args, **kwargs)
|
|
445
|
+
self.build()
|
|
446
|
+
|
|
447
|
+
def build(self) -> None:
|
|
448
|
+
"""Build the graph from installed Python distributions."""
|
|
449
|
+
for dist in importlib.metadata.distributions():
|
|
450
|
+
name = dist.metadata["Name"].lower()
|
|
451
|
+
self.add_node(name)
|
|
452
|
+
|
|
453
|
+
requires = dist.requires or []
|
|
454
|
+
for req in requires:
|
|
455
|
+
dep = self.parse_pkg_name_from_req(req)
|
|
456
|
+
if dep:
|
|
457
|
+
self.add_edge(name, dep) # package → dependency
|
|
458
|
+
|
|
459
|
+
@staticmethod
|
|
460
|
+
def parse_pkg_name_from_req(req: str) -> str | None:
|
|
461
|
+
"""Extract the bare dependency name from a requirement string."""
|
|
462
|
+
if not req:
|
|
463
|
+
return None
|
|
464
|
+
# split on the first non alphanumeric character like >, <, =, etc.
|
|
465
|
+
dep = re.split(r"[^a-zA-Z0-9]", req.strip())[0].strip()
|
|
466
|
+
return dep.lower().strip() if dep else None
|
|
467
|
+
|
|
468
|
+
def get_all_depending_on(
|
|
469
|
+
self, package: ModuleType, *, include_self: bool = False
|
|
470
|
+
) -> set[ModuleType]:
|
|
471
|
+
"""Return all packages that directly or indirectly depend on the given package.
|
|
472
|
+
|
|
473
|
+
Args:
|
|
474
|
+
package: The module whose dependents should be found.
|
|
475
|
+
include_self: Whether to include the package itself in the result.
|
|
476
|
+
|
|
477
|
+
Returns:
|
|
478
|
+
A set of imported module objects representing dependents.
|
|
479
|
+
"""
|
|
480
|
+
target = package.__name__.lower()
|
|
481
|
+
if target not in self:
|
|
482
|
+
msg = f"Package '{target}' not found in dependency graph"
|
|
483
|
+
raise ValueError(msg)
|
|
484
|
+
|
|
485
|
+
dependents = nx.ancestors(self, target)
|
|
486
|
+
if include_self:
|
|
487
|
+
dependents.add(target)
|
|
488
|
+
|
|
489
|
+
return self.import_packages(dependents)
|
|
490
|
+
|
|
491
|
+
@staticmethod
|
|
492
|
+
def import_packages(names: set[str]) -> set[ModuleType]:
|
|
493
|
+
"""Attempt to import all module names that can be resolved."""
|
|
494
|
+
modules: set[ModuleType] = set()
|
|
495
|
+
for name in names:
|
|
496
|
+
spec = importlib.util.find_spec(name)
|
|
497
|
+
if spec is not None:
|
|
498
|
+
modules.add(importlib.import_module(name))
|
|
499
|
+
return modules
|
|
500
|
+
|
|
501
|
+
def get_all_depending_on_winipedia_utils(
|
|
502
|
+
self, *, include_winipedia_utils: bool = False
|
|
503
|
+
) -> set[ModuleType]:
|
|
504
|
+
"""Return all packages that directly or indirectly depend on winipedia_utils."""
|
|
505
|
+
if get_src_package() == winipedia_utils:
|
|
506
|
+
deps: set[ModuleType] = set()
|
|
507
|
+
else:
|
|
508
|
+
deps = self.get_all_depending_on(winipedia_utils, include_self=False)
|
|
509
|
+
if include_winipedia_utils:
|
|
510
|
+
deps.add(winipedia_utils)
|
|
511
|
+
return deps
|
|
@@ -5,6 +5,7 @@ from typing import Any, cast
|
|
|
5
5
|
|
|
6
6
|
from winipedia_utils.modules.package import get_src_package, make_name_from_package
|
|
7
7
|
from winipedia_utils.projects.poetry.poetry import VersionConstraint
|
|
8
|
+
from winipedia_utils.testing.config import ExperimentConfigFile
|
|
8
9
|
from winipedia_utils.testing.convention import TESTS_PACKAGE_NAME
|
|
9
10
|
from winipedia_utils.text.config import ConfigFile, TomlConfigFile
|
|
10
11
|
|
|
@@ -62,7 +63,9 @@ class PyprojectConfigFile(TomlConfigFile):
|
|
|
62
63
|
"files": ".",
|
|
63
64
|
},
|
|
64
65
|
"pytest": {"ini_options": {"testpaths": [TESTS_PACKAGE_NAME]}},
|
|
65
|
-
"bandit": {
|
|
66
|
+
"bandit": {
|
|
67
|
+
"exclude_dirs": [ExperimentConfigFile.get_path().as_posix()],
|
|
68
|
+
},
|
|
66
69
|
},
|
|
67
70
|
}
|
|
68
71
|
|
|
@@ -9,10 +9,9 @@ import tomlkit
|
|
|
9
9
|
import yaml
|
|
10
10
|
from dotenv import dotenv_values
|
|
11
11
|
|
|
12
|
-
import winipedia_utils
|
|
13
12
|
from winipedia_utils.iterating.iterate import nested_structure_is_subset
|
|
14
13
|
from winipedia_utils.modules.class_ import init_all_nonabstract_subclasses
|
|
15
|
-
from winipedia_utils.modules.package import get_src_package
|
|
14
|
+
from winipedia_utils.modules.package import DependencyGraph, get_src_package
|
|
16
15
|
from winipedia_utils.projects.poetry.poetry import (
|
|
17
16
|
get_python_module_script,
|
|
18
17
|
)
|
|
@@ -149,8 +148,14 @@ class ConfigFile(ABC):
|
|
|
149
148
|
@classmethod
|
|
150
149
|
def init_config_files(cls) -> None:
|
|
151
150
|
"""Initialize all subclasses."""
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
pkgs_depending_on_winipedia_utils = (
|
|
152
|
+
DependencyGraph().get_all_depending_on_winipedia_utils(
|
|
153
|
+
include_winipedia_utils=True
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
pkgs_depending_on_winipedia_utils.add(get_src_package())
|
|
157
|
+
for pkg in pkgs_depending_on_winipedia_utils:
|
|
158
|
+
init_all_nonabstract_subclasses(cls, load_package_before=pkg)
|
|
154
159
|
|
|
155
160
|
@staticmethod
|
|
156
161
|
def get_python_setup_script() -> str:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/concurrent/multiprocessing.py
RENAMED
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/concurrent/multithreading.py
RENAMED
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/data/dataframe/__init__.py
RENAMED
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/data/dataframe/cleaning.py
RENAMED
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/data/structures/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/repo/__init__.py
RENAMED
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/repo/protect.py
RENAMED
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/workflows/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/workflows/base/base.py
RENAMED
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/workflows/publish.py
RENAMED
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/github/workflows/release.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/gitignore/gitignore.py
RENAMED
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/pre_commit/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/git/pre_commit/run_hooks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/projects/poetry/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/download_arrow.svg
RENAMED
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/fullscreen_icon.svg
RENAMED
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/menu_icon.svg
RENAMED
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/pause_icon.svg
RENAMED
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/play_icon.svg
RENAMED
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/resources/svgs/plus_icon.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{winipedia_utils-0.4.41 → winipedia_utils-0.4.46}/winipedia_utils/testing/tests/base/utils/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|