-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #64 from alphatwirl/dev
Support Python 3.9
- Loading branch information
Showing
9 changed files
with
201 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
from __future__ import annotations | ||
|
||
import atexit | ||
import contextlib | ||
import multiprocessing | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ name = "atpbar" | |
dynamic = ["version"] | ||
description = "Progress bars for threading and multiprocessing tasks" | ||
readme = "README.md" | ||
requires-python = ">=3.10" | ||
requires-python = ">=3.9" | ||
license = "" | ||
authors = [{ name = "Tai Sakuma", email = "[email protected]" }] | ||
classifiers = [ | ||
|
@@ -16,11 +16,14 @@ classifiers = [ | |
"Intended Audience :: End Users/Desktop", | ||
"License :: OSI Approved :: BSD License", | ||
"Programming Language :: Python", | ||
"Programming Language :: Python :: 3.9", | ||
"Programming Language :: Python :: 3.10", | ||
"Programming Language :: Python :: 3.11", | ||
"Programming Language :: Python :: 3.12", | ||
] | ||
|
||
dependencies = [ | ||
"typing_extensions>=4.12; python_version < '3.10'", | ||
] | ||
[project.optional-dependencies] | ||
jupyter = ["ipywidgets>=8.1"] | ||
tests = [ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,16 @@ | ||
import os | ||
import sys | ||
from pathlib import Path | ||
|
||
import pytest | ||
from hypothesis import settings | ||
|
||
if os.getenv('GITHUB_ACTIONS') == 'true': | ||
settings.register_profile('ci', deadline=None) | ||
settings.load_profile('ci') | ||
|
||
|
||
def pytest_ignore_collect(collection_path: Path, config: pytest.Config) -> bool: | ||
if collection_path.name == 'test_state.py' and sys.version_info < (3, 10): | ||
return True | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import sys | ||
from pathlib import Path | ||
|
||
import pytest | ||
|
||
|
||
def pytest_ignore_collect(collection_path: Path, config: pytest.Config) -> bool: | ||
if collection_path.name == 'test_print.py' and sys.version_info < (3, 10): | ||
return True | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
import sys | ||
from unittest.mock import MagicMock, Mock, call | ||
|
||
import pytest | ||
from hypothesis import given, settings | ||
from hypothesis import strategies as st | ||
|
||
from atpbar.machine import ( | ||
Active, | ||
Callback, | ||
Disabled, | ||
Initial, | ||
ProgressReporter, | ||
Registered, | ||
State, | ||
Yielded, | ||
) | ||
|
||
pytestmark = pytest.mark.skipif(sys.version_info >= (3, 10), reason='for Python 3.9') | ||
|
||
|
||
class StatefulTest: | ||
def __init__(self) -> None: | ||
self.callback = MagicMock(spec=Callback) | ||
self.reporter = Mock(spec=ProgressReporter) | ||
self.callback.reporter = self.reporter | ||
self.state: State = Initial(callback=self.callback) | ||
|
||
def prepare_reporter(self) -> None: | ||
prev = self.state | ||
self.callback.reset_mock() | ||
self.state = prev.prepare_reporter() | ||
if isinstance(prev, Initial): | ||
assert isinstance(self.state, Active) | ||
assert self.callback.mock_calls == [call.on_active()] | ||
else: | ||
assert self.state is prev | ||
assert self.callback.mock_calls == [] | ||
|
||
def register_reporter(self) -> None: | ||
prev = self.state | ||
self.callback.reset_mock() | ||
reporter = Mock(spec=ProgressReporter) | ||
self.state = prev.register_reporter(reporter) | ||
assert isinstance(self.state, Registered) | ||
assert self.callback.mock_calls == [call.on_registered(reporter)] | ||
|
||
def disable(self) -> None: | ||
prev = self.state | ||
self.callback.reset_mock() | ||
self.state = prev.disable() | ||
assert isinstance(self.state, Disabled) | ||
assert self.callback.mock_calls == [call.on_disabled()] | ||
|
||
def fetch_reporter(self) -> None: | ||
prev = self.state | ||
self.callback.reset_mock() | ||
|
||
with prev.fetch_reporter() as reporter: | ||
if isinstance(prev, Active): | ||
assert self.callback.mock_calls == [ | ||
call.fetch_reporter_in_active(), | ||
call.fetch_reporter_in_active().__enter__(), | ||
] | ||
assert ( | ||
reporter | ||
is self.callback.fetch_reporter_in_active.return_value.__enter__.return_value | ||
) | ||
elif isinstance(prev, Yielded): | ||
assert self.callback.mock_calls == [ | ||
call.fetch_reporter_in_yielded(), | ||
call.fetch_reporter_in_yielded().__enter__(), | ||
] | ||
assert ( | ||
reporter | ||
is self.callback.fetch_reporter_in_yielded.return_value.__enter__.return_value | ||
) | ||
elif isinstance(prev, Registered): | ||
assert self.callback.mock_calls == [ | ||
call.fetch_reporter_in_registered(), | ||
call.fetch_reporter_in_registered().__enter__(), | ||
] | ||
assert ( | ||
reporter | ||
is self.callback.fetch_reporter_in_registered.return_value.__enter__.return_value | ||
) | ||
elif isinstance(prev, Disabled): | ||
assert self.callback.mock_calls == [ | ||
call.fetch_reporter_in_disabled(), | ||
call.fetch_reporter_in_disabled().__enter__(), | ||
] | ||
assert ( | ||
reporter | ||
is self.callback.fetch_reporter_in_disabled.return_value.__enter__.return_value | ||
) | ||
else: | ||
assert self.callback.mock_calls == [] | ||
assert reporter is self.reporter | ||
|
||
def on_yielded(self) -> None: | ||
prev = self.state | ||
self.callback.reset_mock() | ||
self.state = prev.on_yielded() | ||
if isinstance(prev, Active): | ||
assert isinstance(self.state, Yielded) | ||
else: | ||
assert self.state is prev | ||
assert self.callback.mock_calls == [] | ||
|
||
def on_resumed(self) -> None: | ||
prev = self.state | ||
self.callback.reset_mock() | ||
self.state = prev.on_resumed() | ||
if isinstance(prev, Yielded): | ||
assert isinstance(self.state, Active) | ||
assert self.state is prev._active | ||
else: | ||
assert self.state is prev | ||
assert self.callback.mock_calls == [] | ||
|
||
def flush(self) -> None: | ||
prev = self.state | ||
self.callback.reset_mock() | ||
self.state = prev.flush() | ||
if isinstance(prev, Initial): | ||
assert isinstance(self.state, Active) | ||
assert self.callback.mock_calls == [call.on_active()] | ||
elif isinstance(prev, Active): | ||
assert self.state is prev | ||
assert self.callback.mock_calls == [call.flush_in_active()] | ||
else: | ||
assert self.state is prev | ||
assert self.callback.mock_calls == [] | ||
|
||
def shutdown(self) -> None: | ||
prev = self.state | ||
self.callback.reset_mock() | ||
self.state = prev.shutdown() | ||
assert isinstance(self.state, Initial) | ||
if isinstance(prev, Active): | ||
assert self.callback.mock_calls == [call.shutdown_in_active()] | ||
else: | ||
assert self.callback.mock_calls == [] | ||
|
||
|
||
@settings(max_examples=500) | ||
@given(data=st.data()) | ||
def test_state(data: st.DataObject) -> None: | ||
test = StatefulTest() | ||
|
||
METHODS = [ | ||
test.prepare_reporter, | ||
test.register_reporter, | ||
test.disable, | ||
test.fetch_reporter, | ||
test.on_yielded, | ||
test.on_resumed, | ||
test.flush, | ||
test.shutdown, | ||
] | ||
|
||
methods = data.draw(st.lists(st.sampled_from(METHODS))) | ||
|
||
for method in methods: | ||
method() |