winipedia-utils 0.1.0__py3-none-any.whl → 0.1.1__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.
@@ -0,0 +1 @@
1
+ """__init__ module for winipedia_utils.git.gitignore."""
@@ -37,13 +37,7 @@ def path_is_in_gitignore(relative_path: str | Path) -> bool:
37
37
  if is_dir and not as_posix.endswith("/"):
38
38
  as_posix += "/"
39
39
 
40
- gitignore_path = Path(".gitignore")
41
- if not gitignore_path.exists():
42
- return False # No ignore rules
43
-
44
- spec = pathspec.PathSpec.from_lines(
45
- "gitwildmatch", gitignore_path.read_text().splitlines()
46
- )
40
+ spec = pathspec.PathSpec.from_lines("gitwildmatch", load_gitignore())
47
41
 
48
42
  return spec.match_file(as_posix)
49
43
 
@@ -78,3 +72,65 @@ def walk_os_skipping_gitignore_patterns(
78
72
  valid_dirs = [d for d in dirs if not path_is_in_gitignore(rel_root / d)]
79
73
 
80
74
  yield rel_root, valid_dirs, valid_files
75
+
76
+
77
+ def load_gitignore() -> list[str]:
78
+ """Load the .gitignore file."""
79
+ gitignore_path = Path(".gitignore")
80
+ if not gitignore_path.exists():
81
+ gitignore_path.touch()
82
+ return gitignore_path.read_text().splitlines()
83
+
84
+
85
+ def dump_gitignore(patterns: list[str]) -> None:
86
+ """Dump the given patterns to a .gitignore file (overwrites it)."""
87
+ gitignore_path = Path(".gitignore")
88
+ gitignore_path.write_text("\n".join(patterns))
89
+
90
+
91
+ def add_patterns_to_gitignore(patterns: list[str]) -> None:
92
+ """Add the given patterns to the .gitignore file."""
93
+ existing_patterns = load_gitignore()
94
+ new_patterns = [p for p in patterns if p not in existing_patterns]
95
+ if new_patterns:
96
+ logger.info("Adding patterns to .gitignore: %s", new_patterns)
97
+ dump_gitignore(existing_patterns + new_patterns)
98
+
99
+
100
+ def _get_gitignore_patterns() -> list[str]:
101
+ """Get the patterns that should be in the .gitignore file.
102
+
103
+ Those are the patterns that should be in there when using winipedia_utils.
104
+ """
105
+ return [
106
+ "__pycache__/",
107
+ ".idea/",
108
+ ".mypy_cache/",
109
+ ".pytest_cache/",
110
+ ".ruff_cache/",
111
+ ".vscode/",
112
+ "dist/",
113
+ "test.py", # I use this for testing code
114
+ ".git/", # ignore the .git folder for walk_os_skipping_gitignore_patterns func
115
+ ]
116
+
117
+
118
+ def _get_missing_patterns() -> list[str]:
119
+ """Get the patterns that are in the .gitignore file but shouldn't be."""
120
+ needed_patterns = _get_gitignore_patterns()
121
+ existing_patterns = load_gitignore()
122
+ return [p for p in needed_patterns if p not in existing_patterns]
123
+
124
+
125
+ def _gitignore_is_correct() -> bool:
126
+ """Check if the .gitignore file contains all the patterns it should."""
127
+ missing_patterns = _get_missing_patterns()
128
+ return not missing_patterns
129
+
130
+
131
+ def _add_package_patterns_to_gitignore() -> None:
132
+ """Add any missing patterns to the .gitignore file."""
133
+ if _gitignore_is_correct():
134
+ return
135
+ missing_patterns = _get_missing_patterns()
136
+ add_patterns_to_gitignore(missing_patterns)
@@ -19,7 +19,10 @@ from types import ModuleType
19
19
  from setuptools import find_namespace_packages as _find_namespace_packages
20
20
  from setuptools import find_packages as _find_packages
21
21
 
22
- from winipedia_utils.git.gitignore import walk_os_skipping_gitignore_patterns
22
+ from winipedia_utils.git.gitignore.gitignore import (
23
+ load_gitignore,
24
+ walk_os_skipping_gitignore_patterns,
25
+ )
23
26
  from winipedia_utils.logging.logger import get_logger
24
27
 
25
28
  logger = get_logger(__name__)
@@ -148,7 +151,7 @@ def find_packages(
148
151
  depth: int | None = None,
149
152
  include_namespace_packages: bool = False,
150
153
  where: str = ".",
151
- exclude: Iterable[str] = (),
154
+ exclude: Iterable[str] | None = None,
152
155
  include: Iterable[str] = ("*",),
153
156
  ) -> list[str]:
154
157
  """Discover Python packages in the specified directory.
@@ -172,6 +175,11 @@ def find_packages(
172
175
  find_packages(depth=1) might return ["package1", "package2"]
173
176
 
174
177
  """
178
+ if exclude is None:
179
+ exclude = load_gitignore()
180
+ exclude = [
181
+ p.replace("/", ".").removesuffix(".") for p in exclude if p.endswith("/")
182
+ ]
175
183
  if include_namespace_packages:
176
184
  package_names = _find_namespace_packages(
177
185
  where=where, exclude=exclude, include=include
@@ -193,7 +201,7 @@ def find_packages_as_modules(
193
201
  depth: int | None = None,
194
202
  include_namespace_packages: bool = False,
195
203
  where: str = ".",
196
- exclude: Iterable[str] = (),
204
+ exclude: Iterable[str] | None = None,
197
205
  include: Iterable[str] = ("*",),
198
206
  ) -> list[ModuleType]:
199
207
  """Discover and import Python packages in the specified directory.
winipedia_utils/setup.py CHANGED
@@ -6,6 +6,7 @@ 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 winipedia_utils.git.gitignore.gitignore import _add_package_patterns_to_gitignore
9
10
  from winipedia_utils.git.pre_commit.config import _add_package_hook_to_pre_commit_config
10
11
  from winipedia_utils.git.pre_commit.run_hooks import _run_all_hooks
11
12
  from winipedia_utils.logging.logger import get_logger
@@ -25,6 +26,8 @@ def _setup() -> None:
25
26
  _install_dev_dependencies()
26
27
  # create pre-commit config
27
28
  _add_package_hook_to_pre_commit_config()
29
+ # add patterns to .gitignore
30
+ _add_package_patterns_to_gitignore()
28
31
  # add tool.* configurations to pyproject.toml
29
32
  _add_tool_configurations_to_pyproject_toml()
30
33
  # run pre-commit once, create tests is included here
@@ -10,6 +10,7 @@ from importlib import import_module
10
10
  from pathlib import Path
11
11
 
12
12
  from winipedia_utils.consts import _DEV_DEPENDENCIES
13
+ from winipedia_utils.git.gitignore.gitignore import _gitignore_is_correct
13
14
  from winipedia_utils.git.pre_commit.config import (
14
15
  _pre_commit_config_is_correct,
15
16
  )
@@ -130,6 +131,29 @@ def _test_pre_commit_config_yaml_is_correct() -> None:
130
131
  )
131
132
 
132
133
 
134
+ @autouse_session_fixture
135
+ def _test_gitignore_is_correct() -> None:
136
+ """Verify that the .gitignore file exists and has the correct content.
137
+
138
+ This fixture runs once per test session and checks that the .gitignore file
139
+ exists in the root directory and contains the correct content.
140
+
141
+ Raises:
142
+ AssertionError: If the .gitignore file doesn't exist
143
+ or has incorrect content
144
+
145
+ """
146
+ gitignore_path = Path(".gitignore")
147
+ assert_with_msg(
148
+ gitignore_path.is_file(),
149
+ f"Expected {gitignore_path} to exist but it doesn't.",
150
+ )
151
+ assert_with_msg(
152
+ _gitignore_is_correct(),
153
+ "Gitignore is not correct.",
154
+ )
155
+
156
+
133
157
  @autouse_session_fixture
134
158
  def _test_no_namespace_packages() -> None:
135
159
  """Verify that there are no namespace packages in the project.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: winipedia-utils
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: A package with many utility functions
5
5
  License: MIT
6
6
  Author: Winipedia
@@ -11,7 +11,8 @@ winipedia_utils/django/bulk.py,sha256=7MLfq83xanxbVFo4ANdtcYv5S-oQwdrNkH5ljPzjKL
11
11
  winipedia_utils/django/command.py,sha256=ENEg_crSbnm3nQIks-j2DjjAfeZ7ppJkZOyw__IpSYw,13824
12
12
  winipedia_utils/django/database.py,sha256=tH8AA5LTMYY-co8R_pI6xs0SrmJqjrOEJUJdnWc4TBE,11487
13
13
  winipedia_utils/git/__init__.py,sha256=pPo5DDqaQkFim8L6x22DXjqthLnKAxLyXlXl7JXGUdw,48
14
- winipedia_utils/git/gitignore.py,sha256=iliNf_FBfcnyGW2zjoh1yg5fOVvSAISt9vOJb10rAUs,2551
14
+ winipedia_utils/git/gitignore/__init__.py,sha256=t65uvpOaNvh7ICgwuJFRr7vS2nWfxzWUGIpnJs0_jzE,58
15
+ winipedia_utils/git/gitignore/gitignore.py,sha256=wCU2lRztTFKQ7JrKnCqPLCsuVRjfx8wGfTy42BLgFJI,4512
15
16
  winipedia_utils/git/pre_commit/__init__.py,sha256=2sBe5nOqmm3qb8YjhZzE4tCHhqxWOZ6R2ECljSVG7i4,59
16
17
  winipedia_utils/git/pre_commit/config.py,sha256=MUgk-43kd5l0cRk9VKzMQl88bDodsN8rSZcMzSzPpQw,1959
17
18
  winipedia_utils/git/pre_commit/hooks.py,sha256=Q6rXvbpUf9UasQ8vSBruoLA-wjm37jamvIUkXJ1B3FE,3210
@@ -26,7 +27,7 @@ winipedia_utils/modules/__init__.py,sha256=e3CFaC3FhK4ibknFOv1bqOZxA7XeVwmLqWX7o
26
27
  winipedia_utils/modules/class_.py,sha256=RDjal6QYYs9z81DT1mIFrnEhQ9vgN2tCAYN1WWnN24Y,2462
27
28
  winipedia_utils/modules/function.py,sha256=Qn1OPV5dwO-7f3a0f0RpWcrH-E9teGPwldRtwbFYzRM,2551
28
29
  winipedia_utils/modules/module.py,sha256=iJwUJPhVkxyRjJqHVVWh3GNJFiYf45ZdSfR21puQAmw,12673
29
- winipedia_utils/modules/package.py,sha256=CKyeT4Pb2KBzpCM-tHxnC1kq6XvU7W7pWLz1W-wJiv0,12245
30
+ winipedia_utils/modules/package.py,sha256=77DiJmIUrsSsJHAdBZwA8iCi5gv2KSmFCwYyF1uvWLw,12485
30
31
  winipedia_utils/oop/__init__.py,sha256=wGjsVwLbTVEQWOfDJvN9nlvC-3NmAi8Doc2xIrm6e78,47
31
32
  winipedia_utils/oop/mixins/__init__.py,sha256=PDK-cJcdRUfDUCz36qQ5pmMW07G133WtN49OpmILGNI,54
32
33
  winipedia_utils/oop/mixins/meta.py,sha256=UpHags1j80OABxW4Q3QYt7A7lLIArvgUrGcWeYJaRyU,10576
@@ -37,7 +38,7 @@ winipedia_utils/projects/__init__.py,sha256=6oTiSlUMAwO5xnH4SGVnvspzKcxrxo9kn1L4
37
38
  winipedia_utils/projects/poetry/__init__.py,sha256=0yNMuu9KmM19od4VBxBV3HLK-RdCsa0e2Zhg33J7RmQ,60
38
39
  winipedia_utils/projects/poetry/config.py,sha256=r8sbhsF26yro5qLg2srjl3s9MftwEbfmE2F9bAFA58E,2976
39
40
  winipedia_utils/projects/poetry/poetry.py,sha256=5jyUSMxhCZ7pz9bOaz5E9r7Da9qIrGOp6wcBzI1y7Cg,932
40
- winipedia_utils/setup.py,sha256=ozdPXwHBRWLSiL2xLfbWnRZ_OHl560eKgP8e94cuDAM,1280
41
+ winipedia_utils/setup.py,sha256=hu-LoIIOEeDa9uUsOSIl5PWrRDjtVCiyucRBjiML1u4,1444
41
42
  winipedia_utils/testing/__init__.py,sha256=kXhB5xw02ec5xpcW_KV--9CBKdyCjnuR-NZzAJ5tq0g,51
42
43
  winipedia_utils/testing/assertions.py,sha256=0JF4mqVTnLQ1qkAL_FuTwyN_idr00rvVlta7aDdnUXA,851
43
44
  winipedia_utils/testing/convention.py,sha256=NxC_hYaUXshsa6LL6nQoEEKpTzC1KwTloKL8aS2gUPI,5010
@@ -52,13 +53,13 @@ winipedia_utils/testing/tests/base/fixtures/scopes/class_.py,sha256=XCx4HZeHbJJ-
52
53
  winipedia_utils/testing/tests/base/fixtures/scopes/function.py,sha256=5dW7-IPqJ_3Q2j1vftZL5FYKvNSKufqiHzLTTWYhja4,309
53
54
  winipedia_utils/testing/tests/base/fixtures/scopes/module.py,sha256=V0H9WFrdSV7uj__bXM_GKcCJnjResqI7fFjcxyvNaZk,1169
54
55
  winipedia_utils/testing/tests/base/fixtures/scopes/package.py,sha256=IKOfj6vfyjEQdRV5cJoPRQvALmePpGxWkGy23di00-w,309
55
- winipedia_utils/testing/tests/base/fixtures/scopes/session.py,sha256=dd8QRSV_zJpz6_r0Xinryar-ciblFxszn0Bh5p2I6Pw,7652
56
+ winipedia_utils/testing/tests/base/fixtures/scopes/session.py,sha256=CP-CY_qsa2bc8FCIvb64LaB_G0C43eGa3Rt8QtnY4LQ,8435
56
57
  winipedia_utils/testing/tests/base/utils/__init__.py,sha256=mC-8dCkp8xarqkQu2QQLrPjHi6Ww9hcixWdHeQHWeRs,68
57
58
  winipedia_utils/testing/tests/base/utils/utils.py,sha256=dUPDrgAxlfREQb33zz23MfzacLLuwjy2AO-PQQp_aSI,2820
58
59
  winipedia_utils/testing/tests/conftest.py,sha256=CvLtsr-KhSPzbQYin6SYZQC1Ez3AzIsqCWhuLuXinAs,826
59
60
  winipedia_utils/text/__init__.py,sha256=j2bwtK6kyeHI6SnoBjpRju0C1W2n2paXBDlNjNtaUxA,48
60
61
  winipedia_utils/text/string.py,sha256=1jbBftlgxffGgSlPnQh3aRPIr8XekEwpSenjFCW6JyM,3478
61
- winipedia_utils-0.1.0.dist-info/LICENSE,sha256=3PrKJ2CWNrnyyHaC_r0wPDSukVWgmjOxHr__eQVH7cw,1087
62
- winipedia_utils-0.1.0.dist-info/METADATA,sha256=_mORtARL4qiNjHVQRf-1FtpYsFmKFhruGwGSa5kzPzg,12311
63
- winipedia_utils-0.1.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
64
- winipedia_utils-0.1.0.dist-info/RECORD,,
62
+ winipedia_utils-0.1.1.dist-info/LICENSE,sha256=3PrKJ2CWNrnyyHaC_r0wPDSukVWgmjOxHr__eQVH7cw,1087
63
+ winipedia_utils-0.1.1.dist-info/METADATA,sha256=UBPvyoK1Hk-0TdpO_7_x2uTtrSp2QQ-ElLvsGyTNzDQ,12311
64
+ winipedia_utils-0.1.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
65
+ winipedia_utils-0.1.1.dist-info/RECORD,,