Skip to content
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
2 changes: 1 addition & 1 deletion .bumpversion.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.bumpversion]
allow_dirty = true
current_version = "0.183.5"
current_version = "0.184.0"

[[tool.bumpversion.files]]
filename = "pyproject.toml"
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/dycw/actions
rev: 0.15.5
rev: 0.15.8
hooks:
- args:
- --ci--pull-request--pyright
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
jupyter-test = ["pandas>=2.3.3", "polars>=1.37.1"]
libcst = ["libcst>=1.8.6"]
lightweight-charts = ["lightweight-charts>=2.1"]
lightweight-charts-test = ["polars>=1.37.1", "pyarrow>=22.0.0"]
lightweight-charts-test = ["polars>=1.37.1", "pyarrow>=23.0.0"]
math-test = ["numpy>=2.4.1"]
memory-profiler = ["memory-profiler>=0.61.0"]
more-itertools = ["more-itertools>=10.8.0"]
Expand Down Expand Up @@ -116,7 +116,7 @@
name = "dycw-utilities"
readme = "README.md"
requires-python = ">= 3.12"
version = "0.183.5"
version = "0.184.0"

[project.entry-points.pytest11]
pytest-randomly = "utilities.pytest_plugins.pytest_randomly"
Expand Down
22 changes: 17 additions & 5 deletions src/tests/test_hypothesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@
uint32s,
uint64s,
urls,
versions,
version2s,
version3s,
year_months,
zone_infos,
zoned_date_time_periods,
Expand All @@ -127,7 +128,7 @@
from utilities.iterables import one
from utilities.libcst import parse_import
from utilities.platform import maybe_lower_case
from utilities.version import Version
from utilities.version import Version2, Version3
from utilities.whenever import (
DATE_TWO_DIGIT_YEAR_MAX,
DATE_TWO_DIGIT_YEAR_MIN,
Expand Down Expand Up @@ -1223,11 +1224,22 @@ def test_main(
assert url.database is not None


class TestVersions:
class TestVersion2s:
@given(data=data(), suffix=booleans())
def test_main(self, *, data: DataObject, suffix: bool) -> None:
version = data.draw(versions(suffix=suffix))
assert isinstance(version, Version)
version = data.draw(version2s(suffix=suffix))
assert isinstance(version, Version2)
if suffix:
assert version.suffix is not None
else:
assert version.suffix is None


class TestVersion3s:
@given(data=data(), suffix=booleans())
def test_main(self, *, data: DataObject, suffix: bool) -> None:
version = data.draw(version3s(suffix=suffix))
assert isinstance(version, Version3)
if suffix:
assert version.suffix is not None
else:
Expand Down
6 changes: 4 additions & 2 deletions src/tests/test_objects/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
time_deltas,
time_periods,
times,
versions,
version2s,
version3s,
year_months,
zoned_date_time_periods,
zoned_date_times,
Expand Down Expand Up @@ -101,7 +102,8 @@ def objects(
| times()
| hypothesis.strategies.times()
| uuids()
| versions()
| version2s()
| version3s()
| year_months()
| zoned_date_time_periods()
| zoned_date_times()
Expand Down
30 changes: 22 additions & 8 deletions src/tests/test_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
text_ascii,
time_deltas,
times,
versions,
version2s,
version3s,
year_months,
zoned_date_times,
)
Expand All @@ -70,7 +71,7 @@
)
from utilities.text import parse_bool
from utilities.types import Number
from utilities.version import Version
from utilities.version import Version2, Version3


class TestSerializeAndParseObject:
Expand Down Expand Up @@ -312,10 +313,16 @@ def parser(text: str, /) -> DataClassFutureIntEvenOrOddUnion:
raise ImpossibleCaseError(case=[f"{int_=}"])
assert result == expected

@given(version=versions())
def test_version(self, *, version: Version) -> None:
@given(version=version2s())
def test_version2(self, *, version: Version2) -> None:
serialized = serialize_object(version)
result = parse_object(Version, serialized)
result = parse_object(Version2, serialized)
assert result == version

@given(version=version3s())
def test_version3(self, *, version: Version3) -> None:
serialized = serialize_object(version)
result = parse_object(Version3, serialized)
assert result == version

@given(year_month=year_months())
Expand Down Expand Up @@ -631,12 +638,19 @@ def test_error_union_not_implemented(self) -> None:
):
_ = parse_object(DataClassFutureIntEvenOrOddUnion, "invalid")

def test_error_version(self) -> None:
def test_error_version2(self) -> None:
with raises(
_ParseObjectParseError,
match=r"Unable to parse <class 'utilities\.version\.Version2'>; got 'invalid'",
):
_ = parse_object(Version2, "invalid")

def test_error_version3(self) -> None:
with raises(
_ParseObjectParseError,
match=r"Unable to parse <class 'utilities\.version\.Version'>; got 'invalid'",
match=r"Unable to parse <class 'utilities\.version\.Version3'>; got 'invalid'",
):
_ = parse_object(Version, "invalid")
_ = parse_object(Version3, "invalid")

def test_error_year_month(self) -> None:
with raises(
Expand Down
2 changes: 1 addition & 1 deletion src/tests/test_polars.py
Original file line number Diff line number Diff line change
Expand Up @@ -2297,7 +2297,7 @@ class TestNormalPDF:
@given(
xs=lists(float64s(), max_size=10),
loc=float64s(),
scale=float64s(min_value=0.0, exclude_min=True),
scale=float64s(min_value=1e-8),
)
def test_main(self, *, xs: list[float], loc: float, scale: float) -> None:
x = Series(name="x", values=xs, dtype=Float64)
Expand Down
115 changes: 57 additions & 58 deletions src/tests/test_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,138 +7,137 @@
from hypothesis.strategies import booleans, integers, none
from pytest import raises

from utilities.hypothesis import sentinels, text_ascii, versions
from utilities.hypothesis import sentinels, text_ascii, version3s
from utilities.version import (
ParseVersionError,
Version,
_VersionEmptySuffixError,
_VersionNegativeMajorVersionError,
_VersionNegativeMinorVersionError,
_VersionNegativePatchVersionError,
_VersionZeroError,
parse_version,
to_version,
Version3,
_Version3EmptySuffixError,
_Version3NegativeMajorVersionError,
_Version3NegativeMinorVersionError,
_Version3NegativePatchVersionError,
_Version3ParseError,
_Version3ZeroError,
to_version3,
)

if TYPE_CHECKING:
from utilities.constants import Sentinel


class TestParseVersion:
@given(version=versions())
def test_main(self, *, version: Version) -> None:
parsed = parse_version(str(version))
assert parsed == version

def test_error(self) -> None:
with raises(ParseVersionError, match=r"Invalid version string: 'invalid'"):
_ = parse_version("invalid")


class TestVersion:
@given(version=versions())
def test_hashable(self, *, version: Version) -> None:
@given(version=version3s())
def test_hashable(self, *, version: Version3) -> None:
_ = hash(version)

@given(version1=versions(), version2=versions())
def test_orderable(self, *, version1: Version, version2: Version) -> None:
@given(version1=version3s(), version2=version3s())
def test_orderable(self, *, version1: Version3, version2: Version3) -> None:
assert (version1 <= version2) or (version1 >= version2)

@given(version=versions(suffix=booleans()))
def test_repr(self, *, version: Version) -> None:
@given(version=version3s())
def test_parse(self, *, version: Version3) -> None:
parsed = Version3.parse(str(version))
assert parsed == version

@given(version=version3s(suffix=booleans()))
def test_repr(self, *, version: Version3) -> None:
result = repr(version)
assert search(r"^\d+\.\d+\.\d+", result)

@given(version=versions())
def test_bump_major(self, *, version: Version) -> None:
@given(version=version3s())
def test_bump_major(self, *, version: Version3) -> None:
bumped = version.bump_major()
assert version < bumped
assert bumped.major == version.major + 1
assert bumped.minor == 0
assert bumped.patch == 0
assert bumped.suffix is None

@given(version=versions())
def test_bump_minor(self, *, version: Version) -> None:
@given(version=version3s())
def test_bump_minor(self, *, version: Version3) -> None:
bumped = version.bump_minor()
assert version < bumped
assert bumped.major == version.major
assert bumped.minor == version.minor + 1
assert bumped.patch == 0
assert bumped.suffix is None

@given(version=versions())
def test_bump_patch(self, *, version: Version) -> None:
@given(version=version3s())
def test_bump_patch(self, *, version: Version3) -> None:
bumped = version.bump_patch()
assert version < bumped
assert bumped.major == version.major
assert bumped.minor == version.minor
assert bumped.patch == version.patch + 1
assert bumped.suffix is None

@given(version=versions(), suffix=text_ascii(min_size=1) | none())
def test_with_suffix(self, *, version: Version, suffix: str | None) -> None:
@given(version=version3s(), suffix=text_ascii(min_size=1) | none())
def test_with_suffix(self, *, version: Version3, suffix: str | None) -> None:
new = version.with_suffix(suffix=suffix)
assert new.major == version.major
assert new.minor == version.minor
assert new.patch == version.patch
assert new.suffix == suffix

@given(version=versions())
def test_error_order(self, *, version: Version) -> None:
@given(version=version3s())
def test_error_order(self, *, version: Version3) -> None:
with raises(TypeError):
_ = version <= None

def test_error_zero(self) -> None:
with raises(
_VersionZeroError, match=r"Version must be greater than zero; got 0\.0\.0"
_Version3ZeroError, match=r"Version must be greater than zero; got 0\.0\.0"
):
_ = Version(0, 0, 0)
_ = Version3(0, 0, 0)

@given(major=integers(max_value=-1))
def test_error_negative_major_version(self, *, major: int) -> None:
with raises(
_VersionNegativeMajorVersionError,
_Version3NegativeMajorVersionError,
match=r"Major version must be non-negative; got .*",
):
_ = Version(major=major)
_ = Version3(major=major)

@given(minor=integers(max_value=-1))
def test_error_negative_minor_version(self, *, minor: int) -> None:
with raises(
_VersionNegativeMinorVersionError,
_Version3NegativeMinorVersionError,
match=r"Minor version must be non-negative; got .*",
):
_ = Version(minor=minor)
_ = Version3(minor=minor)

@given(patch=integers(max_value=-1))
def test_error_negative_patch_version(self, *, patch: int) -> None:
with raises(
_VersionNegativePatchVersionError,
_Version3NegativePatchVersionError,
match=r"Patch version must be non-negative; got .*",
):
_ = Version(patch=patch)
_ = Version3(patch=patch)

def test_error_empty_suffix(self) -> None:
with raises(
_VersionEmptySuffixError, match=r"Suffix must be non-empty; got .*"
_Version3EmptySuffixError, match=r"Suffix must be non-empty; got .*"
):
_ = Version3(suffix="")

def test_error_parse(self) -> None:
with raises(
_Version3ParseError, match=r"Unable to parse version; got 'invalid'"
):
_ = Version(suffix="")
_ = Version3.parse("invalid")


class TestGetVersion:
@given(version=versions())
def test_version(self, *, version: Version) -> None:
assert to_version(version) == version
class TestToVersion3:
@given(version=version3s())
def test_version(self, *, version: Version3) -> None:
assert to_version3(version) == version

@given(version=versions())
def test_str(self, *, version: Version) -> None:
assert to_version(str(version)) == version
@given(version=version3s())
def test_str(self, *, version: Version3) -> None:
assert to_version3(str(version)) == version

@given(version=none() | sentinels())
def test_none_or_sentinel(self, *, version: None | Sentinel) -> None:
assert to_version(version) is version
assert to_version3(version) is version

@given(version=versions())
def test_callable(self, *, version: Version) -> None:
assert to_version(lambda: version) == version
@given(version=version3s())
def test_callable(self, *, version: Version3) -> None:
assert to_version3(lambda: version) == version
2 changes: 1 addition & 1 deletion src/utilities/__init__.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading