punit 1.2.14__tar.gz → 1.2.19__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.
Files changed (34) hide show
  1. {punit-1.2.14/src/pUnit.egg-info → punit-1.2.19}/PKG-INFO +7 -6
  2. {punit-1.2.14 → punit-1.2.19}/README.md +6 -4
  3. {punit-1.2.14 → punit-1.2.19}/pyproject.toml +1 -2
  4. {punit-1.2.14 → punit-1.2.19/src/pUnit.egg-info}/PKG-INFO +7 -6
  5. {punit-1.2.14 → punit-1.2.19}/src/pUnit.egg-info/requires.txt +0 -1
  6. {punit-1.2.14 → punit-1.2.19}/src/punit/__init__.py +2 -2
  7. {punit-1.2.14 → punit-1.2.19}/src/punit/cli.py +16 -7
  8. {punit-1.2.14 → punit-1.2.19}/src/punit/discovery/TestModuleDiscovery.py +21 -6
  9. {punit-1.2.14 → punit-1.2.19}/src/punit/facts/FactManager.py +14 -8
  10. {punit-1.2.14 → punit-1.2.19}/src/punit/theories/TheoryManager.py +14 -8
  11. {punit-1.2.14 → punit-1.2.19}/.scripts/punit +0 -0
  12. {punit-1.2.14 → punit-1.2.19}/LICENSE +0 -0
  13. {punit-1.2.14 → punit-1.2.19}/setup.cfg +0 -0
  14. {punit-1.2.14 → punit-1.2.19}/src/pUnit.egg-info/SOURCES.txt +0 -0
  15. {punit-1.2.14 → punit-1.2.19}/src/pUnit.egg-info/dependency_links.txt +0 -0
  16. {punit-1.2.14 → punit-1.2.19}/src/pUnit.egg-info/top_level.txt +0 -0
  17. {punit-1.2.14 → punit-1.2.19}/src/punit/TestResult.py +0 -0
  18. {punit-1.2.14 → punit-1.2.19}/src/punit/__main__.py +0 -0
  19. {punit-1.2.14 → punit-1.2.19}/src/punit/assertions/__init__.py +0 -0
  20. {punit-1.2.14 → punit-1.2.19}/src/punit/assertions/collections.py +0 -0
  21. {punit-1.2.14 → punit-1.2.19}/src/punit/assertions/exceptions.py +0 -0
  22. {punit-1.2.14 → punit-1.2.19}/src/punit/assertions/strings.py +0 -0
  23. {punit-1.2.14 → punit-1.2.19}/src/punit/discovery/__init__.py +0 -0
  24. {punit-1.2.14 → punit-1.2.19}/src/punit/facts/Fact.py +0 -0
  25. {punit-1.2.14 → punit-1.2.19}/src/punit/facts/__init__.py +0 -0
  26. {punit-1.2.14 → punit-1.2.19}/src/punit/py.typed +0 -0
  27. {punit-1.2.14 → punit-1.2.19}/src/punit/reports/HtmlReportGenerator.py +0 -0
  28. {punit-1.2.14 → punit-1.2.19}/src/punit/reports/JUnitReportGenerator.py +0 -0
  29. {punit-1.2.14 → punit-1.2.19}/src/punit/reports/__init__.py +0 -0
  30. {punit-1.2.14 → punit-1.2.19}/src/punit/runner.py +0 -0
  31. {punit-1.2.14 → punit-1.2.19}/src/punit/theories/Theory.py +0 -0
  32. {punit-1.2.14 → punit-1.2.19}/src/punit/theories/__init__.py +0 -0
  33. {punit-1.2.14 → punit-1.2.19}/src/punit/traits/Trait.py +0 -0
  34. {punit-1.2.14 → punit-1.2.19}/src/punit/traits/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pUnit
3
- Version: 1.2.14
3
+ Version: 1.2.19
4
4
  Summary: A modernized unit-test framework for Python.
5
5
  Author-email: Shaun Wilson <mrshaunwilson@msn.com>
6
6
  License: MIT License
@@ -39,7 +39,6 @@ Requires-Python: >=3.12
39
39
  Description-Content-Type: text/markdown
40
40
  License-File: LICENSE
41
41
  Provides-Extra: dev
42
- Requires-Dist: furo; extra == "dev"
43
42
  Requires-Dist: coverage; extra == "dev"
44
43
  Requires-Dist: mypy; extra == "dev"
45
44
  Requires-Dist: twine; extra == "dev"
@@ -94,9 +93,9 @@ Usage: python3 -m punit [-h|--help]
94
93
  [-p|--test-package NAME]
95
94
  [-i|--include PATTERN]
96
95
  [-e|--exclude PATTERN]
97
- [-f|--filter PATTERN]
96
+ [-f|--filter PATTERN|@FILEPATH]
98
97
  [-t|--trait [!]NAME[=VALUE]]
99
- [-w|--workdir DIRECTORY]
98
+ [-w|--working-directory PATH]
100
99
  [-n|--no-default-patterns]
101
100
  [-r|--report {junit|json}]
102
101
  [-o|--output FILENAME]
@@ -116,15 +115,17 @@ Options:
116
115
  -e, --exclude PATTERN
117
116
  Exclude any tests matching PATTERN, overriding --include
118
117
  Default: '__*__' (dunder files), '/.*/' (dot-directories)
119
- -f, --filter PATTERN
118
+ -f, --filter PATTERN|@FILEPATH
120
119
  Only execute tests matching PATTERN
121
120
  Default: '*'
121
+ To specify a file containing a list of filters, prefix
122
+ with '@' and provide the path to the file.
122
123
  -t, --trait [!]NAME[=VALUE]
123
124
  Execute tests with the specified trait, negated by prefixing with '!'.
124
125
  If VALUE is specified, matches tests with the trait having specified value.
125
126
  If VALUE is not specified, matches any test with the trait having any value.
126
127
  Default: No filtering based on traits.
127
- -w, --working-directory DIRECTORY
128
+ -w, --working-directory PATH
128
129
  Working directory (defaults to start directory)
129
130
  -n, --no-default-patterns
130
131
  Do not apply any default include/exclude patterns.
@@ -47,9 +47,9 @@ Usage: python3 -m punit [-h|--help]
47
47
  [-p|--test-package NAME]
48
48
  [-i|--include PATTERN]
49
49
  [-e|--exclude PATTERN]
50
- [-f|--filter PATTERN]
50
+ [-f|--filter PATTERN|@FILEPATH]
51
51
  [-t|--trait [!]NAME[=VALUE]]
52
- [-w|--workdir DIRECTORY]
52
+ [-w|--working-directory PATH]
53
53
  [-n|--no-default-patterns]
54
54
  [-r|--report {junit|json}]
55
55
  [-o|--output FILENAME]
@@ -69,15 +69,17 @@ Options:
69
69
  -e, --exclude PATTERN
70
70
  Exclude any tests matching PATTERN, overriding --include
71
71
  Default: '__*__' (dunder files), '/.*/' (dot-directories)
72
- -f, --filter PATTERN
72
+ -f, --filter PATTERN|@FILEPATH
73
73
  Only execute tests matching PATTERN
74
74
  Default: '*'
75
+ To specify a file containing a list of filters, prefix
76
+ with '@' and provide the path to the file.
75
77
  -t, --trait [!]NAME[=VALUE]
76
78
  Execute tests with the specified trait, negated by prefixing with '!'.
77
79
  If VALUE is specified, matches tests with the trait having specified value.
78
80
  If VALUE is not specified, matches any test with the trait having any value.
79
81
  Default: No filtering based on traits.
80
- -w, --working-directory DIRECTORY
82
+ -w, --working-directory PATH
81
83
  Working directory (defaults to start directory)
82
84
  -n, --no-default-patterns
83
85
  Do not apply any default include/exclude patterns.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pUnit"
3
- version = "1.2.14"
3
+ version = "1.2.19"
4
4
  description = "A modernized unit-test framework for Python."
5
5
  keywords = ["test", "unittest", "unit-test", "xUnit", "nUnit", "pytest"]
6
6
  authors = [
@@ -22,7 +22,6 @@ dependencies = [
22
22
 
23
23
  [project.optional-dependencies]
24
24
  dev = [
25
- "furo",
26
25
  "coverage",
27
26
  "mypy",
28
27
  "twine"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pUnit
3
- Version: 1.2.14
3
+ Version: 1.2.19
4
4
  Summary: A modernized unit-test framework for Python.
5
5
  Author-email: Shaun Wilson <mrshaunwilson@msn.com>
6
6
  License: MIT License
@@ -39,7 +39,6 @@ Requires-Python: >=3.12
39
39
  Description-Content-Type: text/markdown
40
40
  License-File: LICENSE
41
41
  Provides-Extra: dev
42
- Requires-Dist: furo; extra == "dev"
43
42
  Requires-Dist: coverage; extra == "dev"
44
43
  Requires-Dist: mypy; extra == "dev"
45
44
  Requires-Dist: twine; extra == "dev"
@@ -94,9 +93,9 @@ Usage: python3 -m punit [-h|--help]
94
93
  [-p|--test-package NAME]
95
94
  [-i|--include PATTERN]
96
95
  [-e|--exclude PATTERN]
97
- [-f|--filter PATTERN]
96
+ [-f|--filter PATTERN|@FILEPATH]
98
97
  [-t|--trait [!]NAME[=VALUE]]
99
- [-w|--workdir DIRECTORY]
98
+ [-w|--working-directory PATH]
100
99
  [-n|--no-default-patterns]
101
100
  [-r|--report {junit|json}]
102
101
  [-o|--output FILENAME]
@@ -116,15 +115,17 @@ Options:
116
115
  -e, --exclude PATTERN
117
116
  Exclude any tests matching PATTERN, overriding --include
118
117
  Default: '__*__' (dunder files), '/.*/' (dot-directories)
119
- -f, --filter PATTERN
118
+ -f, --filter PATTERN|@FILEPATH
120
119
  Only execute tests matching PATTERN
121
120
  Default: '*'
121
+ To specify a file containing a list of filters, prefix
122
+ with '@' and provide the path to the file.
122
123
  -t, --trait [!]NAME[=VALUE]
123
124
  Execute tests with the specified trait, negated by prefixing with '!'.
124
125
  If VALUE is specified, matches tests with the trait having specified value.
125
126
  If VALUE is not specified, matches any test with the trait having any value.
126
127
  Default: No filtering based on traits.
127
- -w, --working-directory DIRECTORY
128
+ -w, --working-directory PATH
128
129
  Working directory (defaults to start directory)
129
130
  -n, --no-default-patterns
130
131
  Do not apply any default include/exclude patterns.
@@ -1,6 +1,5 @@
1
1
 
2
2
  [dev]
3
- furo
4
3
  coverage
5
4
  mypy
6
5
  twine
@@ -7,8 +7,8 @@ from .theories import *
7
7
  from .traits import *
8
8
 
9
9
 
10
- __version__ = '1.2.14'
11
- __commit__ = 'c9cba7c'
10
+ __version__ = '1.2.19'
11
+ __commit__ = 'af80eb6'
12
12
  __all__ = [
13
13
  '__version__', '__commit__',
14
14
  'assertions',
@@ -208,9 +208,9 @@ Usage: python3 -m punit [-h|--help]
208
208
  [-p|--test-package NAME]
209
209
  [-i|--include PATTERN]
210
210
  [-e|--exclude PATTERN]
211
- [-f|--filter PATTERN]
211
+ [-f|--filter PATTERN|@FILEPATH]
212
212
  [-t|--trait [!]NAME[=VALUE]]
213
- [-w|--workdir DIRECTORY]
213
+ [-w|--working-directory PATH]
214
214
  [-n|--no-default-patterns]
215
215
  [-r|--report {junit|json}]
216
216
  [-o|--output FILENAME]
@@ -230,15 +230,17 @@ Options:
230
230
  -e, --exclude PATTERN
231
231
  Exclude any tests matching PATTERN, overriding --include
232
232
  Default: '__*__' (dunder files), '/.*/' (dot-directories)
233
- -f, --filter
233
+ -f, --filter PATTERN|@FILEPATH
234
234
  Only execute tests matching PATTERN
235
235
  Default: '*'
236
+ To specify a file containing a list of filters, prefix
237
+ with '@' and provide the path to the file.
236
238
  -t, --trait [!]NAME[=VALUE]
237
239
  Execute tests with the specified trait, negated by prefixing with '!'.
238
240
  If VALUE is specified, matches tests with the trait having specified value.
239
241
  If VALUE is not specified, matches any test with the trait having any value.
240
242
  Default: No filtering based on traits.
241
- -w, --working-directory DIRECTORY
243
+ -w, --working-directory PATH
242
244
  Working directory (defaults to start directory)
243
245
  -n, --no-default-patterns
244
246
  Do not apply any default include/exclude patterns.
@@ -267,8 +269,15 @@ Options:
267
269
  print('Exclude Patterns:')
268
270
  for pattern in self.__excludePatterns:
269
271
  print(f'\t{pattern}')
270
- print('Filter Pattern:')
271
- print(f'\t{self.__filterPattern}')
272
+ if self.__filterPattern.startswith('@'):
273
+ print(f'Filter Patterns: (from {self.__filterPattern[1:]})')
274
+ if not os.path.exists(os.path.realpath(self.__filterPattern[1:])):
275
+ print(f'\tFILTERS FILE DOES NOT EXIST, ABORTING!')
276
+ exit(5)
277
+ else:
278
+ print('Filter Pattern:')
279
+ print(f'\t{self.__filterPattern}')
280
+
272
281
  def printVersion(self) -> None:
273
282
  print(f'pUnit {__version__} ({__commit__})')
274
283
 
@@ -283,7 +292,7 @@ Options:
283
292
  if not self.__no_default_patterns:
284
293
  # if no other patterns specified, default to including all files found in the directory matching `testPackageName`
285
294
  if len(self.__includePatterns) == 0:
286
- self.__includePatterns.append(f'/{self.testPackageName}/*.py')
295
+ self.__includePatterns.append(f'*.py')
287
296
  # always exclude dot-folders (.git, .venv, etc)
288
297
  self.__excludePatterns.append('/.*')
289
298
  # always exclude dunder files
@@ -15,12 +15,12 @@ class TestModuleDiscovery:
15
15
  __excludePatterns:list[re.Pattern]
16
16
  __excludeTraits:list[Trait]
17
17
  __filenames:list[str]
18
- __filterPattern:re.Pattern
18
+ __filterPatterns:list[re.Pattern]
19
19
  __includePatterns:list[re.Pattern]
20
20
  __includeTraits:list[Trait]
21
21
  __workdir:str
22
22
 
23
- def __init__(self, workdir:str, includePatterns:list[str], excludePatterns:list[str], cli:CommandLineInterface):
23
+ def __init__(self, workdir:str, includePatterns:list[str], excludePatterns:list[str], cli:CommandLineInterface) -> None:
24
24
  self.__cli = cli
25
25
  self.__excludePatterns = []
26
26
  if excludePatterns is not None:
@@ -30,7 +30,7 @@ class TestModuleDiscovery:
30
30
  self.__convertPatternToRegex(pattern),
31
31
  re.IGNORECASE))
32
32
  self.__filenames = []
33
- self.__filterPattern = re.compile(self.__convertPatternToRegex(cli.filterPattern))
33
+ self.__filterPatterns = self.__buildFilterPatterns(cli.filterPattern)
34
34
  self.__includePatterns = []
35
35
  self.__excludeTraits = cli.excludeTraits
36
36
  self.__includeTraits = cli.includeTraits
@@ -42,7 +42,22 @@ class TestModuleDiscovery:
42
42
  re.IGNORECASE))
43
43
  self.__workdir = workdir
44
44
 
45
- def __convertPatternToRegex(self, pattern:str):
45
+ def __buildFilterPatterns(self, input:str) -> list[re.Pattern]:
46
+ if input.startswith('@'):
47
+ # treat as a filepath containing one or more filter patterns
48
+ filepath = os.path.realpath(input[1:])
49
+ with open(filepath, 'rb') as f:
50
+ result = list[re.Pattern]()
51
+ for line in f.read().decode().splitlines():
52
+ if (self.__cli.verbose):
53
+ print(f'\t{line}')
54
+ result.append(re.compile(self.__convertPatternToRegex(line)))
55
+ return result
56
+ else:
57
+ # treat as a single filter pattern
58
+ return [re.compile(self.__convertPatternToRegex(input))]
59
+
60
+ def __convertPatternToRegex(self, pattern:str) -> str:
46
61
  result = re.escape(pattern)\
47
62
  .replace('\\\\', '/')\
48
63
  .replace('\\*', r'.+')\
@@ -100,10 +115,10 @@ class TestModuleDiscovery:
100
115
 
101
116
  def discover(self) -> list[str]:
102
117
  FactManager.instance().excludeTraits = self.__excludeTraits
103
- FactManager.instance().filterPattern = self.__filterPattern
118
+ FactManager.instance().filterPatterns = self.__filterPatterns
104
119
  FactManager.instance().includeTraits = self.__includeTraits
105
120
  TheoryManager.instance().excludeTraits = self.__excludeTraits
106
- TheoryManager.instance().filterPattern = self.__filterPattern
121
+ TheoryManager.instance().filterPatterns = self.__filterPatterns
107
122
  TheoryManager.instance().includeTraits = self.__includeTraits
108
123
  if self.__cli.verbose:
109
124
  print(f'.. starting test discovery')
@@ -12,7 +12,7 @@ from ..traits.Trait import Trait
12
12
  class FactManager:
13
13
 
14
14
  __excludeTraits:list[Trait]
15
- __filterPattern:Optional[re.Pattern]
15
+ __filterPatterns:Optional[list[re.Pattern]]
16
16
  __instance:Optional['FactManager'] = None
17
17
  __includeTraits:list[Trait]
18
18
  __modules:dict[str, list[Fact]]
@@ -21,7 +21,7 @@ class FactManager:
21
21
  def __init__(self):
22
22
  if FactManager.__instance is not None:
23
23
  raise Exception('Cannot create more than one instance of FactManager') # pragma: no cover
24
- self.__filterPattern = None
24
+ self.__filterPatterns = None
25
25
  self.__modules = {}
26
26
  self.__traits = {}
27
27
 
@@ -40,12 +40,12 @@ class FactManager:
40
40
  self.__excludeTraits = value
41
41
 
42
42
  @property
43
- def filterPattern(self) -> Optional[re.Pattern]:
44
- return self.__filterPattern
43
+ def filterPatterns(self) -> Optional[list[re.Pattern]]:
44
+ return self.__filterPatterns
45
45
 
46
- @filterPattern.setter
47
- def filterPattern(self, value:re.Pattern) -> None:
48
- self.__filterPattern = value
46
+ @filterPatterns.setter
47
+ def filterPatterns(self, value:list[re.Pattern]) -> None:
48
+ self.__filterPatterns = value
49
49
 
50
50
  @property
51
51
  def includeTraits(self) -> list[Trait]:
@@ -77,7 +77,13 @@ class FactManager:
77
77
  return l
78
78
 
79
79
  def put(self, fact:Fact) -> None:
80
- if self.filterPattern is None or len(self.filterPattern.findall(fact.filterName)) > 0:
80
+ matchesFilterPattern:bool = self.filterPatterns is None
81
+ if self.filterPatterns is not None and len(self.filterPatterns) > 0:
82
+ for filterPattern in self.filterPatterns:
83
+ if len(filterPattern.findall(fact.filterName)) > 0:
84
+ matchesFilterPattern = True
85
+ break
86
+ if matchesFilterPattern:
81
87
  l = self.get(fact.moduleName)
82
88
  t = self.__traits.get(fact.target)
83
89
  if t is not None:
@@ -12,7 +12,7 @@ from .Theory import Theory
12
12
  class TheoryManager:
13
13
 
14
14
  __excludeTraits:list[Trait]
15
- __filterPattern:Optional[re.Pattern]
15
+ __filterPatterns:Optional[list[re.Pattern]]
16
16
  __includeTraits:list[Trait]
17
17
  __instance:Optional['TheoryManager'] = None
18
18
  __modules:dict[str, list[Theory]]
@@ -22,7 +22,7 @@ class TheoryManager:
22
22
  def __init__(self):
23
23
  if TheoryManager.__instance is not None:
24
24
  raise Exception('Cannot create more than one instance of TheoryManager') # pragma: no cover
25
- self.__filterPattern = None
25
+ self.__filterPatterns = None
26
26
  self.__modules = {}
27
27
  self.__datas = {}
28
28
  self.__traits = {}
@@ -42,12 +42,12 @@ class TheoryManager:
42
42
  self.__excludeTraits = value
43
43
 
44
44
  @property
45
- def filterPattern(self) -> Optional[re.Pattern]:
46
- return self.__filterPattern
45
+ def filterPatterns(self) -> Optional[list[re.Pattern]]:
46
+ return self.__filterPatterns
47
47
 
48
- @filterPattern.setter
49
- def filterPattern(self, value:re.Pattern) -> None:
50
- self.__filterPattern = value
48
+ @filterPatterns.setter
49
+ def filterPatterns(self, value:list[re.Pattern]) -> None:
50
+ self.__filterPatterns = value
51
51
 
52
52
  @property
53
53
  def includeTraits(self) -> list[Trait]:
@@ -79,7 +79,13 @@ class TheoryManager:
79
79
  return l
80
80
 
81
81
  def put(self, theory:Theory) -> None:
82
- if self.filterPattern is None or len(self.filterPattern.findall(theory.filterName)) > 0:
82
+ matchesFilterPattern:bool = self.filterPatterns is None
83
+ if self.filterPatterns is not None and len(self.filterPatterns) > 0:
84
+ for filterPattern in self.filterPatterns:
85
+ if len(filterPattern.findall(theory.filterName)) > 0:
86
+ matchesFilterPattern = True
87
+ break
88
+ if matchesFilterPattern:
83
89
  l = self.get(theory.moduleName)
84
90
  d = self.__datas.get(theory.target)
85
91
  if d is not None:
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