Skip to content

Commit

Permalink
Code coverage (#141)
Browse files Browse the repository at this point in the history
* adding coverage exclusions
* adding coverage for represent_prop, ContainsTheEntry, ContainsItemMatching, 
    ContainsTheItem, ContainsTheKey, ContainsTheText, ContainsTheValue, 
    IsEmpty, EndsWith, HasLength, IsCloseTo, IsEqualTo, IsGreaterThan, 
    IsGreaterThanOrEqualTo, IsInRange, IsLessThan, IsLessThanOrEqualTo, 
    IsLessThanOrEqualTo, IsNot, ReadsExactly, StartsWith, custom matchers
* ensuring proper format of logged pattern
* fixed path mocking to avoid false positive
* configuring coverage to skip reporting of tests
* removing redundant coverage exclusion
* removing exclude since we don't have `:members:` to begin with (re: PR comments)
* ignoring pycharm project files in git
* latest version of ruff no longer triggers PLR0913 on `settings_customise_sources` which causes it to complain about RUF100 (unused noqa) while pylint does not.
* use a dummy settings class instead of mocking.
* update dependencies.
---------
Co-authored-by: Perry Goy <[email protected]>
  • Loading branch information
bandophahita authored Aug 2, 2024
1 parent 8aa6c94 commit b5be493
Show file tree
Hide file tree
Showing 16 changed files with 988 additions and 452 deletions.
2 changes: 1 addition & 1 deletion .cruft.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"template": "https://github.com/ScreenPyHQ/cookiecutter_screenpy/",
"commit": "2b69298215c08160678dd749884c426a55828dce",
"commit": "4ad86820b5729801d7c765e04cfda2e953671164",
"checkout": null,
"context": {
"cookiecutter": {
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,6 @@ dmypy.json

# ruff linter
.ruff_cache/

#pycharm project files
.idea/
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ files: '(screenpy|tests)/.*'
fail_fast: false
repos:
- repo: https://github.com/psf/black
rev: 24.1.1
rev: 24.4.2
hooks:
- id: black
language_version: python3.12
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.2.0
rev: v0.5.5
hooks:
- id: ruff
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
rev: v1.11.1
hooks:
- id: mypy
language_version: python3.12
Expand Down
865 changes: 452 additions & 413 deletions poetry.lock

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ extend-exclude = '''
[tool.ruff]
target-version = "py38" # minimum supported version
line-length = 88 # same as Black.
output-format = "concise"
extend-exclude = [
"docs",
]
Expand Down Expand Up @@ -234,3 +235,16 @@ playwright = ["screenpy-playwright"]
pyotp = ["screenpy-pyotp"]
requests = ["screenpy-requests"]
selenium = ["screenpy-selenium"]

[tool.coverage.run]
source = ["screenpy"]
omit = [
"/tests/*",
]


[tool.coverage.report]
exclude_also = [
"if TYPE_CHECKING:",
"pass",
]
6 changes: 3 additions & 3 deletions screenpy/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@

from pydantic.fields import FieldInfo

if sys.version_info >= (3, 11):
if sys.version_info >= (3, 11): # pragma: no cover
try:
import tomllib
except ImportError:
if not TYPE_CHECKING:
# Help users on older alphas
import tomli as tomllib
else:
else: # pragma: no cover
import tomli as tomllib


Expand Down Expand Up @@ -142,7 +142,7 @@ class ScreenPySettings(BaseSettings):
"""

@classmethod
def settings_customise_sources( # noqa: PLR0913
def settings_customise_sources( # noqa: PLR0913, RUF100
cls,
settings_cls: type[BaseSettings],
init_settings: PydanticBaseSettingsSource,
Expand Down
4 changes: 2 additions & 2 deletions screenpy/resolutions/contains_item_matching.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ class ContainsItemMatching:

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f'A sequence with an item matching the pattern r"{self.pattern}".'
return f"A sequence with an item matching the pattern r'{self.pattern}'."

@beat('... hoping it contains an item matching the pattern r"{pattern}".')
@beat("... hoping it contains an item matching the pattern r'{pattern}'.")
def resolve(self) -> Matcher[Sequence[str]]:
"""Produce the Matcher to make the assertion."""
return has_item_matching(self.pattern)
Expand Down
27 changes: 21 additions & 6 deletions screenpy/resolutions/custom_matchers/is_in_bounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,16 @@
InequalityFunc = Callable[[float, float], bool]


class DegenerateIntervalError(ValueError):
"""ValueError specifically for degenerate intervals."""


class IsInBounds(BaseMatcher[float]):
"""Matches a number which is in the given range."""
"""Matches a number which is in the given range.
Only supports proper intervals.
https://en.wikipedia.org/wiki/Interval_%28mathematics%29#Notations_for_intervals
"""

def __init__(
self,
Expand All @@ -32,6 +40,9 @@ def __init__(
upper_comparator: InequalityFunc,
majorant: float,
) -> None:
if minorant >= majorant:
msg = f"minorant ({minorant}) must be less than majorant ({majorant})."
raise DegenerateIntervalError(msg)
self.minorant = minorant
self.lower_comparator = lower_comparator
self.upper_comparator = upper_comparator
Expand Down Expand Up @@ -62,16 +73,20 @@ def describe_mismatch(self, item: float, mismatch_description: Description) -> N
)


def is_in_bounds(*bounds: int | (float | str)) -> IsInBounds:
def is_in_bounds(*bounds: int | float | str) -> IsInBounds:
"""Matches a number that falls within the bounds."""
lower_comparator = operator.le
upper_comparator = operator.le
if len(bounds) == 1:
bounding_string = str(bounds[0])
pattern = (
r"^(?P<lower>[\[\(]?)"
r"(?P<minorant>\d+).*?(?P<majorant>\d+)"
r"(?P<upper>[\]\)]?)$"
pattern = re.compile(
r"^" # start of line
r"(?P<lower>[\[(]?)" # [ or (
r"(?P<minorant>-?(\d+\.?\d*)|(\.\d+))" # minorant (int or float)
r"[\-, ]+?" # any number of comma, dash and space
r"(?P<majorant>-?(\d+\.?\d*)|(\.\d+))" # majorant (int or float)
r"(?P<upper>[])]?)" # ) or ]
r"$" # end of line
)
matched = re.match(pattern, bounding_string)
if matched is None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ def _matches(self, item: Sequence[str]) -> bool:
def describe_to(self, description: Description) -> None:
"""Describe the passing case."""
description.append_text(
f'a sequence containing an element which matches r"{self.pattern}"'
f"a sequence containing an element which matches r'{self.pattern}'"
)

def describe_match(self, _: Sequence[str], match_description: Description) -> None:
"""Describe the match, for use with IsNot."""
match_description.append_text(f'it contains an item matching "{self.pattern}"')
match_description.append_text(f"it contains an item matching r'{self.pattern}'")

def describe_mismatch(
self, item: Sequence[str], mismatch_description: Description
Expand All @@ -41,7 +41,7 @@ def describe_mismatch(
mismatch_description.append_text("was not a sequence")
return
mismatch_description.append_text(
f'did not contain an item matching r"{self.pattern}"'
f"did not contain an item matching r'{self.pattern}'"
)


Expand Down
10 changes: 8 additions & 2 deletions screenpy/resolutions/has_length.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from hamcrest.core.matcher import Matcher

from screenpy.pacing import beat
from screenpy.speech_tools import represent_prop


class HasLength:
Expand All @@ -18,16 +19,21 @@ class HasLength:
)
"""

@property
def length_to_log(self) -> str:
"""Represent the length in a log-friendly way."""
return represent_prop(self.length)

@property
def item_plural(self) -> str:
"""Decide if we need "item" or "items" in the beat message."""
return "items" if self.length != 1 else "item"

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f"{self.length} {self.item_plural} long."
return f"{self.length_to_log} {self.item_plural} long."

@beat("... hoping it's a collection with {length} {item_plural} in it.")
@beat("... hoping it's a collection with {length_to_log} {item_plural} in it.")
def resolve(self) -> Matcher[Sized]:
"""Produce the Matcher to make the assertion."""
return has_length(self.length)
Expand Down
15 changes: 13 additions & 2 deletions screenpy/resolutions/is_close_to.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from hamcrest.core.matcher import Matcher

from screenpy.pacing import beat
from screenpy.speech_tools import represent_prop


class IsCloseTo:
Expand All @@ -16,11 +17,21 @@ class IsCloseTo:
)
"""

@property
def delta_to_log(self) -> str:
"""Represent the delta in a log-friendly way."""
return represent_prop(self.delta)

@property
def num_to_log(self) -> str:
"""Represent the num in a log-friendly way."""
return represent_prop(self.num)

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f"At most {self.delta} away from {self.num}."
return f"At most {self.delta_to_log} away from {self.num_to_log}."

@beat("... hoping it's at most {delta} away from {num}.")
@beat("... hoping it's at most {delta_to_log} away from {num_to_log}.")
def resolve(self) -> Matcher[float]:
"""Produce the Matcher to make the assertion."""
return close_to(self.num, self.delta)
Expand Down
2 changes: 1 addition & 1 deletion screenpy/resolutions/matches.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from screenpy.pacing import beat

if TYPE_CHECKING: # pragma: no cover
if TYPE_CHECKING:
from hamcrest.core.matcher import Matcher


Expand Down
Loading

0 comments on commit b5be493

Please sign in to comment.