hunterMakesPy 0.3.3__py3-none-any.whl → 0.3.4__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/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 +420 -0
- hunterMakesPy/theTypes.py +2 -4
- {huntermakespy-0.3.3.dist-info → huntermakespy-0.3.4.dist-info}/METADATA +1 -1
- huntermakespy-0.3.4.dist-info/RECORD +21 -0
- huntermakespy-0.3.3.dist-info/RECORD +0 -20
- {huntermakespy-0.3.3.dist-info → huntermakespy-0.3.4.dist-info}/WHEEL +0 -0
- {huntermakespy-0.3.3.dist-info → huntermakespy-0.3.4.dist-info}/licenses/LICENSE +0 -0
- {huntermakespy-0.3.3.dist-info → huntermakespy-0.3.4.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
# pyright: standard
|
|
2
|
+
"""Tests for filesystem toolkit utilities.
|
|
3
|
+
|
|
4
|
+
(AI generated docstring)
|
|
5
|
+
|
|
6
|
+
This module validates the behavior of file and directory operations,
|
|
7
|
+
including safe directory creation, file writing, and dynamic importing.
|
|
8
|
+
|
|
9
|
+
"""
|
|
2
10
|
from hunterMakesPy import (
|
|
3
11
|
importLogicalPath2Identifier, importPathFilename2Identifier, makeDirsSafely, writePython, writeStringToHere)
|
|
4
12
|
from hunterMakesPy.tests.conftest import standardizedEqualTo
|
|
@@ -18,14 +26,22 @@ import sys
|
|
|
18
26
|
('sys', 'version', None, type(sys.version)),
|
|
19
27
|
]
|
|
20
28
|
)
|
|
21
|
-
def testImportLogicalPath2IdentifierWithAbsolutePaths(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
def testImportLogicalPath2IdentifierWithAbsolutePaths(logicalPathModuleTarget: str, identifierTarget: str, packageIdentifierIfRelativeTarget: str | None, expectedType: type) -> None:
|
|
30
|
+
"""Test importing identifiers from modules using absolute logical paths.
|
|
31
|
+
|
|
32
|
+
Parameters
|
|
33
|
+
----------
|
|
34
|
+
logicalPathModuleTarget : str
|
|
35
|
+
The logical path of the module (e.g., 'os.path').
|
|
36
|
+
identifierTarget : str
|
|
37
|
+
The identifier (function/class) to import.
|
|
38
|
+
packageIdentifierIfRelativeTarget : str | None
|
|
39
|
+
Expected to be None for absolute paths.
|
|
40
|
+
expectedType : type
|
|
41
|
+
The expected type of the imported object.
|
|
42
|
+
|
|
43
|
+
"""
|
|
44
|
+
identifierImported: object = importLogicalPath2Identifier(logicalPathModuleTarget, identifierTarget, packageIdentifierIfRelativeTarget)
|
|
29
45
|
|
|
30
46
|
assert isinstance(identifierImported, expectedType), (
|
|
31
47
|
f"\nTesting: `importLogicalPath2Identifier({logicalPathModuleTarget}, {identifierTarget}, {packageIdentifierIfRelativeTarget})`\n"
|
|
@@ -33,7 +49,6 @@ def testImportLogicalPath2IdentifierWithAbsolutePaths(
|
|
|
33
49
|
f"Got type: {type(identifierImported)}"
|
|
34
50
|
)
|
|
35
51
|
|
|
36
|
-
|
|
37
52
|
@pytest.mark.parametrize(
|
|
38
53
|
"pythonSourceTarget, identifierTarget, moduleIdentifierTarget, expectedValueWhenCalled",
|
|
39
54
|
[
|
|
@@ -43,23 +58,34 @@ def testImportLogicalPath2IdentifierWithAbsolutePaths(
|
|
|
43
58
|
("def fibonacciSequence():\n return 21\n", "fibonacciSequence", "moduleEast", 21),
|
|
44
59
|
]
|
|
45
60
|
)
|
|
46
|
-
def testImportPathFilename2IdentifierWithCallables(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
def testImportPathFilename2IdentifierWithCallables(pathTmpTesting: pathlib.Path, pythonSourceTarget: str, identifierTarget: str, moduleIdentifierTarget: str | None, expectedValueWhenCalled: object) -> None:
|
|
62
|
+
"""Test importing callable identifiers from Python files.
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
pathTmpTesting : pathlib.Path
|
|
67
|
+
Temporary directory fixture.
|
|
68
|
+
pythonSourceTarget : str
|
|
69
|
+
Source code to write to the temporary file.
|
|
70
|
+
identifierTarget : str
|
|
71
|
+
The callable identifier to import.
|
|
72
|
+
moduleIdentifierTarget : str | None
|
|
73
|
+
Optional module name hint.
|
|
74
|
+
expectedValueWhenCalled : object
|
|
75
|
+
The expected return value when calling the imported object.
|
|
76
|
+
|
|
77
|
+
"""
|
|
78
|
+
pathFilenameModule: pathlib.Path = pathTmpTesting / f"moduleTest{hash(pythonSourceTarget) % 89}.py" # Use prime number 89
|
|
55
79
|
pathFilenameModule.write_text(pythonSourceTarget)
|
|
56
80
|
|
|
81
|
+
def callImportedIdentifier() -> object:
|
|
82
|
+
return importPathFilename2Identifier(pathFilenameModule, identifierTarget, moduleIdentifierTarget)()
|
|
83
|
+
|
|
57
84
|
standardizedEqualTo(
|
|
58
85
|
expectedValueWhenCalled,
|
|
59
|
-
|
|
86
|
+
callImportedIdentifier,
|
|
60
87
|
)
|
|
61
88
|
|
|
62
|
-
|
|
63
89
|
@pytest.mark.parametrize(
|
|
64
90
|
"pythonSourceTarget, identifierTarget, moduleIdentifierTarget, expectedValue",
|
|
65
91
|
[
|
|
@@ -69,15 +95,24 @@ def testImportPathFilename2IdentifierWithCallables(
|
|
|
69
95
|
("sequenceValue = 55\n", "sequenceValue", "moduleSouthWest", 55),
|
|
70
96
|
]
|
|
71
97
|
)
|
|
72
|
-
def testImportPathFilename2IdentifierWithVariables(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
98
|
+
def testImportPathFilename2IdentifierWithVariables(pathTmpTesting: pathlib.Path, pythonSourceTarget: str, identifierTarget: str, moduleIdentifierTarget: str | None, expectedValue: object) -> None:
|
|
99
|
+
"""Test importing variable identifiers from Python files.
|
|
100
|
+
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
pathTmpTesting : pathlib.Path
|
|
104
|
+
Temporary directory fixture.
|
|
105
|
+
pythonSourceTarget : str
|
|
106
|
+
Source code to write to the temporary file.
|
|
107
|
+
identifierTarget : str
|
|
108
|
+
The variable identifier to import.
|
|
109
|
+
moduleIdentifierTarget : str | None
|
|
110
|
+
Optional module name hint.
|
|
111
|
+
expectedValue : object
|
|
112
|
+
The expected value of the imported variable.
|
|
113
|
+
|
|
114
|
+
"""
|
|
115
|
+
pathFilenameModule: pathlib.Path = pathTmpTesting / f"moduleTest{hash(pythonSourceTarget) % 97}.py" # Use prime number 97
|
|
81
116
|
pathFilenameModule.write_text(pythonSourceTarget)
|
|
82
117
|
|
|
83
118
|
standardizedEqualTo(
|
|
@@ -88,7 +123,6 @@ def testImportPathFilename2IdentifierWithVariables(
|
|
|
88
123
|
moduleIdentifierTarget
|
|
89
124
|
)
|
|
90
125
|
|
|
91
|
-
|
|
92
126
|
@pytest.mark.parametrize(
|
|
93
127
|
"listDirectoryComponents, filenameTarget",
|
|
94
128
|
[
|
|
@@ -98,17 +132,24 @@ def testImportPathFilename2IdentifierWithVariables(
|
|
|
98
132
|
(['cardinal', 'directions', 'multiple'], 'prime23.txt'),
|
|
99
133
|
]
|
|
100
134
|
)
|
|
101
|
-
def testMakeDirsSafelyCreatesNestedDirectories(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
135
|
+
def testMakeDirsSafelyCreatesNestedDirectories(pathTmpTesting: pathlib.Path, listDirectoryComponents: list[str], filenameTarget: str) -> None:
|
|
136
|
+
"""Test that makeDirsSafely creates nested parent directories.
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
pathTmpTesting : pathlib.Path
|
|
141
|
+
Temporary directory fixture.
|
|
142
|
+
listDirectoryComponents : list[str]
|
|
143
|
+
List of nested directory names.
|
|
144
|
+
filenameTarget : str
|
|
145
|
+
Name of the target file inside the nested directories.
|
|
146
|
+
|
|
147
|
+
"""
|
|
148
|
+
pathDirectoryNested: pathlib.Path = pathTmpTesting
|
|
108
149
|
for directoryComponent in listDirectoryComponents:
|
|
109
150
|
pathDirectoryNested = pathDirectoryNested / directoryComponent
|
|
110
151
|
|
|
111
|
-
pathFilenameTarget = pathDirectoryNested / filenameTarget
|
|
152
|
+
pathFilenameTarget: pathlib.Path = pathDirectoryNested / filenameTarget
|
|
112
153
|
makeDirsSafely(pathFilenameTarget)
|
|
113
154
|
|
|
114
155
|
assert pathDirectoryNested.exists() and pathDirectoryNested.is_dir(), (
|
|
@@ -117,7 +158,6 @@ def testMakeDirsSafelyCreatesNestedDirectories(
|
|
|
117
158
|
f"Got: exists={pathDirectoryNested.exists()}, is_dir={pathDirectoryNested.is_dir() if pathDirectoryNested.exists() else False}"
|
|
118
159
|
)
|
|
119
160
|
|
|
120
|
-
|
|
121
161
|
@pytest.mark.parametrize(
|
|
122
162
|
"streamTypeTarget",
|
|
123
163
|
[
|
|
@@ -126,14 +166,20 @@ def testMakeDirsSafelyCreatesNestedDirectories(
|
|
|
126
166
|
]
|
|
127
167
|
)
|
|
128
168
|
def testMakeDirsSafelyWithIOStreamDoesNotRaise(streamTypeTarget: io.IOBase) -> None:
|
|
129
|
-
"""Test that makeDirsSafely handles IO streams without raising exceptions.
|
|
169
|
+
"""Test that makeDirsSafely handles IO streams without raising exceptions.
|
|
170
|
+
|
|
171
|
+
Parameters
|
|
172
|
+
----------
|
|
173
|
+
streamTypeTarget : io.IOBase
|
|
174
|
+
The IO stream object to test.
|
|
175
|
+
|
|
176
|
+
"""
|
|
130
177
|
# This test verifies that no exception is raised
|
|
131
178
|
makeDirsSafely(streamTypeTarget)
|
|
132
179
|
|
|
133
180
|
# If we reach this point, no exception was raised
|
|
134
181
|
assert True
|
|
135
182
|
|
|
136
|
-
|
|
137
183
|
@pytest.mark.parametrize(
|
|
138
184
|
"listDirectoryComponents, filenameTarget, contentTarget",
|
|
139
185
|
[
|
|
@@ -143,18 +189,26 @@ def testMakeDirsSafelyWithIOStreamDoesNotRaise(streamTypeTarget: io.IOBase) -> N
|
|
|
143
189
|
(['west', 'sequence'], 'test23.txt', 'sequence value 23'),
|
|
144
190
|
]
|
|
145
191
|
)
|
|
146
|
-
def testWriteStringToHereCreatesFileAndDirectories(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
192
|
+
def testWriteStringToHereCreatesFileAndDirectories(pathTmpTesting: pathlib.Path, listDirectoryComponents: list[str], filenameTarget: str, contentTarget: str) -> None:
|
|
193
|
+
"""Test that writeStringToHere creates directories and writes content to files.
|
|
194
|
+
|
|
195
|
+
Parameters
|
|
196
|
+
----------
|
|
197
|
+
pathTmpTesting : pathlib.Path
|
|
198
|
+
Temporary directory fixture.
|
|
199
|
+
listDirectoryComponents : list[str]
|
|
200
|
+
Nested directory names.
|
|
201
|
+
filenameTarget : str
|
|
202
|
+
Target filename.
|
|
203
|
+
contentTarget : str
|
|
204
|
+
Content to write to the file.
|
|
205
|
+
|
|
206
|
+
"""
|
|
207
|
+
pathDirectoryNested: pathlib.Path = pathTmpTesting
|
|
154
208
|
for directoryComponent in listDirectoryComponents:
|
|
155
209
|
pathDirectoryNested = pathDirectoryNested / directoryComponent
|
|
156
210
|
|
|
157
|
-
pathFilenameTarget = pathDirectoryNested / filenameTarget
|
|
211
|
+
pathFilenameTarget: pathlib.Path = pathDirectoryNested / filenameTarget
|
|
158
212
|
writeStringToHere(contentTarget, pathFilenameTarget)
|
|
159
213
|
|
|
160
214
|
assert pathFilenameTarget.exists(), (
|
|
@@ -163,14 +217,13 @@ def testWriteStringToHereCreatesFileAndDirectories(
|
|
|
163
217
|
f"Got: exists={pathFilenameTarget.exists()}"
|
|
164
218
|
)
|
|
165
219
|
|
|
166
|
-
contentActual = pathFilenameTarget.read_text(encoding="utf-8")
|
|
220
|
+
contentActual: str = pathFilenameTarget.read_text(encoding="utf-8")
|
|
167
221
|
assert contentActual == contentTarget, (
|
|
168
222
|
f"\nTesting: `writeStringToHere({contentTarget}, {pathFilenameTarget})`\n"
|
|
169
223
|
f"Expected content: {contentTarget}\n"
|
|
170
224
|
f"Got content: {contentActual}"
|
|
171
225
|
)
|
|
172
226
|
|
|
173
|
-
|
|
174
227
|
@pytest.mark.parametrize(
|
|
175
228
|
"contentTarget",
|
|
176
229
|
[
|
|
@@ -181,18 +234,24 @@ def testWriteStringToHereCreatesFileAndDirectories(
|
|
|
181
234
|
]
|
|
182
235
|
)
|
|
183
236
|
def testWriteStringToHereWithIOStream(contentTarget: str) -> None:
|
|
184
|
-
"""Test that writeStringToHere writes content to IO streams.
|
|
185
|
-
|
|
237
|
+
"""Test that writeStringToHere writes content to IO streams.
|
|
238
|
+
|
|
239
|
+
Parameters
|
|
240
|
+
----------
|
|
241
|
+
contentTarget : str
|
|
242
|
+
Content to write to the stream.
|
|
243
|
+
|
|
244
|
+
"""
|
|
245
|
+
streamMemory: io.StringIO = io.StringIO()
|
|
186
246
|
writeStringToHere(contentTarget, streamMemory)
|
|
187
247
|
|
|
188
|
-
contentActual = streamMemory.getvalue()
|
|
248
|
+
contentActual: str = streamMemory.getvalue()
|
|
189
249
|
assert contentActual == contentTarget, (
|
|
190
250
|
f"\nTesting: `writeStringToHere({contentTarget}, StringIO)`\n"
|
|
191
251
|
f"Expected content: {contentTarget}\n"
|
|
192
252
|
f"Got content: {contentActual}"
|
|
193
253
|
)
|
|
194
254
|
|
|
195
|
-
|
|
196
255
|
@pytest.mark.parametrize(
|
|
197
256
|
"logicalPathModuleTarget, identifierTarget, expectedExceptionType",
|
|
198
257
|
[
|
|
@@ -206,14 +265,19 @@ def testImportLogicalPath2IdentifierWithInvalidInputs(
|
|
|
206
265
|
identifierTarget: str,
|
|
207
266
|
expectedExceptionType: type[Exception]
|
|
208
267
|
) -> None:
|
|
209
|
-
"""Test that importLogicalPath2Identifier raises appropriate exceptions for invalid inputs.
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
268
|
+
"""Test that importLogicalPath2Identifier raises appropriate exceptions for invalid inputs.
|
|
269
|
+
|
|
270
|
+
Parameters
|
|
271
|
+
----------
|
|
272
|
+
logicalPathModuleTarget : str
|
|
273
|
+
Invalid module path.
|
|
274
|
+
identifierTarget : str
|
|
275
|
+
Identifier to import.
|
|
276
|
+
expectedExceptionType : type[Exception]
|
|
277
|
+
The expected exception type.
|
|
216
278
|
|
|
279
|
+
"""
|
|
280
|
+
standardizedEqualTo( expectedExceptionType, importLogicalPath2Identifier, logicalPathModuleTarget, identifierTarget )
|
|
217
281
|
|
|
218
282
|
@pytest.mark.parametrize(
|
|
219
283
|
"pathFilenameTarget, identifierTarget, expectedExceptionType",
|
|
@@ -221,22 +285,24 @@ def testImportLogicalPath2IdentifierWithInvalidInputs(
|
|
|
221
285
|
('nonexistent.py', 'anyIdentifier', FileNotFoundError),
|
|
222
286
|
]
|
|
223
287
|
)
|
|
224
|
-
def testImportPathFilename2IdentifierWithInvalidInputs(
|
|
225
|
-
|
|
226
|
-
pathFilenameTarget: str,
|
|
227
|
-
identifierTarget: str,
|
|
228
|
-
expectedExceptionType: type[Exception]
|
|
229
|
-
) -> None:
|
|
230
|
-
"""Test that importPathFilename2Identifier raises appropriate exceptions for invalid inputs."""
|
|
231
|
-
pathFilenameNonexistent = pathTmpTesting / pathFilenameTarget
|
|
288
|
+
def testImportPathFilename2IdentifierWithInvalidInputs(pathTmpTesting: pathlib.Path, pathFilenameTarget: str, identifierTarget: str, expectedExceptionType: type[Exception]) -> None:
|
|
289
|
+
"""Test that importPathFilename2Identifier raises appropriate exceptions for invalid inputs.
|
|
232
290
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
291
|
+
Parameters
|
|
292
|
+
----------
|
|
293
|
+
pathTmpTesting : pathlib.Path
|
|
294
|
+
Temporary directory fixture.
|
|
295
|
+
pathFilenameTarget : str
|
|
296
|
+
Invalid or nonexistent filename.
|
|
297
|
+
identifierTarget : str
|
|
298
|
+
Identifier to import.
|
|
299
|
+
expectedExceptionType : type[Exception]
|
|
300
|
+
The expected exception type.
|
|
239
301
|
|
|
302
|
+
"""
|
|
303
|
+
pathFilenameNonexistent: pathlib.Path = pathTmpTesting / pathFilenameTarget
|
|
304
|
+
|
|
305
|
+
standardizedEqualTo( expectedExceptionType, importPathFilename2Identifier, pathFilenameNonexistent, identifierTarget )
|
|
240
306
|
|
|
241
307
|
@pytest.mark.parametrize(
|
|
242
308
|
"pythonSourceTarget, identifierTarget, expectedExceptionType",
|
|
@@ -251,17 +317,24 @@ def testImportPathFilename2IdentifierWithValidFileInvalidIdentifier(
|
|
|
251
317
|
identifierTarget: str,
|
|
252
318
|
expectedExceptionType: type[Exception]
|
|
253
319
|
) -> None:
|
|
254
|
-
"""Test that importPathFilename2Identifier raises AttributeError for nonexistent identifiers
|
|
255
|
-
|
|
320
|
+
"""Test that importPathFilename2Identifier raises AttributeError for nonexistent identifiers.
|
|
321
|
+
|
|
322
|
+
Parameters
|
|
323
|
+
----------
|
|
324
|
+
pathTmpTesting : pathlib.Path
|
|
325
|
+
Temporary directory fixture.
|
|
326
|
+
pythonSourceTarget : str
|
|
327
|
+
Valid python source code.
|
|
328
|
+
identifierTarget : str
|
|
329
|
+
Identifier that does not exist in the source.
|
|
330
|
+
expectedExceptionType : type[Exception]
|
|
331
|
+
Expected exception (usually AttributeError).
|
|
332
|
+
|
|
333
|
+
"""
|
|
334
|
+
pathFilenameModule: pathlib.Path = pathTmpTesting / f"moduleTest{hash(pythonSourceTarget) % 101}.py" # Use prime number 101
|
|
256
335
|
pathFilenameModule.write_text(pythonSourceTarget)
|
|
257
336
|
|
|
258
|
-
standardizedEqualTo(
|
|
259
|
-
expectedExceptionType,
|
|
260
|
-
importPathFilename2Identifier,
|
|
261
|
-
pathFilenameModule,
|
|
262
|
-
identifierTarget
|
|
263
|
-
)
|
|
264
|
-
|
|
337
|
+
standardizedEqualTo( expectedExceptionType, importPathFilename2Identifier, pathFilenameModule, identifierTarget )
|
|
265
338
|
|
|
266
339
|
@pytest.mark.parametrize(
|
|
267
340
|
"pythonSourceTarget, expectedFormattedContent",
|
|
@@ -284,13 +357,20 @@ def testImportPathFilename2IdentifierWithValidFileInvalidIdentifier(
|
|
|
284
357
|
),
|
|
285
358
|
]
|
|
286
359
|
)
|
|
287
|
-
def testWritePythonFormatsAndWritesToFile(
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
360
|
+
def testWritePythonFormatsAndWritesToFile(pathTmpTesting: pathlib.Path, pythonSourceTarget: str, expectedFormattedContent: str) -> None:
|
|
361
|
+
"""Test that writePython formats Python source code and writes it to files.
|
|
362
|
+
|
|
363
|
+
Parameters
|
|
364
|
+
----------
|
|
365
|
+
pathTmpTesting : pathlib.Path
|
|
366
|
+
Temporary directory fixture.
|
|
367
|
+
pythonSourceTarget : str
|
|
368
|
+
Unformatted python source.
|
|
369
|
+
expectedFormattedContent : str
|
|
370
|
+
Expected formatted content.
|
|
371
|
+
|
|
372
|
+
"""
|
|
373
|
+
pathFilenameTarget: pathlib.Path = pathTmpTesting / "formattedModule.py"
|
|
294
374
|
writePython(pythonSourceTarget, pathFilenameTarget)
|
|
295
375
|
|
|
296
376
|
assert pathFilenameTarget.exists(), (
|
|
@@ -299,14 +379,13 @@ def testWritePythonFormatsAndWritesToFile(
|
|
|
299
379
|
f"Got: exists={pathFilenameTarget.exists()}"
|
|
300
380
|
)
|
|
301
381
|
|
|
302
|
-
contentActual = pathFilenameTarget.read_text(encoding="utf-8")
|
|
382
|
+
contentActual: str = pathFilenameTarget.read_text(encoding="utf-8")
|
|
303
383
|
assert contentActual == expectedFormattedContent, (
|
|
304
384
|
f"\nTesting: `writePython(...)`\n"
|
|
305
385
|
f"Expected content:\n{repr(expectedFormattedContent)}\n"
|
|
306
386
|
f"Got content:\n{repr(contentActual)}"
|
|
307
387
|
)
|
|
308
388
|
|
|
309
|
-
|
|
310
389
|
@pytest.mark.parametrize(
|
|
311
390
|
"pythonSourceTarget, expectedFormattedContent",
|
|
312
391
|
[
|
|
@@ -320,22 +399,27 @@ def testWritePythonFormatsAndWritesToFile(
|
|
|
320
399
|
),
|
|
321
400
|
]
|
|
322
401
|
)
|
|
323
|
-
def testWritePythonFormatsAndWritesToStream(
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
402
|
+
def testWritePythonFormatsAndWritesToStream(pythonSourceTarget: str, expectedFormattedContent: str) -> None:
|
|
403
|
+
"""Test that writePython formats Python source code and writes it to IO streams.
|
|
404
|
+
|
|
405
|
+
Parameters
|
|
406
|
+
----------
|
|
407
|
+
pythonSourceTarget : str
|
|
408
|
+
Unformatted python source.
|
|
409
|
+
expectedFormattedContent : str
|
|
410
|
+
Expected formatted content.
|
|
411
|
+
|
|
412
|
+
"""
|
|
413
|
+
streamMemory: io.StringIO = io.StringIO()
|
|
329
414
|
writePython(pythonSourceTarget, streamMemory)
|
|
330
415
|
|
|
331
|
-
contentActual = streamMemory.getvalue()
|
|
416
|
+
contentActual: str = streamMemory.getvalue()
|
|
332
417
|
assert contentActual == expectedFormattedContent, (
|
|
333
418
|
f"\nTesting: `writePython(..., StringIO)`\n"
|
|
334
419
|
f"Expected content:\n{repr(expectedFormattedContent)}\n"
|
|
335
420
|
f"Got content:\n{repr(contentActual)}"
|
|
336
421
|
)
|
|
337
422
|
|
|
338
|
-
|
|
339
423
|
@pytest.mark.parametrize(
|
|
340
424
|
"pythonSourceTarget, settingsCustom, expectedFormattedContent",
|
|
341
425
|
[
|
|
@@ -357,18 +441,30 @@ def testWritePythonWithCustomSettings(
|
|
|
357
441
|
settingsCustom: dict[str, dict[str, object]],
|
|
358
442
|
expectedFormattedContent: str
|
|
359
443
|
) -> None:
|
|
360
|
-
"""Test that writePython respects custom formatter settings.
|
|
361
|
-
|
|
444
|
+
"""Test that writePython respects custom formatter settings.
|
|
445
|
+
|
|
446
|
+
Parameters
|
|
447
|
+
----------
|
|
448
|
+
pathTmpTesting : pathlib.Path
|
|
449
|
+
Temporary directory fixture.
|
|
450
|
+
pythonSourceTarget : str
|
|
451
|
+
Unformatted python source.
|
|
452
|
+
settingsCustom : dict[str, dict[str, object]]
|
|
453
|
+
Dictionary of formatter settings.
|
|
454
|
+
expectedFormattedContent : str
|
|
455
|
+
Expected formatted content.
|
|
456
|
+
|
|
457
|
+
"""
|
|
458
|
+
pathFilenameTarget: pathlib.Path = pathTmpTesting / "customFormattedModule.py"
|
|
362
459
|
writePython(pythonSourceTarget, pathFilenameTarget, settingsCustom)
|
|
363
460
|
|
|
364
|
-
contentActual = pathFilenameTarget.read_text(encoding="utf-8")
|
|
461
|
+
contentActual: str = pathFilenameTarget.read_text(encoding="utf-8")
|
|
365
462
|
assert contentActual == expectedFormattedContent, (
|
|
366
463
|
f"\nTesting: `writePython(..., custom settings)`\n"
|
|
367
464
|
f"Expected content:\n{repr(expectedFormattedContent)}\n"
|
|
368
465
|
f"Got content:\n{repr(contentActual)}"
|
|
369
466
|
)
|
|
370
467
|
|
|
371
|
-
|
|
372
468
|
@pytest.mark.parametrize(
|
|
373
469
|
"pythonSourceTarget",
|
|
374
470
|
[
|
|
@@ -377,12 +473,18 @@ def testWritePythonWithCustomSettings(
|
|
|
377
473
|
"def primeFunction():\n return 37\n",
|
|
378
474
|
]
|
|
379
475
|
)
|
|
380
|
-
def testWritePythonCreatesNestedDirectories(
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
476
|
+
def testWritePythonCreatesNestedDirectories(pathTmpTesting: pathlib.Path, pythonSourceTarget: str) -> None:
|
|
477
|
+
"""Test that writePython creates nested directories when writing to files.
|
|
478
|
+
|
|
479
|
+
Parameters
|
|
480
|
+
----------
|
|
481
|
+
pathTmpTesting : pathlib.Path
|
|
482
|
+
Temporary directory fixture.
|
|
483
|
+
pythonSourceTarget : str
|
|
484
|
+
Python source code.
|
|
485
|
+
|
|
486
|
+
"""
|
|
487
|
+
pathFilenameTarget: pathlib.Path = pathTmpTesting / "nested" / "directories" / "module.py"
|
|
386
488
|
writePython(pythonSourceTarget, pathFilenameTarget)
|
|
387
489
|
|
|
388
490
|
assert pathFilenameTarget.exists(), (
|
|
@@ -397,7 +499,6 @@ def testWritePythonCreatesNestedDirectories(
|
|
|
397
499
|
f"Got: exists={pathFilenameTarget.parent.exists()}"
|
|
398
500
|
)
|
|
399
501
|
|
|
400
|
-
|
|
401
502
|
@pytest.mark.parametrize(
|
|
402
503
|
"pythonSourceTarget, expectedContainsImport",
|
|
403
504
|
[
|
|
@@ -406,23 +507,29 @@ def testWritePythonCreatesNestedDirectories(
|
|
|
406
507
|
("import sys\n\nvalueFibonacci = sys.version\n", "import sys"),
|
|
407
508
|
]
|
|
408
509
|
)
|
|
409
|
-
def testWritePythonPreservesUsedImports(
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
510
|
+
def testWritePythonPreservesUsedImports(pathTmpTesting: pathlib.Path, pythonSourceTarget: str, expectedContainsImport: str) -> None:
|
|
511
|
+
"""Test that writePython preserves imports that are actually used in the code.
|
|
512
|
+
|
|
513
|
+
Parameters
|
|
514
|
+
----------
|
|
515
|
+
pathTmpTesting : pathlib.Path
|
|
516
|
+
Temporary directory fixture.
|
|
517
|
+
pythonSourceTarget : str
|
|
518
|
+
Python source with used imports.
|
|
519
|
+
expectedContainsImport : str
|
|
520
|
+
Import string that should remain.
|
|
521
|
+
|
|
522
|
+
"""
|
|
523
|
+
pathFilenameTarget: pathlib.Path = pathTmpTesting / "preservedImports.py"
|
|
416
524
|
writePython(pythonSourceTarget, pathFilenameTarget)
|
|
417
525
|
|
|
418
|
-
contentActual = pathFilenameTarget.read_text(encoding="utf-8")
|
|
526
|
+
contentActual: str = pathFilenameTarget.read_text(encoding="utf-8")
|
|
419
527
|
assert expectedContainsImport in contentActual, (
|
|
420
528
|
f"\nTesting: `writePython(...)` preserves used imports\n"
|
|
421
529
|
f"Expected content to contain: {expectedContainsImport}\n"
|
|
422
530
|
f"Got content:\n{contentActual}"
|
|
423
531
|
)
|
|
424
532
|
|
|
425
|
-
|
|
426
533
|
@pytest.mark.parametrize(
|
|
427
534
|
"pythonSourceTarget, expectedNotContainsImport",
|
|
428
535
|
[
|
|
@@ -431,16 +538,23 @@ def testWritePythonPreservesUsedImports(
|
|
|
431
538
|
("import sys\nimport collections\n\nvalueFibonacci = sys.version\n", "import collections"),
|
|
432
539
|
]
|
|
433
540
|
)
|
|
434
|
-
def testWritePythonRemovesUnusedImports(
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
541
|
+
def testWritePythonRemovesUnusedImports(pathTmpTesting: pathlib.Path, pythonSourceTarget: str, expectedNotContainsImport: str) -> None:
|
|
542
|
+
"""Test that writePython removes imports that are not used in the code.
|
|
543
|
+
|
|
544
|
+
Parameters
|
|
545
|
+
----------
|
|
546
|
+
pathTmpTesting : pathlib.Path
|
|
547
|
+
Temporary directory fixture.
|
|
548
|
+
pythonSourceTarget : str
|
|
549
|
+
Python source with unused imports.
|
|
550
|
+
expectedNotContainsImport : str
|
|
551
|
+
Import string that should be removed.
|
|
552
|
+
|
|
553
|
+
"""
|
|
554
|
+
pathFilenameTarget: pathlib.Path = pathTmpTesting / "removedImports.py"
|
|
441
555
|
writePython(pythonSourceTarget, pathFilenameTarget)
|
|
442
556
|
|
|
443
|
-
contentActual = pathFilenameTarget.read_text(encoding="utf-8")
|
|
557
|
+
contentActual: str = pathFilenameTarget.read_text(encoding="utf-8")
|
|
444
558
|
assert expectedNotContainsImport not in contentActual, (
|
|
445
559
|
f"\nTesting: `writePython(...)` removes unused imports\n"
|
|
446
560
|
f"Expected content to NOT contain: {expectedNotContainsImport}\n"
|