hunterMakesPy 0.1.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.
@@ -0,0 +1,319 @@
1
+ # pyright: standard
2
+ from collections.abc import Callable, Iterable, Iterator
3
+ from decimal import Decimal
4
+ from fractions import Fraction
5
+ from hunterMakesPy import autoDecodingRLE, stringItUp, updateExtendPolishDictionaryLists
6
+ from numpy.typing import NDArray
7
+ from tests.conftest import standardizedEqualTo
8
+ from typing import Any, Literal
9
+ import datetime
10
+ import numpy
11
+ import pytest
12
+
13
+ class CustomIterable:
14
+ def __init__(self, items: Iterable[Any]) -> None: self.items = items
15
+ def __iter__(self) -> Iterator[Any]: return iter(self.items)
16
+
17
+ @pytest.mark.parametrize("description,value_scrapPile,expected", [
18
+ # Basic types and structures
19
+ ("Empty input", [], []),
20
+ ("Prime numbers", [11, 13, 17], ['11', '13', '17']),
21
+ ("Cardinal directions", ["NE", "SW", "SE"], ["NE", "SW", "SE"]),
22
+ ("Country codes", ["FR", "JP", "BR"], ["FR", "JP", "BR"]),
23
+ ("Boolean values", [True, False], ['True', 'False']),
24
+ ("None value", [None], ['None']),
25
+ # Numbers and numeric types
26
+ ("Fibonacci floats", [2.584, -4.236, 6.854], ['2.584', '-4.236', '6.854']),
27
+ ("Complex with primes", [complex(11,0), complex(13,0)], ['(11+0j)', '(13+0j)']),
28
+ ("Decimal and Fraction", [Decimal('3.141'), Fraction(89, 55)], ['3.141', '89/55']),
29
+ ("NumPy primes", numpy.array([11, 13, 17]), ['11', '13', '17']),
30
+ # Temporal types with meaningful dates
31
+ ("Historical date", [datetime.date(1789, 7, 14)], ['1789-07-14']), # Bastille Day
32
+ ("Time zones", [datetime.time(23, 11, 37)], ['23:11:37']), # Non-standard time
33
+ ("Moon landing", [datetime.datetime(1969, 7, 20, 20, 17, 40)], ['1969-07-20 20:17:40']),
34
+ # Binary data - accepting either representation
35
+ ("Prime bytes", [b'\x0B', b'\x0D', b'\x11'], [repr(b'\x0b'), repr(b'\x0d'), repr(b'\x11')]), # Let Python choose representation
36
+ ("Custom bytearray", [bytearray(b"DEADBEEF")], ["bytearray(b'DEADBEEF')"]),
37
+ # Nested structures with unique values
38
+ ("Nested dictionary", {'phi': 1.618, 'euler': 2.718}, ['phi', '1.618', 'euler', '2.718']),
39
+ ("Mixed nesting", [{'NE': 37}, {'SW': 41}], ['NE', '37', 'SW', '41']),
40
+ ("Tuples and lists", [(13, 17), [19, 23]], ['13', '17', '19', '23']),
41
+ ("Sets and frozensets", [{37, 41}, frozenset([43, 47])], ['41', '37', '43', '47']),
42
+ # Special cases and error handling
43
+ ("NaN and Infinities", [float('nan'), float('inf'), -float('inf')], ['nan', 'inf', '-inf']),
44
+ ("Large prime", [10**19 + 33], ['10000000000000000033']),
45
+ ("Simple recursive", [[[...]]], ['Ellipsis']), # Recursive list
46
+ ("Complex recursive", {'self': {'self': None}}, ['self', 'self', 'None']),
47
+ # Generators and custom iterables
48
+ ("Generator from primes", (x for x in [11, 13, 17]), ['11', '13', '17']),
49
+ ("Iterator from Fibonacci", iter([3, 5, 8, 13]), ['3', '5', '8', '13']),
50
+ ("Custom iterable cardinal", CustomIterable(["NW", "SE", "NE"]), ["NW", "SE", "NE"]),
51
+ ("Custom iterable empty", CustomIterable([]), []),
52
+ # Weird stuff
53
+ ("Bad __str__", type('BadStr', (), {'__str__': lambda x: None})(), [None]),
54
+ # Error cases
55
+ ("Raising __str__", type('RaisingStr', (), {'__str__': lambda x: 1/0})(), ZeroDivisionError),
56
+ ], ids=lambda x: x if isinstance(x, str) else "")
57
+ def testStringItUp(description: str, value_scrapPile: list[Any], expected: list[str] | type[Exception]) -> None:
58
+ """Test stringItUp with various inputs."""
59
+ standardizedEqualTo(expected, stringItUp, value_scrapPile)
60
+
61
+ @pytest.mark.parametrize("description,value_scrapPile,expected", [
62
+ ("Memory view", memoryview(b"DEADBEEF"), ["<memory at 0x"]), # Special handling for memoryview
63
+ ], ids=lambda x: x if isinstance(x, str) else "")
64
+ def testStringItUpErrorCases(description: Literal['Memory view'], value_scrapPile: memoryview, expected: list[str]) -> None:
65
+ result = stringItUp(value_scrapPile)
66
+ assert len(result) == 1
67
+ assert result[0].startswith(expected[0])
68
+
69
+ @pytest.mark.parametrize("description,value_dictionaryLists,keywordArguments,expected", [
70
+ ("Mixed value types", ({'ne': [11, 'prime'], 'sw': [True, None]}, {'ne': [3.141, 'golden'], 'sw': [False, 'void']}), {'destroyDuplicates': False, 'reorderLists': False}, {'ne': [11, 'prime', 3.141, 'golden'], 'sw': [True, None, False, 'void']}),
71
+ ("Empty dictionaries", (dict[str, list[Any]](), dict[str, list[Any]]()), dict[str, Any](), dict[str, list[Any]]()),
72
+ ("Tuple values", ({'ne': (11, 13), 'sw': (17,)}, {'ne': (19, 23, 13, 29, 11), 'sw': (31, 17, 37)}), {'destroyDuplicates': False, 'reorderLists': False}, {'ne': [11, 13, 19, 23, 13, 29, 11], 'sw': [17, 31, 17, 37]}),
73
+ ("Set values", ({'ne': {11, 13}, 'sw': {17}}, {'ne': {19, 23, 13, 29, 11}, 'sw': {31, 17, 37}}), {'destroyDuplicates': True, 'reorderLists': True}, {'ne': [11, 13, 19, 23, 29], 'sw': [17, 31, 37]}),
74
+ ("NumPy arrays", ({'ne': numpy.array([11, 13]), 'sw': numpy.array([17])}, {'ne': numpy.array([19, 23, 13, 29, 11]), 'sw': numpy.array([31, 17, 37])}), {'destroyDuplicates': False, 'reorderLists': False}, {'ne': [11, 13, 19, 23, 13, 29, 11], 'sw': [17, 31, 17, 37]}),
75
+ ("Destroy duplicates", ({'fr': [11, 13], 'jp': [17]}, {'fr': [19, 23, 13, 29, 11], 'jp': [31, 17, 37]}), {'destroyDuplicates': True, 'reorderLists': False}, {'fr': [11, 13, 19, 23, 29], 'jp': [17, 31, 37]}),
76
+ ("Non-string keys", ({None: [13], True: [17]}, {19: [23], (29, 31): [37]}), {'destroyDuplicates': False, 'reorderLists': False}, {'None': [13], 'True': [17], '19': [23], '(29, 31)': [37]}),
77
+ ("Reorder lists", ({'fr': [11, 13], 'jp': [17]}, {'fr': [19, 23, 13, 29, 11], 'jp': [31, 17, 37]}), {'destroyDuplicates': False, 'reorderLists': True}, {'fr': [11, 11, 13, 13, 19, 23, 29], 'jp': [17, 17, 31, 37]}),
78
+ ("Non-iterable values", ({'ne': 13, 'sw': 17}, {'ne': 19, 'nw': 23}), {'destroyDuplicates': False, 'reorderLists': False}, TypeError),
79
+ ("Skip erroneous types", ({'ne': [11, 13], 'sw': [17, 19]}, {'ne': 23, 'nw': 29}), {'killErroneousDataTypes': True}, {'ne': [11, 13], 'sw': [17, 19]}),
80
+ ], ids=lambda x: x if isinstance(x, str) else "")
81
+ def testUpdateExtendPolishDictionaryLists(description: str, value_dictionaryLists: dict[str, Any], keywordArguments: dict[str, Any], expected: dict[str, Any] | type[TypeError]) -> None:
82
+ standardizedEqualTo(expected, updateExtendPolishDictionaryLists, *value_dictionaryLists, **keywordArguments)
83
+ # ruff: noqa: ERA001
84
+ # NOTE one line of code with `standardizedEqualTo` replaced the following ten lines of code.
85
+ # if isinstance(expected, type) and issubclass(expected, Exception):
86
+ # with pytest.raises(expected):
87
+ # updateExtendPolishDictionaryLists(*value_dictionaryLists, **keywordArguments)
88
+ # else:
89
+ # result = updateExtendPolishDictionaryLists(*value_dictionaryLists, **keywordArguments)
90
+ # if description == "Set values": # Special handling for unordered sets
91
+ # for key in result:
92
+ # assert sorted(result[key]) == sorted(expected[key])
93
+ # else:
94
+ # assert result == expected
95
+
96
+ # ruff: noqa: RUF005
97
+ @pytest.mark.parametrize("description,value_arrayTarget,expected", [
98
+ ("One range", numpy.array(list(range(50,60))), "[*range(50,60)]"),
99
+ ("Value, range", numpy.array([123]+list(range(71,81))), "[123,*range(71,81)]"),
100
+ ("range, value", numpy.array(list(range(91,97))+[101]), "[*range(91,97),101]"),
101
+ ("Value, range, value", numpy.array([151]+list(range(163,171))+[181]), "[151,*range(163,171),181]"),
102
+ ("Repeat values", numpy.array([191, 191, 191]), "[191]*3"),
103
+ ("Value with repeat", numpy.array([211, 223, 223, 223]), "[211]+[223]*3"),
104
+ ("Range with repeat", numpy.array(list(range(251,257))+[271, 271, 271]), "[*range(251,257)]+[271]*3"),
105
+ ("Value, range, repeat", numpy.array([281]+list(range(291,297))+[307, 307]), "[281,*range(291,297)]+[307]*2"),
106
+ ("repeat, value", numpy.array([313, 313, 313, 331, 331, 349]), "[313]*3+[331]*2+[349]"),
107
+ ("repeat, range", numpy.array([373, 373, 373]+list(range(383,389))), "[373]*3+[*range(383,389)]"),
108
+ ("repeat, range, value", numpy.array(7*[401]+list(range(409,415))+[421]), "[401]*7+[*range(409,415),421]"),
109
+ ("Repeated primes", numpy.array([431, 431, 431, 443, 443, 457]), "[431]*3+[443]*2+[457]"),
110
+ ("Two Ranges", numpy.array(list(range(461,471))+list(range(479,487))), "[*range(461,471),*range(479,487)]"),
111
+ ("2D array primes", numpy.array([[491, 499, 503], [509, 521, 523]]), "[[491,499,503],[509,521,523]]"),
112
+ ("3D array primes", numpy.array([[[541, 547], [557, 563]], [[569, 571], [577, 587]]]), "[[[541,547],[557,563]],[[569,571],[577,587]]]"),
113
+ ], ids=lambda x: x if isinstance(x, str) else "")
114
+ def testAutoDecodingRLE(description: str, value_arrayTarget: NDArray[numpy.integer[Any]], expected: str) -> None:
115
+ """Test autoDecodingRLE with various input arrays."""
116
+ standardizedEqualTo(expected, autoDecodingRLE, value_arrayTarget)
117
+
118
+ # Helper functions for generating RLE test data
119
+ def generateCartesianMapping(dimensions: tuple[int, int], formula: Callable[[int, int], int]) -> NDArray[Any]:
120
+ """Generate a 2D cartesian mapping based on a formula."""
121
+ height, width = dimensions
122
+ arrayMapping = numpy.zeros((height, width), dtype=numpy.int32)
123
+
124
+ for y in range(height):
125
+ for x in range(width):
126
+ arrayMapping[y, x] = formula(x, y)
127
+
128
+ return arrayMapping
129
+
130
+ def generateWavePattern(dimensions: tuple[int, int]) -> NDArray[Any]:
131
+ """Generate a sine wave pattern that produces many RLE-friendly sequences."""
132
+ height, width = dimensions
133
+
134
+ def waveFormula(x: int, y: int) -> int:
135
+ return int(10 * numpy.sin(x / 5) + 10 * numpy.sin(y / 5))
136
+
137
+ return generateCartesianMapping(dimensions, waveFormula)
138
+
139
+ def generateChessboard(dimensions: tuple[int, int], squareSize: int = 4) -> NDArray[Any]:
140
+ """Generate a chessboard pattern with alternating values."""
141
+ height, width = dimensions
142
+
143
+ def chessboardFormula(x: int, y: int) -> int:
144
+ return 1 if ((x // squareSize) + (y // squareSize)) % 2 == 0 else 0
145
+
146
+ return generateCartesianMapping(dimensions, chessboardFormula)
147
+
148
+ def generatePrimeModuloMatrix(dimensions: tuple[int, int], modulus: int = 6) -> NDArray[Any]:
149
+ """Generate a matrix where each cell is (x*y) % modulus."""
150
+ height, width = dimensions
151
+
152
+ def primeModuloFormula(x: int, y: int) -> int:
153
+ return ((x + 1) * (y + 1)) % modulus
154
+
155
+ return generateCartesianMapping(dimensions, primeModuloFormula)
156
+
157
+ def generateSpiralPattern(dimensions: tuple[int, int], scale: int = 1) -> NDArray[Any]:
158
+ """Generate a spiral pattern that creates interesting RLE sequences."""
159
+ height, width = dimensions
160
+
161
+ def spiralFormula(x: int, y: int) -> int:
162
+ xCenter = width // 2
163
+ yCenter = height // 2
164
+ distanceX = x - xCenter
165
+ distanceY = y - yCenter
166
+ distance = numpy.sqrt(distanceX**2 + distanceY**2)
167
+ angle = numpy.arctan2(distanceY, distanceX)
168
+ return int((distance + 5 * angle) * scale) % 10
169
+
170
+ return generateCartesianMapping(dimensions, spiralFormula)
171
+
172
+ def generateSignedQuadraticFunction(dimensions: tuple[int, int]) -> NDArray[Any]:
173
+ """Generate a matrix with a quadratic function that includes negative values."""
174
+ height, width = dimensions
175
+
176
+ def quadraticFormula(x: int, y: int) -> int:
177
+ xCenter = width // 2
178
+ yCenter = height // 2
179
+ return (x - xCenter)**2 - (y - yCenter)**2
180
+
181
+ return generateCartesianMapping(dimensions, quadraticFormula)
182
+
183
+ def generateTilePattern(dimensions: tuple[int, int], tileSize: int = 10) -> NDArray[Any]:
184
+ """Generate a repeating tile pattern."""
185
+ height, width = dimensions
186
+
187
+ def tileFormula(x: int, y: int) -> int:
188
+ patternX = x % tileSize
189
+ patternY = y % tileSize
190
+ if patternX < patternY:
191
+ return patternX
192
+ else:
193
+ return patternY
194
+
195
+ return generateCartesianMapping(dimensions, tileFormula)
196
+
197
+ def generateRepeatingZones(dimensions: tuple[int, int], zoneWidth: int = 15) -> NDArray[Any]:
198
+ """Generate horizontal zones with repeating values."""
199
+ height, width = dimensions
200
+
201
+ def zoneFormula(x: int, y: int) -> int:
202
+ zone = y // zoneWidth
203
+ return zone % 5 # 5 different zones
204
+
205
+ return generateCartesianMapping(dimensions, zoneFormula)
206
+
207
+ def generateStepPattern(dimensions: tuple[int, int], step: int = 5) -> NDArray[Any]:
208
+ """Generate a stepping pattern that increases along the x-axis."""
209
+ height, width = dimensions
210
+
211
+ def stepFormula(x: int, y: int) -> int:
212
+ return x // step
213
+
214
+ return generateCartesianMapping(dimensions, stepFormula)
215
+
216
+ def generateAlternatingColumns(dimensions: tuple[int, int], blockSize: int = 1) -> NDArray[Any]:
217
+ """Generate alternating columns with different values."""
218
+ height, width = dimensions
219
+
220
+ def columnFormula(x: int, y: int) -> int:
221
+ return (x // blockSize) % 2
222
+
223
+ return generateCartesianMapping(dimensions, columnFormula)
224
+
225
+ # Updated test cases for autoDecodingRLE with more realistic data
226
+ @pytest.mark.parametrize("description,value_arrayTarget", [
227
+ # Basic test cases with simple patterns
228
+ ("Simple range", numpy.array(list(range(50,60)))),
229
+
230
+ # Chessboard patterns
231
+ ("Small chessboard", generateChessboard((8, 8))),
232
+
233
+ # Alternating columns - creates patterns with good RLE opportunities
234
+ ("Alternating columns", generateAlternatingColumns((5, 20), 2)),
235
+
236
+ # Step pattern - creates horizontal runs
237
+ ("Step pattern", generateStepPattern((6, 30), 3)),
238
+
239
+ # Repeating zones - creates horizontal bands
240
+ ("Repeating zones", generateRepeatingZones((40, 40), 8)),
241
+
242
+ # Tile pattern - creates complex repeating regions
243
+ ("Tile pattern", generateTilePattern((15, 15), 5)),
244
+
245
+ # Signed quadratic function - includes negative values
246
+ ("Signed quadratic", generateSignedQuadraticFunction((10, 10))),
247
+
248
+ # Prime modulo matrix - periodic patterns
249
+ ("Prime modulo", generatePrimeModuloMatrix((12, 12), 7)),
250
+
251
+ # Wave pattern - smooth gradients
252
+ ("Wave pattern", generateWavePattern((20, 20))),
253
+
254
+ # Spiral pattern - complex pattern with good RLE potential
255
+ ("Spiral pattern", generateSpiralPattern((15, 15), 2)),
256
+ ], ids=lambda x: x if isinstance(x, str) else "")
257
+ def testAutoDecodingRLEWithRealisticData(description: str, value_arrayTarget: NDArray[numpy.integer[Any]]) -> None:
258
+ """Test autoDecodingRLE with more realistic data patterns."""
259
+ # Here we test the function behavior rather than expected string output
260
+ resultRLE = autoDecodingRLE(value_arrayTarget)
261
+
262
+ # Test that the result is a valid string
263
+ assert isinstance(resultRLE, str)
264
+
265
+ # Test that the result contains the expected syntax elements
266
+ assert "[" in resultRLE, f"Result should contain list syntax: {resultRLE}"
267
+ assert "]" in resultRLE, f"Result should contain list syntax: {resultRLE}"
268
+
269
+ # Check that the result is more compact than the raw string representation
270
+ rawStrLength = len(str(value_arrayTarget.tolist()))
271
+ encodedLength = len(resultRLE)
272
+ assert encodedLength <= rawStrLength, f"Encoded string ({encodedLength}) should be shorter than raw string ({rawStrLength})"
273
+
274
+ @pytest.mark.parametrize("description,addSpaces", [
275
+ ("With spaces", True),
276
+ ("Without spaces", False),
277
+ ], ids=lambda x: x if isinstance(x, str) else "")
278
+ def testAutoDecodingRLEWithSpaces(description: str, addSpaces: bool) -> None:
279
+ """Test that the addSpaces parameter affects the internal comparison logic.
280
+
281
+ Note: addSpaces doesn't directly change the output format, it just changes
282
+ the comparison when measuring the length of the string representation.
283
+ The feature exists because `ast` inserts spaces in its string representation.
284
+ """
285
+ # Create a pattern that has repeated sequences to trigger the RLE logic
286
+ arrayTarget = generateRepeatingZones((10, 10), 2)
287
+
288
+ # Test both configurations
289
+ resultWithSpacesFlag = autoDecodingRLE(arrayTarget, assumeAddSpaces=addSpaces)
290
+ resultNoSpacesFlag = autoDecodingRLE(arrayTarget, assumeAddSpaces=False)
291
+
292
+ # When addSpaces=True, the internal length comparisons change
293
+ # but the actual output format doesn't necessarily differ
294
+ # Just verify the function runs without errors in both cases
295
+ assert isinstance(resultWithSpacesFlag, str)
296
+ assert isinstance(resultNoSpacesFlag, str)
297
+
298
+ def testAutoDecodingRLELargeCartesianMapping() -> None:
299
+ """Test autoDecodingRLE with a large (100x100) cartesian mapping."""
300
+ dimensions = (100, 100)
301
+
302
+ # Generate a large cartesian mapping with a complex pattern
303
+ def complexFormula(x: int, y: int) -> int:
304
+ return ((x * 17) % 11 + (y * 13) % 7) % 10
305
+
306
+ arrayMapping = generateCartesianMapping(dimensions, complexFormula)
307
+
308
+ # Verify the function works with large arrays
309
+ resultRLE = autoDecodingRLE(arrayMapping)
310
+
311
+ # The result should be a valid string representation
312
+ assert isinstance(resultRLE, str)
313
+ assert "[" in resultRLE
314
+ assert "]" in resultRLE
315
+
316
+ # The RLE encoding should be more compact than the raw representation
317
+ rawStrLength = len(str(arrayMapping.tolist()))
318
+ encodedLength = len(resultRLE)
319
+ assert encodedLength <= rawStrLength, f"RLE encoded string ({encodedLength}) should be shorter than raw string ({rawStrLength})"
@@ -0,0 +1,43 @@
1
+ # pyright: standard
2
+ from hunterMakesPy import importLogicalPath2Identifier, importPathFilename2Identifier, makeDirsSafely, writeStringToHere
3
+ from tests.conftest import uniformTestFailureMessage
4
+ import io
5
+ import math
6
+ import os
7
+ import pathlib
8
+ import pytest
9
+
10
+ def testMakeDirsSafelyCreatesParentDirectories(pathTmpTesting: pathlib.Path) -> None:
11
+ nestedDirectory = pathTmpTesting / "sub1" / "sub2"
12
+ filePath = nestedDirectory / "dummy.txt"
13
+ makeDirsSafely(filePath)
14
+ assert nestedDirectory.exists() and nestedDirectory.is_dir(), uniformTestFailureMessage(True, nestedDirectory.exists() and nestedDirectory.is_dir(), "testMakeDirsSafelyCreatesParentDirectories", filePath)
15
+
16
+ def testMakeDirsSafelyWithIOBaseDoesNotRaise() -> None:
17
+ memoryStream = io.StringIO()
18
+ makeDirsSafely(memoryStream)
19
+
20
+ def testWriteStringToHereCreatesFileAndWritesContent(pathTmpTesting: pathlib.Path) -> None:
21
+ nestedDirectory = pathTmpTesting / "a" / "b"
22
+ filePath = nestedDirectory / "test.txt"
23
+ writeStringToHere("hello world", filePath)
24
+ assert filePath.exists(), uniformTestFailureMessage(True, filePath.exists(), "testWriteStringToHereCreatesFileAndWritesContent", filePath)
25
+ assert filePath.read_text() == "hello world", uniformTestFailureMessage("hello world", filePath.read_text(), "testWriteStringToHereCreatesFileAndWritesContent", filePath)
26
+
27
+ @pytest.mark.parametrize(
28
+ "moduleName, identifier, expectedType",
29
+ [("math", "gcd", type(math.gcd)),("os.path", "join", type(os.path.join))])
30
+ def testImportLogicalPath2Identifier(moduleName: str, identifier: str, expectedType: type) -> None:
31
+ imported = importLogicalPath2Identifier(moduleName, identifier)
32
+ assert isinstance(imported, expectedType), uniformTestFailureMessage(expectedType, type(imported), "testImportLogicalPath2Identifier", (moduleName, identifier))
33
+
34
+ @pytest.mark.parametrize( "source, identifier, expected", [ ("def fibonacciNumber():\n return 13\n", "fibonacciNumber", 13), ("prime = 17\n", "prime", 17), ] )
35
+ def testImportPathFilename2Identifier(tmp_path: pathlib.Path, source: str, identifier: str, expected: object) -> None:
36
+ filePath = tmp_path / "moduleTest.py"
37
+ filePath.write_text(source)
38
+ imported = importPathFilename2Identifier(filePath, identifier)
39
+ if callable(imported):
40
+ actual = imported()
41
+ else:
42
+ actual = imported
43
+ assert actual == expected, uniformTestFailureMessage(expected, actual, "testImportPathFilename2Identifier", (filePath, identifier))
@@ -0,0 +1,21 @@
1
+ # pyright: standard
2
+ from collections.abc import Callable
3
+ from hunterMakesPy.pytestForYourUse import (
4
+ PytestFor_defineConcurrencyLimit, PytestFor_intInnit, PytestFor_oopsieKwargsie)
5
+ from typing import ParamSpec, TypeVar
6
+ import pytest
7
+
8
+ parameters = ParamSpec('parameters')
9
+ returnType = TypeVar('returnType')
10
+
11
+ @pytest.mark.parametrize("nameOfTest,aPytest", PytestFor_defineConcurrencyLimit())
12
+ def testConcurrencyLimit(nameOfTest: str, aPytest: Callable[parameters, returnType], *arguments: parameters.args, **keywordArguments: parameters.kwargs) -> None:
13
+ aPytest(*arguments, **keywordArguments)
14
+
15
+ @pytest.mark.parametrize("nameOfTest,aPytest", PytestFor_intInnit())
16
+ def testIntInnit(nameOfTest: str, aPytest: Callable[parameters, returnType], *arguments: parameters.args, **keywordArguments: parameters.kwargs) -> None:
17
+ aPytest(*arguments, **keywordArguments)
18
+
19
+ @pytest.mark.parametrize("nameOfTest,aPytest", PytestFor_oopsieKwargsie())
20
+ def testOopsieKwargsie(nameOfTest: str, aPytest: Callable[parameters, returnType], *arguments: parameters.args, **keywordArguments: parameters.kwargs) -> None:
21
+ aPytest(*arguments, **keywordArguments)