Skip to content

Commit

Permalink
0.13.8: tag on deploy; remove coloration; remove header in explanatio…
Browse files Browse the repository at this point in the history
…n; rename module wrappers->iterators
  • Loading branch information
ebonnal committed Jul 1, 2024
1 parent f6a8def commit 4fc0fe6
Show file tree
Hide file tree
Showing 10 changed files with 32 additions and 74 deletions.
16 changes: 13 additions & 3 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ name: PyPI

on:
push:
tags:
- 'v*'
branches:
- main
paths:
- 'version.py'

jobs:
pypi:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v1
with:
Expand All @@ -24,3 +27,10 @@ jobs:
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
- name: Tag
run: |
TAG=$(python -c 'from version import __version__; print(__version__)' | sed 's/^/v/')
git config --global user.name 'github-actions'
git config --global user.email '[email protected]'
git tag -a $TAG -m"Release $TAG"
git push origin $TAG
6 changes: 3 additions & 3 deletions streamable/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
cast,
)

from streamable.wrappers import (
from streamable.iterators import (
AsyncConcurrentMappingIterable,
CatchingIterator,
ConcurrentFlatteningIterable,
Expand Down Expand Up @@ -118,8 +118,8 @@ def amap(
)


def observe(iterator: Iterator[T], what: str, colored: bool = False) -> Iterator[T]:
return ObservingIterator(iterator, what, colored)
def observe(iterator: Iterator[T], what: str) -> Iterator[T]:
return ObservingIterator(iterator, what)


def slow(iterator: Iterator[T], frequency: float) -> Iterator[T]:
Expand Down
11 changes: 1 addition & 10 deletions streamable/wrappers.py → streamable/iterators.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,26 +203,17 @@ def __next__(self):


class ObservingIterator(Iterator[T]):
def __init__(self, iterator: Iterator[T], what: str, colored: bool) -> None:
def __init__(self, iterator: Iterator[T], what: str) -> None:
self.iterator = iterator
self.what = what
self.colored = colored
self._n_yields = 0
self._n_errors = 0
self._last_log_after_n_calls = 0
self._start_time = time.time()

def _log(self) -> None:
errors_summary = f"errors={self._n_errors}"

if self.colored and self._n_errors > 0:
# colorize the error summary in red if any
errors_summary = util.bold(util.colorize_in_red(errors_summary))

yields_summary = f"{self._n_yields} {self.what} yielded"
if self.colored:
yields_summary = util.bold(yields_summary)

elapsed_time = f"duration={datetime.fromtimestamp(time.time()) - datetime.fromtimestamp(self._start_time)}"

util.get_logger().info(
Expand Down
16 changes: 7 additions & 9 deletions streamable/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,21 +121,21 @@ def catch(
"""
return CatchStream(self, when, raise_after_exhaustion=raise_after_exhaustion)

def explain(self, colored: bool = False) -> "Stream[T]":
def explain(self) -> "Stream[T]":
"""
Logs this stream's explanation (INFO level)
"""
get_logger().info("explanation:\n%s", self.explanation(colored))
get_logger().info("explanation:\n%s", self.explanation())
return self

def explanation(self, colored: bool = False) -> str:
def explanation(self) -> str:
"""
Returns:
str: A pretty representation of this stream's operations.
"""
from streamable.visitors import explanation

return self.accept(explanation.ExplanationVisitor(colored))
return self.accept(explanation.ExplanationVisitor())

def filter(self, keep: Callable[[T], Any] = bool) -> "Stream[T]":
"""
Expand Down Expand Up @@ -315,7 +315,7 @@ def amap(
validate_concurrency(concurrency)
return AMapStream(self, transformation, concurrency)

def observe(self, what: str = "elements", colored: bool = False) -> "Stream[T]":
def observe(self, what: str = "elements") -> "Stream[T]":
"""
Logs the progress of the iterations over this stream.
Expand All @@ -328,12 +328,11 @@ def observe(self, what: str = "elements", colored: bool = False) -> "Stream[T]":
Args:
what (str): (plural) name representing the objects yielded.
colored (bool): whether or not to use ascii colorization.
Returns:
Stream[T]: A stream of upstream elements whose iteration is logged for observability.
"""
return ObserveStream(self, what, colored)
return ObserveStream(self, what)

def slow(self, frequency: float) -> "Stream[T]":
"""
Expand Down Expand Up @@ -485,10 +484,9 @@ def accept(self, visitor: "Visitor[V]") -> V:


class ObserveStream(DownStream[T, T]):
def __init__(self, upstream: Stream[T], what: str, colored: bool) -> None:
def __init__(self, upstream: Stream[T], what: str) -> None:
super().__init__(upstream)
self.what = what
self.colored = colored

def accept(self, visitor: "Visitor[V]") -> V:
return visitor.visit_observe_stream(self)
Expand Down
12 changes: 0 additions & 12 deletions streamable/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,6 @@ def validate_truncate_args(
raise ValueError(f"`count` must be less than sys.maxsize but got {count}.")


def colorize_in_red(s: str) -> str:
return f"\033[91m{s}\033[0m"


def colorize_in_grey(s: str) -> str:
return f"\033[90m{s}\033[0m"


def bold(s: str) -> str:
return f"\033[1m{s}\033[0m"


def get_name(o: object) -> str:
if o is None:
return "None"
Expand Down
26 changes: 2 additions & 24 deletions streamable/visitors/explanation.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,15 @@
class ExplanationVisitor(Visitor[str]):
def __init__(
self,
colored: bool = False,
margin_step: int = 2,
header: str = "",
) -> None:
self.colored = colored
self.header = header
self.margin_step = margin_step

self.linking_symbol = "└" + "─" * (self.margin_step - 1) + "•"

if self.colored:
self.header = util.bold(self.header)
if self.colored:
self.linking_symbol = util.colorize_in_grey(self.linking_symbol)

def _explanation(self, stream: stream.Stream, attributes_repr: str) -> str:
explanation = self.header

if self.header:
explanation += "\n"
self.header = ""

name = stream.__class__.__name__
if self.colored:
name = util.colorize_in_red(name)

stream_repr = f"{name}({attributes_repr})"

explanation += self.linking_symbol + stream_repr + "\n"
explanation = self.linking_symbol + stream_repr + "\n"

if stream.upstream is not None:
explanation += textwrap.indent(
Expand Down Expand Up @@ -105,9 +85,7 @@ def visit_amap_stream(self, stream: AMapStream) -> str:
return self.visit_map_stream(cast(MapStream, stream))

def visit_observe_stream(self, stream: ObserveStream) -> str:
return self._explanation(
stream, f"what='{stream.what}', colored={stream.colored}"
)
return self._explanation(stream, f"what='{stream.what}'")

def visit_slow_stream(self, stream: SlowStream) -> str:
return self._explanation(stream, f"frequency={stream.frequency}")
1 change: 0 additions & 1 deletion streamable/visitors/iterator.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ def visit_observe_stream(self, stream: ObserveStream[T]) -> Iterator[T]:
return functions.observe(
stream.upstream.accept(self),
stream.what,
stream.colored,
)

def visit_slow_stream(self, stream: SlowStream[T]) -> Iterator[T]:
Expand Down
1 change: 0 additions & 1 deletion tests/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,5 @@ def test_signatures(self) -> None:
iterator, lambda ex: None, raise_after_exhaustion=True
)
observed_it_1: Iterator[int] = observe(iterator, what="objects")
observed_it_2: Iterator[int] = observe(iterator, what="objects", colored=True)
slowed_it_1: Iterator[int] = slow(iterator, frequency=1)
truncated_it_1: Iterator[int] = truncate(iterator, count=1)
15 changes: 5 additions & 10 deletions tests/test_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,20 +198,15 @@ class CustomCallable:
explanation_2,
msg="Stream.explain() must be deterministic.",
)
colored_explanation = complex_stream.explanation(colored=True)
self.assertNotEqual(
explanation_1,
colored_explanation,
msg="Stream.explain(colored=True) must different from non colored one.",
)
explanation_3 = complex_stream.map(str).explanation()

explanation_2 = complex_stream.map(str).explanation()
self.assertNotEqual(
explanation_1,
explanation_3,
explanation_2,
msg="explanation of different streams must be different",
)

print(colored_explanation)
print(explanation_1)

def test_explain(self) -> None:
stream = Stream(src)
Expand Down Expand Up @@ -944,7 +939,7 @@ def test_observe(self) -> None:
.slow(1)
.observe("chars")
.map(int)
.observe("ints", colored=True)
.observe("ints")
.group(2)
.observe("int pairs")
)
Expand Down
2 changes: 1 addition & 1 deletion version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.13.0"
__version__ = "0.13.8"

0 comments on commit 4fc0fe6

Please sign in to comment.