punit 1.4.8__tar.gz → 1.5.2__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 (44) hide show
  1. {punit-1.4.8/src/pUnit.egg-info → punit-1.5.2}/PKG-INFO +2 -2
  2. {punit-1.4.8 → punit-1.5.2}/README.md +1 -1
  3. {punit-1.4.8 → punit-1.5.2}/pyproject.toml +1 -1
  4. {punit-1.4.8 → punit-1.5.2/src/pUnit.egg-info}/PKG-INFO +2 -2
  5. {punit-1.4.8 → punit-1.5.2}/src/pUnit.egg-info/SOURCES.txt +1 -0
  6. punit-1.5.2/src/punit/__init__.py +26 -0
  7. {punit-1.4.8 → punit-1.5.2}/src/punit/__main__.py +8 -4
  8. {punit-1.4.8 → punit-1.5.2}/src/punit/assertions/__init__.py +2 -1
  9. {punit-1.4.8 → punit-1.5.2}/src/punit/assertions/collections.py +44 -21
  10. {punit-1.4.8 → punit-1.5.2}/src/punit/assertions/exceptions.py +7 -7
  11. punit-1.5.2/src/punit/assertions/numeric.py +651 -0
  12. punit-1.5.2/src/punit/assertions/strings.py +98 -0
  13. {punit-1.4.8 → punit-1.5.2}/src/punit/cli.py +36 -38
  14. punit-1.4.8/src/punit/__init__.py +0 -23
  15. punit-1.4.8/src/punit/assertions/strings.py +0 -55
  16. {punit-1.4.8 → punit-1.5.2}/LICENSE +0 -0
  17. {punit-1.4.8 → punit-1.5.2}/setup.cfg +0 -0
  18. {punit-1.4.8 → punit-1.5.2}/src/pUnit.egg-info/dependency_links.txt +0 -0
  19. {punit-1.4.8 → punit-1.5.2}/src/pUnit.egg-info/entry_points.txt +0 -0
  20. {punit-1.4.8 → punit-1.5.2}/src/pUnit.egg-info/requires.txt +0 -0
  21. {punit-1.4.8 → punit-1.5.2}/src/pUnit.egg-info/top_level.txt +0 -0
  22. {punit-1.4.8 → punit-1.5.2}/src/punit/TestResult.py +0 -0
  23. {punit-1.4.8 → punit-1.5.2}/src/punit/discovery/TestModuleDiscovery.py +0 -0
  24. {punit-1.4.8 → punit-1.5.2}/src/punit/discovery/__init__.py +0 -0
  25. {punit-1.4.8 → punit-1.5.2}/src/punit/facts/Fact.py +0 -0
  26. {punit-1.4.8 → punit-1.5.2}/src/punit/facts/FactManager.py +0 -0
  27. {punit-1.4.8 → punit-1.5.2}/src/punit/facts/__init__.py +0 -0
  28. {punit-1.4.8 → punit-1.5.2}/src/punit/filters/Filter.py +0 -0
  29. {punit-1.4.8 → punit-1.5.2}/src/punit/filters/FilterManager.py +0 -0
  30. {punit-1.4.8 → punit-1.5.2}/src/punit/filters/__init__.py +0 -0
  31. {punit-1.4.8 → punit-1.5.2}/src/punit/metadata/CallableMetadata.py +0 -0
  32. {punit-1.4.8 → punit-1.5.2}/src/punit/metadata/__init__.py +0 -0
  33. {punit-1.4.8 → punit-1.5.2}/src/punit/py.typed +0 -0
  34. {punit-1.4.8 → punit-1.5.2}/src/punit/reports/HtmlReportGenerator.py +0 -0
  35. {punit-1.4.8 → punit-1.5.2}/src/punit/reports/JUnitReportGenerator.py +0 -0
  36. {punit-1.4.8 → punit-1.5.2}/src/punit/reports/JsonReportGenerator.py +0 -0
  37. {punit-1.4.8 → punit-1.5.2}/src/punit/reports/__init__.py +0 -0
  38. {punit-1.4.8 → punit-1.5.2}/src/punit/runner.py +0 -0
  39. {punit-1.4.8 → punit-1.5.2}/src/punit/theories/Theory.py +0 -0
  40. {punit-1.4.8 → punit-1.5.2}/src/punit/theories/TheoryManager.py +0 -0
  41. {punit-1.4.8 → punit-1.5.2}/src/punit/theories/__init__.py +0 -0
  42. {punit-1.4.8 → punit-1.5.2}/src/punit/traits/Trait.py +0 -0
  43. {punit-1.4.8 → punit-1.5.2}/src/punit/traits/TraitManager.py +0 -0
  44. {punit-1.4.8 → punit-1.5.2}/src/punit/traits/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pUnit
3
- Version: 1.4.8
3
+ Version: 1.5.2
4
4
  Summary: A modernized unit-test framework for Python.
5
5
  Author-email: Shaun Wilson <mrshaunwilson@msn.com>
6
6
  License: MIT License
@@ -114,7 +114,7 @@ Options:
114
114
  Default: '*.py'
115
115
  -e, --exclude PATTERN
116
116
  Exclude test files matching PATTERN, overriding --include
117
- Default: '__*__' (dunder files), '/.*/' (dot-directories)
117
+ Default: '__*__' (dunders)
118
118
  -f, --filter PATTERN|@FILEPATH
119
119
  Only execute tests matching PATTERN
120
120
  Default: '*'
@@ -70,7 +70,7 @@ Options:
70
70
  Default: '*.py'
71
71
  -e, --exclude PATTERN
72
72
  Exclude test files matching PATTERN, overriding --include
73
- Default: '__*__' (dunder files), '/.*/' (dot-directories)
73
+ Default: '__*__' (dunders)
74
74
  -f, --filter PATTERN|@FILEPATH
75
75
  Only execute tests matching PATTERN
76
76
  Default: '*'
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pUnit"
3
- version = "1.4.8"
3
+ version = "1.5.2"
4
4
  description = "A modernized unit-test framework for Python."
5
5
  keywords = ["test", "unittest", "unit-test", "xUnit", "nUnit", "pytest"]
6
6
  authors = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pUnit
3
- Version: 1.4.8
3
+ Version: 1.5.2
4
4
  Summary: A modernized unit-test framework for Python.
5
5
  Author-email: Shaun Wilson <mrshaunwilson@msn.com>
6
6
  License: MIT License
@@ -114,7 +114,7 @@ Options:
114
114
  Default: '*.py'
115
115
  -e, --exclude PATTERN
116
116
  Exclude test files matching PATTERN, overriding --include
117
- Default: '__*__' (dunder files), '/.*/' (dot-directories)
117
+ Default: '__*__' (dunders)
118
118
  -f, --filter PATTERN|@FILEPATH
119
119
  Only execute tests matching PATTERN
120
120
  Default: '*'
@@ -16,6 +16,7 @@ src/punit/runner.py
16
16
  src/punit/assertions/__init__.py
17
17
  src/punit/assertions/collections.py
18
18
  src/punit/assertions/exceptions.py
19
+ src/punit/assertions/numeric.py
19
20
  src/punit/assertions/strings.py
20
21
  src/punit/discovery/TestModuleDiscovery.py
21
22
  src/punit/discovery/__init__.py
@@ -0,0 +1,26 @@
1
+ # SPDX-FileCopyrightText: © 2024 Shaun Wilson
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from .assertions import collections, exceptions, numeric, strings
5
+ from .facts import fact
6
+ from .theories import theory, inlinedata
7
+ from .traits import trait
8
+
9
+ from .assertions.exceptions import raises
10
+ from .assertions.numeric import approx
11
+
12
+
13
+ __version__ = '1.5.2'
14
+ __commit__ = '19ca1ae'
15
+ __all__ = [
16
+ '__version__', '__commit__',
17
+ 'assertions',
18
+ 'collections',
19
+ 'exceptions', 'raises',
20
+ 'numeric', 'approx',
21
+ 'strings',
22
+ 'fact',
23
+ 'metadata',
24
+ 'theory', 'inlinedata',
25
+ 'trait'
26
+ ]
@@ -5,6 +5,8 @@ import asyncio
5
5
  import os
6
6
  import sys
7
7
  import time
8
+ from pathlib import Path
9
+
8
10
  from .cli import CommandLineInterface
9
11
  from .discovery import TestModuleDiscovery
10
12
  from .reports import HtmlReportGenerator, JUnitReportGenerator, JsonReportGenerator
@@ -22,10 +24,12 @@ async def async_main() -> None:
22
24
  cli.printVersion()
23
25
  os.chdir(cli.workdir)
24
26
  if cli.no_pathfix is not True:
25
- if os.path.exists('src') and 'src' not in sys.path:
26
- sys.path.append('src')
27
- if '.' not in sys.path:
28
- sys.path.append('src')
27
+ pathbase = str(Path.cwd())
28
+ srcbase = os.path.join(pathbase, 'src')
29
+ if os.path.exists(srcbase) and srcbase not in sys.path:
30
+ sys.path.append(srcbase)
31
+ if pathbase not in sys.path:
32
+ sys.path.append(pathbase)
29
33
  testModuleDiscovery = TestModuleDiscovery(
30
34
  os.path.join(cli.workdir, cli.testPackageName),
31
35
  cli.includePatterns,
@@ -1,11 +1,12 @@
1
1
  # SPDX-FileCopyrightText: © 2024 Shaun Wilson
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
- from . import collections, exceptions, strings
4
+ from . import collections, exceptions, numeric, strings
5
5
 
6
6
 
7
7
  __all__ = [
8
8
  'collections',
9
9
  'exceptions',
10
+ 'numeric',
10
11
  'strings'
11
12
  ]
@@ -4,12 +4,14 @@
4
4
  from typing import Any, Callable, Optional, Sequence, cast
5
5
 
6
6
 
7
- def areSame(actual: Sequence[Any] | set[Any] | dict[Any, Any] | None, expected: Sequence[Any] | set[Any] | dict[Any, Any] | None, sort: bool = False, sort_function: Optional[Callable[[Any], Any]] = None) -> bool:
7
+ def are_same(actual: Sequence[Any] | set[Any] | dict[Any, Any] | None, expected: Sequence[Any] | set[Any] | dict[Any, Any] | None, sort: bool = False, sort_function: Optional[Callable[[Any], Any]] = None) -> bool:
8
8
  """
9
9
  Check if two sequences contain the same elements in the same order.
10
-
11
- :param actual: The sequence to check
12
- :param expected: The sequence to compare against
10
+
11
+ Can optionally specify *sort* so that differences in order do not cause failure.
12
+
13
+ :param actual: The sequence to check.
14
+ :param expected: The sequence to compare against.
13
15
  :param sort: Sort sequences before performing comparisons.
14
16
  :param sort_function: Custom function to use when sorting.
15
17
  :returns bool: True if the sequences contain the same elements in the same order, False otherwise.
@@ -27,44 +29,48 @@ def areSame(actual: Sequence[Any] | set[Any] | dict[Any, Any] | None, expected:
27
29
  if sort:
28
30
  if isinstance(actual, dict) or isinstance(expected, dict):
29
31
  sort_function = sort_function if sort_function is not None else lambda e: e[0]
30
- actual = sorted(cast(dict, actual).items(), key=sort_function)
31
- expected = sorted(cast(dict, expected).items(), key=sort_function)
32
+ actual = sorted(cast(dict[Any, Any], actual).items(), key=sort_function)
33
+ expected = sorted(cast(dict[Any, Any], expected).items(), key=sort_function)
32
34
  else:
33
35
  sort_function = sort_function if sort_function is not None else lambda e: e
34
36
  actual = sorted(actual, key=sort_function)
35
37
  expected = sorted(expected, key=sort_function)
36
38
 
37
39
  if isinstance(actual, dict) or isinstance(expected, dict):
38
- for pairs in zip(cast(dict, actual).items(), cast(dict, expected).items()):
40
+ for pairs in zip(cast(dict[Any, Any], actual).items(), cast(dict[Any, Any], expected).items()):
39
41
  if not areSame(pairs[0], pairs[1]):
40
- return False
42
+ return False
41
43
  else:
42
44
  for pairs in zip(actual, expected):
43
45
  if isinstance(pairs[0], dict) or isinstance(pairs[1], dict):
44
46
  if not areSame(pairs[0], pairs[1]):
45
- return False
46
- elif pairs[0] != pairs[1]:
47
47
  return False
48
+ elif pairs[0] != pairs[1]:
49
+ return False
48
50
  return True
49
51
 
50
- def hasLength(actual: Sequence[Any] | set[Any] | dict[Any, Any] | None, expected: int | None) -> bool:
52
+
53
+ def has_length(actual: Sequence[Any] | set[Any] | dict[Any, Any] | None, min: Optional[int] = None, max: Optional[int] = None) -> bool:
51
54
  """
52
55
  Check if actual value has the expected number of elements.
53
-
56
+
54
57
  :param actual: The actual value to check.
55
58
  :param int|None expected: The expected number of elements
56
-
59
+
57
60
  :returns bool: True if the sequence has exactly the expected number of elements, False otherwise
58
61
  """
59
- if actual is None and (expected is None or expected == 0):
60
- return True
61
- elif actual is None and (expected is not None and expected != 0):
62
- return False
63
- elif actual is not None and expected is None:
64
- return False
65
- return actual is not None and len(actual) == expected
62
+ if actual is None:
63
+ if ((min is None or min == 0) and (max is None or max == 0)):
64
+ return True
65
+ return not ((min is not None and min != 0) or (max is not None or max != 0))
66
+ else:
67
+ if ((min is None) and (max is None)):
68
+ return False
69
+ len_actual = len(actual)
70
+ return (min is None or len_actual >= min) and (max is None or len_actual <= max)
71
+
66
72
 
67
- def isNoneOrEmpty(actual: Sequence[Any] | set[Any] | dict[Any, Any] | None) -> bool:
73
+ def is_none_or_empty(actual: Sequence[Any] | set[Any] | dict[Any, Any] | None) -> bool:
68
74
  """
69
75
  Check if actual value is None or empty.
70
76
 
@@ -74,3 +80,20 @@ def isNoneOrEmpty(actual: Sequence[Any] | set[Any] | dict[Any, Any] | None) -> b
74
80
  if actual is None:
75
81
  return True
76
82
  return len(actual) == 0
83
+
84
+
85
+ # DEPRECATIONS
86
+ areSame = are_same
87
+ hasLength = has_length
88
+ isNoneOrEmpty = is_none_or_empty
89
+
90
+
91
+ __all__ = [
92
+ 'are_same',
93
+ 'has_length',
94
+ 'is_none_or_empty',
95
+ # deprecated (do not use):
96
+ 'areSame',
97
+ 'hasLength',
98
+ 'isNoneOrEmpty'
99
+ ]
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: © 2026 Shaun Wilson
1
+ # SPDX-FileCopyrightText: © 2024 Shaun Wilson
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
4
  from typing import Any, Callable, Generic, Optional, TypeVar, cast, get_args
@@ -8,12 +8,12 @@ TError = TypeVar('TError', bound=Exception)
8
8
 
9
9
 
10
10
  class raises(Generic[TError]):
11
-
12
- __action:Callable
13
- __exact:bool
14
- __expect:Optional[TError|type]
15
11
 
16
- def __init__(self, action:Callable, *, exact:bool = False, expect:Optional[TError|type] = None) -> None:
12
+ __action: Callable[[], Any]
13
+ __exact: bool
14
+ __expect: Optional[TError | type]
15
+
16
+ def __init__(self, action: Callable[[], Any], *, exact: bool = False, expect: Optional[TError | type] = None) -> None:
17
17
  self.__action = action
18
18
  self.__exact = exact
19
19
  self.__expect = expect
@@ -28,7 +28,7 @@ class raises(Generic[TError]):
28
28
  if self.__exact:
29
29
  return type(ex) is expected
30
30
  elif expected is not None:
31
- return issubclass(type(ex), cast(Any,expected))
31
+ return issubclass(type(ex), cast(Any, expected))
32
32
  return False
33
33
 
34
34