hunterMakesPy 0.3.3__py3-none-any.whl → 0.4.0__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.
- hunterMakesPy/Z0Z_CallableFunction.py +70 -0
- hunterMakesPy/__init__.py +8 -1
- hunterMakesPy/coping.py +2 -4
- hunterMakesPy/pytestForYourUse.py +1 -2
- hunterMakesPy/tests/conftest.py +79 -5
- hunterMakesPy/tests/test_coping.py +258 -153
- hunterMakesPy/tests/test_dataStructures.py +250 -69
- hunterMakesPy/tests/test_filesystemToolkit.py +245 -131
- hunterMakesPy/tests/test_parseParameters.py +63 -7
- hunterMakesPy/tests/test_theTypes.py +359 -0
- hunterMakesPy/theTypes.py +5 -6
- {huntermakespy-0.3.3.dist-info → huntermakespy-0.4.0.dist-info}/METADATA +2 -3
- huntermakespy-0.4.0.dist-info/RECORD +22 -0
- {huntermakespy-0.3.3.dist-info → huntermakespy-0.4.0.dist-info}/WHEEL +1 -1
- huntermakespy-0.3.3.dist-info/RECORD +0 -20
- {huntermakespy-0.3.3.dist-info → huntermakespy-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {huntermakespy-0.3.3.dist-info → huntermakespy-0.4.0.dist-info}/top_level.txt +0 -0
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
"""Tests for the coping mechanism module.
|
|
2
|
+
|
|
3
|
+
(AI generated docstring)
|
|
4
|
+
|
|
5
|
+
This module validates the behavior of package setting retrieval,
|
|
6
|
+
null-check utilities, and installation path resolution.
|
|
7
|
+
|
|
8
|
+
"""
|
|
1
9
|
from hunterMakesPy import PackageSettings, raiseIfNone
|
|
2
10
|
from hunterMakesPy.coping import getIdentifierPackagePACKAGING, getPathPackageINSTALLING
|
|
3
11
|
from hunterMakesPy.tests.conftest import uniformTestFailureMessage
|
|
@@ -5,212 +13,309 @@ from pathlib import Path
|
|
|
5
13
|
import pytest
|
|
6
14
|
|
|
7
15
|
@pytest.mark.parametrize(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
"returnTarget, expected",
|
|
17
|
+
[
|
|
18
|
+
(13, 13),
|
|
19
|
+
(17, 17),
|
|
20
|
+
("fibonacci", "fibonacci"),
|
|
21
|
+
("prime", "prime"),
|
|
22
|
+
([], []),
|
|
23
|
+
({}, {}),
|
|
24
|
+
(False, False),
|
|
25
|
+
(0, 0),
|
|
26
|
+
]
|
|
19
27
|
)
|
|
20
28
|
def testRaiseIfNoneReturnsNonNoneValues(returnTarget: object, expected: object) -> None:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
"""Verify that non-None values are returned exactly as provided.
|
|
30
|
+
|
|
31
|
+
(AI generated docstring)
|
|
24
32
|
|
|
33
|
+
Parameters
|
|
34
|
+
----------
|
|
35
|
+
returnTarget : object
|
|
36
|
+
The value to pass to `raiseIfNone`.
|
|
37
|
+
expected : object
|
|
38
|
+
The expected return value (should be identical to `returnTarget`).
|
|
39
|
+
|
|
40
|
+
"""
|
|
41
|
+
actual: object = raiseIfNone(returnTarget)
|
|
42
|
+
assert actual == expected, uniformTestFailureMessage(expected, actual, "testRaiseIfNoneReturnsNonNoneValues", returnTarget)
|
|
43
|
+
assert actual is returnTarget, uniformTestFailureMessage(returnTarget, actual, "testRaiseIfNoneReturnsNonNoneValues identity check", returnTarget)
|
|
25
44
|
|
|
26
45
|
def testRaiseIfNoneRaisesValueErrorWhenGivenNone() -> None:
|
|
27
|
-
|
|
28
|
-
|
|
46
|
+
"""Verify that ValueError is raised when input is None.
|
|
47
|
+
|
|
48
|
+
(AI generated docstring)
|
|
29
49
|
|
|
50
|
+
"""
|
|
51
|
+
with pytest.raises(ValueError, match=r"A function unexpectedly returned `None`.*"):
|
|
52
|
+
raiseIfNone(None)
|
|
30
53
|
|
|
31
54
|
@pytest.mark.parametrize(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
55
|
+
"customMessage",
|
|
56
|
+
[
|
|
57
|
+
"Configuration must include 'host' setting",
|
|
58
|
+
"Database connection failed",
|
|
59
|
+
"User input is required",
|
|
60
|
+
"Network request returned empty response",
|
|
61
|
+
]
|
|
39
62
|
)
|
|
40
63
|
def testRaiseIfNoneRaisesValueErrorWithCustomMessage(customMessage: str) -> None:
|
|
41
|
-
|
|
42
|
-
|
|
64
|
+
"""Verify that custom error messages are used when provided.
|
|
65
|
+
|
|
66
|
+
(AI generated docstring)
|
|
43
67
|
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
customMessage : str
|
|
71
|
+
The custom error message to expect.
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
with pytest.raises(ValueError, match=customMessage):
|
|
75
|
+
raiseIfNone(None, customMessage)
|
|
44
76
|
|
|
45
77
|
def testRaiseIfNoneWithEmptyStringMessage() -> None:
|
|
46
|
-
|
|
47
|
-
|
|
78
|
+
"""Verify that empty custom message string triggers default message.
|
|
79
|
+
|
|
80
|
+
(AI generated docstring)
|
|
48
81
|
|
|
82
|
+
"""
|
|
83
|
+
with pytest.raises(ValueError, match=r"A function unexpectedly returned `None`.*"):
|
|
84
|
+
raiseIfNone(None, "")
|
|
49
85
|
|
|
50
86
|
def testRaiseIfNonePreservesTypeAnnotations() -> None:
|
|
51
|
-
|
|
52
|
-
|
|
87
|
+
"""Verify that type info is preserved through the pass-through.
|
|
88
|
+
|
|
89
|
+
(AI generated docstring)
|
|
53
90
|
|
|
54
|
-
|
|
55
|
-
|
|
91
|
+
"""
|
|
92
|
+
integerValue: int = raiseIfNone(23)
|
|
93
|
+
assert isinstance(integerValue, int), uniformTestFailureMessage(int, type(integerValue), "testRaiseIfNonePreservesTypeAnnotations", integerValue)
|
|
56
94
|
|
|
57
|
-
|
|
58
|
-
|
|
95
|
+
stringValue: str = raiseIfNone("cardinal")
|
|
96
|
+
assert isinstance(stringValue, str), uniformTestFailureMessage(str, type(stringValue), "testRaiseIfNonePreservesTypeAnnotations", stringValue)
|
|
97
|
+
|
|
98
|
+
listValue: list[int] = raiseIfNone([29, 31])
|
|
99
|
+
assert isinstance(listValue, list), uniformTestFailureMessage(list, type(listValue), "testRaiseIfNonePreservesTypeAnnotations", listValue)
|
|
59
100
|
|
|
60
101
|
# Tests for PackageSettings dataclass
|
|
61
102
|
@pytest.mark.parametrize(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
103
|
+
"identifierPackageFALLBACK, expectedIdentifierPackage",
|
|
104
|
+
[
|
|
105
|
+
("astToolFactory", "hunterMakesPy"), # Should read from pyproject.toml
|
|
106
|
+
("nonExistentPackage", "hunterMakesPy"), # Should read from pyproject.toml
|
|
107
|
+
("customPackage", "hunterMakesPy"), # Should read from pyproject.toml
|
|
108
|
+
]
|
|
68
109
|
)
|
|
69
110
|
def testPackageSettingsWithFallbackUsesProjectToml(identifierPackageFALLBACK: str, expectedIdentifierPackage: str) -> None:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
111
|
+
"""Test that PackageSettings reads package name from pyproject.toml when using fallback.
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
identifierPackageFALLBACK : str
|
|
116
|
+
The fallback identifier to use if retrieval fails (or to trigger lookup).
|
|
117
|
+
expectedIdentifierPackage : str
|
|
118
|
+
The expected resolved package identifier.
|
|
119
|
+
|
|
120
|
+
"""
|
|
121
|
+
packageSettings: PackageSettings = PackageSettings(identifierPackageFALLBACK)
|
|
122
|
+
assert packageSettings.identifierPackage == expectedIdentifierPackage, uniformTestFailureMessage(
|
|
123
|
+
expectedIdentifierPackage, packageSettings.identifierPackage, "PackageSettings fallback", identifierPackageFALLBACK
|
|
124
|
+
)
|
|
75
125
|
|
|
76
126
|
@pytest.mark.parametrize(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
127
|
+
"explicitIdentifierPackage, expectedIdentifierPackage",
|
|
128
|
+
[
|
|
129
|
+
("customPackageName", "customPackageName"),
|
|
130
|
+
("fibonacci", "fibonacci"),
|
|
131
|
+
("prime", "prime"),
|
|
132
|
+
("astToolFactory", "astToolFactory"),
|
|
133
|
+
]
|
|
84
134
|
)
|
|
85
135
|
def testPackageSettingsWithExplicitIdentifierPackage(explicitIdentifierPackage: str, expectedIdentifierPackage: str) -> None:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
136
|
+
"""Test that PackageSettings respects explicitly provided identifierPackage.
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
explicitIdentifierPackage : str
|
|
141
|
+
The explicitly provided package identifier.
|
|
142
|
+
expectedIdentifierPackage : str
|
|
143
|
+
The expected resolved package identifier.
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
packageSettings: PackageSettings = PackageSettings(identifierPackage=explicitIdentifierPackage)
|
|
147
|
+
assert packageSettings.identifierPackage == expectedIdentifierPackage, uniformTestFailureMessage(
|
|
148
|
+
expectedIdentifierPackage, packageSettings.identifierPackage, "PackageSettings explicit identifierPackage", explicitIdentifierPackage
|
|
149
|
+
)
|
|
91
150
|
|
|
92
151
|
@pytest.mark.parametrize(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
152
|
+
"explicitPathPackage, expectedPathPackage",
|
|
153
|
+
[
|
|
154
|
+
(Path("C:/fibonacci/path"), Path("C:/fibonacci/path")),
|
|
155
|
+
(Path("C:/prime/directory"), Path("C:/prime/directory")),
|
|
156
|
+
(Path("/usr/local/lib/package"), Path("/usr/local/lib/package")),
|
|
157
|
+
(Path("relative/path"), Path("relative/path")),
|
|
158
|
+
]
|
|
100
159
|
)
|
|
101
160
|
def testPackageSettingsWithExplicitPathPackage(explicitPathPackage: Path, expectedPathPackage: Path) -> None:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
161
|
+
"""Test that PackageSettings respects explicitly provided pathPackage.
|
|
162
|
+
|
|
163
|
+
Parameters
|
|
164
|
+
----------
|
|
165
|
+
explicitPathPackage : Path
|
|
166
|
+
The explicitly provided package path.
|
|
167
|
+
expectedPathPackage : Path
|
|
168
|
+
The expected resolved package path.
|
|
169
|
+
|
|
170
|
+
"""
|
|
171
|
+
packageSettings: PackageSettings = PackageSettings(pathPackage=explicitPathPackage)
|
|
172
|
+
assert packageSettings.pathPackage == expectedPathPackage, uniformTestFailureMessage(
|
|
173
|
+
expectedPathPackage, packageSettings.pathPackage, "PackageSettings explicit pathPackage", explicitPathPackage
|
|
174
|
+
)
|
|
107
175
|
|
|
108
176
|
@pytest.mark.parametrize(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
177
|
+
"fileExtension, expectedFileExtension",
|
|
178
|
+
[
|
|
179
|
+
(".fibonacci", ".fibonacci"),
|
|
180
|
+
(".prime", ".prime"),
|
|
181
|
+
(".txt", ".txt"),
|
|
182
|
+
(".md", ".md"),
|
|
183
|
+
(".json", ".json"),
|
|
184
|
+
]
|
|
117
185
|
)
|
|
118
186
|
def testPackageSettingsWithCustomFileExtension(fileExtension: str, expectedFileExtension: str) -> None:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
187
|
+
"""Test that PackageSettings respects custom file extensions.
|
|
188
|
+
|
|
189
|
+
Parameters
|
|
190
|
+
----------
|
|
191
|
+
fileExtension : str
|
|
192
|
+
The custom file extension to set.
|
|
193
|
+
expectedFileExtension : str
|
|
194
|
+
The expected file extension in the settings.
|
|
195
|
+
|
|
196
|
+
"""
|
|
197
|
+
packageSettings: PackageSettings = PackageSettings(fileExtension=fileExtension)
|
|
198
|
+
assert packageSettings.fileExtension == expectedFileExtension, uniformTestFailureMessage(
|
|
199
|
+
expectedFileExtension, packageSettings.fileExtension, "PackageSettings custom fileExtension", fileExtension
|
|
200
|
+
)
|
|
124
201
|
|
|
125
202
|
def testPackageSettingsDefaultValues() -> None:
|
|
126
|
-
|
|
127
|
-
|
|
203
|
+
"""Test that PackageSettings has correct default values when no arguments provided."""
|
|
204
|
+
packageSettings: PackageSettings = PackageSettings()
|
|
128
205
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
206
|
+
# Should have default file extension
|
|
207
|
+
assert packageSettings.fileExtension == '.py', uniformTestFailureMessage(
|
|
208
|
+
'.py', packageSettings.fileExtension, "PackageSettings default fileExtension"
|
|
209
|
+
)
|
|
133
210
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
211
|
+
# identifierPackage should be empty when no fallback provided
|
|
212
|
+
assert packageSettings.identifierPackage == '', uniformTestFailureMessage(
|
|
213
|
+
'', packageSettings.identifierPackage, "PackageSettings default identifierPackage"
|
|
214
|
+
)
|
|
138
215
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
)
|
|
216
|
+
expectedPath: Path = Path()
|
|
217
|
+
assert packageSettings.pathPackage == expectedPath, uniformTestFailureMessage(
|
|
218
|
+
expectedPath, packageSettings.pathPackage, "PackageSettings default pathPackage, pathPackage should remain as Path() when identifierPackage is empty"
|
|
219
|
+
)
|
|
144
220
|
|
|
145
221
|
@pytest.mark.parametrize(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
222
|
+
"identifierPackageFALLBACK, identifierPackage, pathPackage, fileExtension",
|
|
223
|
+
[
|
|
224
|
+
("fallback", "custom", Path("C:/custom/path"), ".txt"),
|
|
225
|
+
("fibonacci", "prime", Path("C:/fibonacci/lib"), ".md"),
|
|
226
|
+
("defaultFallback", "overridePackage", Path("/usr/local/override"), ".json"),
|
|
227
|
+
]
|
|
152
228
|
)
|
|
153
229
|
def testPackageSettingsAllParametersCombined(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
230
|
+
identifierPackageFALLBACK: str,
|
|
231
|
+
identifierPackage: str,
|
|
232
|
+
pathPackage: Path,
|
|
233
|
+
fileExtension: str
|
|
158
234
|
) -> None:
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
235
|
+
"""Test PackageSettings with all parameters provided.
|
|
236
|
+
|
|
237
|
+
Parameters
|
|
238
|
+
----------
|
|
239
|
+
identifierPackageFALLBACK : str
|
|
240
|
+
The fallback identifier.
|
|
241
|
+
identifierPackage : str
|
|
242
|
+
The explicit package identifier.
|
|
243
|
+
pathPackage : Path
|
|
244
|
+
The explicit package path.
|
|
245
|
+
fileExtension : str
|
|
246
|
+
The explicit file extension.
|
|
247
|
+
|
|
248
|
+
"""
|
|
249
|
+
packageSettings: PackageSettings = PackageSettings(
|
|
250
|
+
identifierPackageFALLBACK
|
|
251
|
+
, identifierPackage=identifierPackage
|
|
252
|
+
, pathPackage=pathPackage
|
|
253
|
+
, fileExtension=fileExtension
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
assert packageSettings.identifierPackage == identifierPackage, uniformTestFailureMessage(
|
|
257
|
+
identifierPackage, packageSettings.identifierPackage, "PackageSettings combined identifierPackage"
|
|
258
|
+
)
|
|
259
|
+
assert packageSettings.pathPackage == pathPackage, uniformTestFailureMessage(
|
|
260
|
+
pathPackage, packageSettings.pathPackage, "PackageSettings combined pathPackage"
|
|
261
|
+
)
|
|
262
|
+
assert packageSettings.fileExtension == fileExtension, uniformTestFailureMessage(
|
|
263
|
+
fileExtension, packageSettings.fileExtension, "PackageSettings combined fileExtension"
|
|
264
|
+
)
|
|
176
265
|
|
|
177
266
|
def testPackageSettingsFallbackIgnoredWhenExplicitIdentifierProvided() -> None:
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
267
|
+
"""Test that fallback is ignored when explicit identifierPackage is provided."""
|
|
268
|
+
packageSettings: PackageSettings = PackageSettings("shouldBeIgnored", identifierPackage="explicit")
|
|
269
|
+
assert packageSettings.identifierPackage == "explicit", uniformTestFailureMessage(
|
|
270
|
+
"explicit", packageSettings.identifierPackage, "PackageSettings fallback ignored"
|
|
271
|
+
)
|
|
183
272
|
|
|
184
273
|
# Tests for helper functions
|
|
185
274
|
@pytest.mark.parametrize(
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
275
|
+
"identifierPackageFALLBACK, expectedResult",
|
|
276
|
+
[
|
|
277
|
+
("fibonacci", "hunterMakesPy"), # Should read from pyproject.toml
|
|
278
|
+
("prime", "hunterMakesPy"), # Should read from pyproject.toml
|
|
279
|
+
("nonExistentPackage", "hunterMakesPy"), # Should read from pyproject.toml
|
|
280
|
+
]
|
|
192
281
|
)
|
|
193
282
|
def testGetIdentifierPackagePACKAGING(identifierPackageFALLBACK: str, expectedResult: str) -> None:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
283
|
+
"""Test that getIdentifierPackagePACKAGING reads from pyproject.toml correctly.
|
|
284
|
+
|
|
285
|
+
Parameters
|
|
286
|
+
----------
|
|
287
|
+
identifierPackageFALLBACK : str
|
|
288
|
+
The fallback identifier to provide.
|
|
289
|
+
expectedResult : str
|
|
290
|
+
The expected package identifier result.
|
|
291
|
+
|
|
292
|
+
"""
|
|
293
|
+
actual: str = getIdentifierPackagePACKAGING(identifierPackageFALLBACK)
|
|
294
|
+
assert actual == expectedResult, uniformTestFailureMessage(
|
|
295
|
+
expectedResult, actual, "getIdentifierPackagePACKAGING", identifierPackageFALLBACK
|
|
296
|
+
)
|
|
199
297
|
|
|
200
298
|
@pytest.mark.parametrize(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
299
|
+
"identifierPackage",
|
|
300
|
+
[
|
|
301
|
+
"hunterMakesPy", # This package exists
|
|
302
|
+
"fibonacci", # Non-existent package should fallback to cwd
|
|
303
|
+
"prime", # Non-existent package should fallback to cwd
|
|
304
|
+
]
|
|
207
305
|
)
|
|
208
306
|
def testGetPathPackageINSTALLING(identifierPackage: str) -> None:
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
307
|
+
"""Test that getPathPackageINSTALLING returns valid Path objects.
|
|
308
|
+
|
|
309
|
+
Parameters
|
|
310
|
+
----------
|
|
311
|
+
identifierPackage : str
|
|
312
|
+
The package identifier to look up.
|
|
313
|
+
|
|
314
|
+
"""
|
|
315
|
+
actual: Path = getPathPackageINSTALLING(identifierPackage)
|
|
316
|
+
assert isinstance(actual, Path), uniformTestFailureMessage(
|
|
317
|
+
Path, type(actual), "getPathPackageINSTALLING type", identifierPackage
|
|
318
|
+
)
|
|
319
|
+
assert actual.exists() or actual == Path.cwd(), uniformTestFailureMessage(
|
|
320
|
+
"existing path or cwd", actual, "getPathPackageINSTALLING existence", identifierPackage
|
|
321
|
+
)
|