Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

represent various objects when logging better #98

Merged
merged 19 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions screenpy/actions/make_note.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from screenpy.exceptions import UnableToAct
from screenpy.pacing import aside, beat
from screenpy.protocols import Answerable, ErrorKeeper
from screenpy.speech_tools import represent_prop

SelfMakeNote = TypeVar("SelfMakeNote", bound="MakeNote")
T_Q = Union[Answerable, object]
Expand Down Expand Up @@ -54,9 +55,9 @@ def as_(self: SelfMakeNote, key: str) -> SelfMakeNote:

def describe(self: SelfMakeNote) -> str:
"""Describe the Action in present tense."""
return f"Make a note under {self.key}."
return f"Make a note under {represent_prop(self.key)}."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be key_to_log instead, just in case we change our mind on represent_prop.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(And it looks like that's the approach you have in the other describe methods, to use *_to_log.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've always worried that setting the variable in the constructor would somehow lead to a problem if anyone were to alter the attribute being logged after instantiation. It might be a non-issue but it's one of the reasons I try to avoid it as much as possible.

We want the value coming out of describe to be accurate at the moment it is called.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot that part of the reason we have *_to_log is for the beat message. I kinda want to go through each of the classes and make those attributes properties.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they will not need to be around any longer, ideally, once we figure out this whole update to the logging bit. Or maybe the description/beat itself becomes a property, i think that would be slick.

Either way, let's do the describe reimagining before we do a change like that, because it might not be necessary in that brave new world.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that would be slick.

It really would. the only reason I didn't earlier is because the pattern wasn't already being used. I'll open an issue to add those at some point.


@beat('{} jots something down under "{key}".')
@beat("{} jots something down under {key_to_log}.")
def perform_as(self: SelfMakeNote, the_actor: Actor) -> None:
"""Direct the Actor to take a note."""
if self.key is None:
Expand All @@ -81,3 +82,4 @@ def __init__(
) -> None:
self.question = question
self.key = key
self.key_to_log = represent_prop(key)
4 changes: 2 additions & 2 deletions screenpy/actions/see.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from screenpy.actor import Actor
from screenpy.pacing import aside, beat
from screenpy.protocols import Answerable, ErrorKeeper, Resolvable
from screenpy.speech_tools import get_additive_description
from screenpy.speech_tools import get_additive_description, represent_prop

SelfSee = TypeVar("SelfSee", bound="See")
T_Q = Union[Answerable, object]
Expand Down Expand Up @@ -56,7 +56,7 @@ def perform_as(self: SelfSee, the_actor: Actor) -> None:
else:
# must be a value instead of a question!
value = self.question
aside(f"the actual value is: {value}")
aside(f"the actual value is: {represent_prop(value)}")

reason = ""
if isinstance(self.question, ErrorKeeper):
Expand Down
3 changes: 2 additions & 1 deletion screenpy/pacing.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from typing import Any, Callable, Optional

from screenpy.narration import Narrator, StdOutAdapter
from screenpy.speech_tools import represent_prop

Function = Callable[..., Any]
the_narrator: Narrator = Narrator(adapters=[StdOutAdapter()])
Expand Down Expand Up @@ -88,7 +89,7 @@ def wrapper(*args: Any, **kwargs: Any) -> Any:
with the_narrator.stating_a_beat(func, completed_line, gravitas) as n_func:
retval = n_func(*args, **kwargs)
if retval is not None:
aside(f"=> {retval}")
aside(f"=> {represent_prop(retval)}")
return retval

return wrapper
Expand Down
5 changes: 4 additions & 1 deletion screenpy/resolutions/contains_the_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

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

K = TypeVar("K", bound=Hashable)
V = TypeVar("V")
Expand Down Expand Up @@ -78,4 +79,6 @@ def __init__(self, *kv_args: Any, **kv_kwargs: Any) -> None:
]
self.entries = dict(pairs, **kv_kwargs)
self.entry_plural = "entries" if len(self.entries) != 1 else "entry"
self.entries_to_log = ", ".join(f"{k}->{v}" for k, v in self.entries.items())
self.entries_to_log = ", ".join(
f"{represent_prop(k)}->{represent_prop(v)}" for k, v in self.entries.items()
)
6 changes: 4 additions & 2 deletions screenpy/resolutions/contains_the_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from hamcrest.core.matcher import Matcher

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

T = TypeVar("T")

Expand All @@ -24,12 +25,13 @@ class ContainsTheItem:

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f'A sequence containing "{self.item}".'
return f"A sequence containing {self.item_to_log}."

@beat('... hoping it contains "{item}".')
@beat("... hoping it contains {item_to_log}.")
def resolve(self) -> Matcher[Sequence[T]]:
"""Produce the Matcher to make the assertion."""
return has_item(self.item)

def __init__(self, item: T) -> None:
self.item = item
self.item_to_log = represent_prop(item)
6 changes: 4 additions & 2 deletions screenpy/resolutions/contains_the_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from hamcrest.core.matcher import Matcher

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

K = TypeVar("K", bound=Hashable)

Expand All @@ -22,12 +23,13 @@ class ContainsTheKey(Generic[K]):

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f'Containing the key "{self.key}".'
return f"Containing the key {self.key_to_log}."

@beat('... hoping it\'s a dict containing the key "{key}".')
@beat("... hoping it's a dict containing the key {key_to_log}.")
def resolve(self) -> Matcher[Mapping[K, Any]]:
"""Produce the Matcher to make the assertion."""
return has_key(self.key)

def __init__(self, key: K) -> None:
self.key = key
self.key_to_log = represent_prop(key)
6 changes: 4 additions & 2 deletions screenpy/resolutions/contains_the_text.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 ContainsTheText:
Expand All @@ -20,12 +21,13 @@ class ContainsTheText:

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f'Containing the text "{self.text}".'
return f"Containing the text {self.text_to_log}."

@beat('... hoping it contains "{text}".')
@beat("... hoping it contains {text_to_log}.")
def resolve(self) -> Matcher[str]:
"""Produce the Matcher to make the assertion."""
return contains_string(self.text)

def __init__(self, text: str) -> None:
self.text = text
self.text_to_log = represent_prop(text)
6 changes: 4 additions & 2 deletions screenpy/resolutions/contains_the_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from hamcrest.core.matcher import Matcher

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

V = TypeVar("V")

Expand All @@ -24,12 +25,13 @@ class ContainsTheValue(Generic[V]):

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f'Containing the value "{self.value}".'
return f"Containing the value {self.value_to_log}."

@beat('... hoping it contains the value "{value}".')
@beat("... hoping it contains the value {value_to_log}.")
def resolve(self) -> Matcher[Mapping[Any, V]]:
"""Produce the Matcher to form the assertion."""
return has_value(self.value)

def __init__(self, value: V) -> None:
self.value = value
self.value_to_log = represent_prop(value)
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ 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 {self.pattern}"
f'a sequence containing an element which matches r"{self.pattern}"'
bandophahita marked this conversation as resolved.
Show resolved Hide resolved
)

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


Expand Down
6 changes: 4 additions & 2 deletions screenpy/resolutions/ends_with.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 EndsWith:
Expand All @@ -20,12 +21,13 @@ class EndsWith:

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f'Ending with "{self.postfix}".'
return f"Ending with {self.postfix_to_log}."

@beat('... hoping it ends with "{postfix}".')
@beat("... hoping it ends with {postfix_to_log}.")
def resolve(self) -> Matcher[str]:
"""Produce the Matcher to make the assertion."""
return ends_with(self.postfix)

def __init__(self, postfix: str) -> None:
self.postfix = postfix
self.postfix_to_log = represent_prop(postfix)
6 changes: 4 additions & 2 deletions screenpy/resolutions/is_equal_to.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from hamcrest.core.matcher import Matcher

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


class IsEqualTo:
Expand All @@ -22,12 +23,13 @@ class IsEqualTo:

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f"Equal to {self.expected}."
return f"Equal to {self.expected_to_log}."

@beat("... hoping it's equal to {expected}.")
@beat("... hoping it's equal to {expected_to_log}.")
def resolve(self) -> Matcher[Any]:
"""Produce the Matcher to make the assertion."""
return equal_to(self.expected)

def __init__(self, obj: Any) -> None:
self.expected = obj
self.expected_to_log = represent_prop(obj)
6 changes: 4 additions & 2 deletions screenpy/resolutions/is_greater_than.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from hamcrest.core.matcher import Matcher

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


class IsGreaterThan:
Expand All @@ -20,12 +21,13 @@ class IsGreaterThan:

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f"Greater than {self.number}."
return f"Greater than {self.number_to_log}."

@beat("... hoping it's greater than {number}.")
@beat("... hoping it's greater than {number_to_log}.")
def resolve(self) -> Matcher[Any]:
"""Produce the Matcher to make the assertion."""
return greater_than(self.number)

def __init__(self, number: float) -> None:
self.number = number
self.number_to_log = represent_prop(number)
6 changes: 4 additions & 2 deletions screenpy/resolutions/is_greater_than_or_equal_to.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from hamcrest.core.matcher import Matcher

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


class IsGreaterThanOrEqualTo:
Expand All @@ -22,12 +23,13 @@ class IsGreaterThanOrEqualTo:

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f"Greater than or equal to {self.number}."
return f"Greater than or equal to {self.number_to_log}."

@beat("... hoping it's greater than or equal to {number}.")
@beat("... hoping it's greater than or equal to {number_to_log}.")
def resolve(self) -> Matcher[Any]:
"""Produce the Matcher to make the assertion."""
return greater_than_or_equal_to(self.number)

def __init__(self, number: float) -> None:
self.number = number
self.number_to_log = represent_prop(number)
6 changes: 4 additions & 2 deletions screenpy/resolutions/is_less_than.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 IsLessThan:
Expand All @@ -20,12 +21,13 @@ class IsLessThan:

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f"Less than {self.number}."
return f"Less than {self.number_to_log}."

@beat("... hoping it's less than {number}.")
@beat("... hoping it's less than {number_to_log}.")
def resolve(self) -> Matcher[float]:
"""Produce the Matcher to make the assertion."""
return less_than(self.number)

def __init__(self, number: float) -> None:
self.number = number
self.number_to_log = represent_prop(number)
6 changes: 4 additions & 2 deletions screenpy/resolutions/is_less_than_or_equal_to.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 IsLessThanOrEqualTo:
Expand All @@ -20,12 +21,13 @@ class IsLessThanOrEqualTo:

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f"Less than or equal to {self.number}."
return f"Less than or equal to {self.number_to_log}."

@beat("... hoping it's less than or equal to {number}.")
@beat("... hoping it's less than or equal to {number_to_log}.")
def resolve(self) -> Matcher[float]:
"""Produce the Matcher to make the assertion."""
return less_than_or_equal_to(self.number)

def __init__(self, number: float) -> None:
self.number = number
self.number_to_log = represent_prop(number)
6 changes: 4 additions & 2 deletions screenpy/resolutions/reads_exactly.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 ReadsExactly:
Expand All @@ -20,12 +21,13 @@ class ReadsExactly:

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f'"{self.text}", verbatim.'
return f"{self.text_to_log}, verbatim."

@beat('... hoping it\'s "{text}", verbatim.')
@beat("... hoping it's {text_to_log}, verbatim.")
def resolve(self) -> Matcher[object]:
"""Produce the Matcher to make the assertion."""
return has_string(self.text)

def __init__(self, text: str) -> None:
self.text = text
self.text_to_log = represent_prop(text)
6 changes: 4 additions & 2 deletions screenpy/resolutions/starts_with.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 StartsWith:
Expand All @@ -20,12 +21,13 @@ class StartsWith:

def describe(self) -> str:
"""Describe the Resolution's expectation."""
return f'Starting with "{self.prefix}".'
return f"Starting with {self.prefix_to_log}."

@beat('... hoping it starts with "{prefix}".')
@beat("... hoping it starts with {prefix_to_log}.")
def resolve(self) -> Matcher[str]:
"""Produce the Matcher to make the assertion."""
return starts_with(self.prefix)

def __init__(self, prefix: str) -> None:
self.prefix = prefix
self.prefix_to_log = represent_prop(prefix)
Loading