Skip to content

Commit

Permalink
remove external inf dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
stringertheory committed Aug 6, 2024
1 parent fd3a709 commit 4a5db62
Show file tree
Hide file tree
Showing 11 changed files with 237 additions and 37 deletions.
1 change: 1 addition & 0 deletions docs-md/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# boodle doodle
5 changes: 5 additions & 0 deletions docs-md/modules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
::: traces.timeseries

::: traces.timeseries.TimeSeries
:docstring:
:members:
3 changes: 3 additions & 0 deletions docs-md/stylesheets/extra.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:root > * {
--md-mermaid-label-bg-color: rgba(255, 255, 255, 0.9);
}
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
site_name: traces
docs_dir: ./docs-md
repo_url: https://github.com/stringertheory/traces
site_url: https://stringertheory.github.io/traces
site_description: A Python library for unevenly-spaced time series analysis
Expand Down Expand Up @@ -48,6 +49,7 @@ extra:
link: https://pypi.org/project/traces

markdown_extensions:
- mkautodoc
- toc:
permalink: true
- pymdownx.arithmatex:
Expand Down
28 changes: 14 additions & 14 deletions poetry.lock

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

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ packages = [

[tool.poetry.dependencies]
python = ">=3.8,<4.0"
infinity = "^1.5"
sortedcontainers = "^2.4.0"

[tool.poetry.group.dev.dependencies]
Expand Down Expand Up @@ -46,6 +45,7 @@ bump-my-version = "^0.17.3"
notebook = "^7.0.7"
deptry = "^0.12.0"
python-dateutil = "^2.8.2"
mkautodoc = "^0.2.0"

[tool.poetry.group.docs.dependencies]
mkdocs = "^1.4.2"
Expand Down
2 changes: 1 addition & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from datetime import date, datetime, timedelta

import pytest
from infinity import inf

import traces.utils as utils
from traces.infinity import inf

timedelta_list = [
timedelta(hours=1),
Expand Down
3 changes: 1 addition & 2 deletions traces/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from infinity import inf

from . import decorators, operations
from .eventseries import EventSeries
from .histogram import Histogram
from .infinity import inf
from .timeseries import TimeSeries
from .utils import datetime_range

Expand Down
154 changes: 154 additions & 0 deletions traces/infinity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
"""This module is derived from the `infinity` package (at
https://pypi.org/project/infinity/ or
https://github.com/kvesteri/infinity), which is licensed under the BSD
3-Clause "New" or "Revised" License:
Copyright (c) 2014, Konsta Vesterinen
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

from functools import total_ordering


@total_ordering
class Infinity:
def __init__(self, positive=True):
self.positive = positive

def __neg__(self):
return Infinity(not self.positive)

def __gt__(self, other):
if self == other:
return False
return self.positive

def __eq__(self, other):
return (
(
isinstance(other, self.__class__)
and other.positive == self.positive
)
or (self.positive and other == float("inf"))
or (not self.positive and other == float("-inf"))
)

def __ne__(self, other):
return not (self == other)

def __bool__(self):
return True

def __nonzero__(self):
return True

def __str__(self):
return "%sinf" % ("" if self.positive else "-")

def __float__(self):
return float(str(self))

def __add__(self, other):
if is_infinite(other) and other != self:
return NotImplemented
return self

def __radd__(self, other):
return self

def __sub__(self, other):
if is_infinite(other) and other == self:
return NotImplemented
return self

def __rsub__(self, other):
return self

def timetuple(self):
return ()

def __abs__(self):
return self.__class__()

def __pos__(self):
return self

def __div__(self, other):
if is_infinite(other):
return NotImplemented

return Infinity(
other > 0 and self.positive or other < 0 and not self.positive
)

def __rdiv__(self, other):
return 0

def __repr__(self):
return str(self)

__truediv__ = __div__
__rtruediv__ = __rdiv__
__floordiv__ = __div__
__rfloordiv__ = __rdiv__

def __mul__(self, other):
if other == 0:
return NotImplemented
return Infinity(
other > 0 and self.positive or other < 0 and not self.positive
)

__rmul__ = __mul__

def __pow__(self, other):
if other == 0:
return NotImplemented
elif other == -self:
return -0.0 if not self.positive else 0.0
else:
return Infinity()

def __rpow__(self, other):
if other in (1, -1):
return NotImplemented
elif other == -self:
return -0.0 if not self.positive else 0.0
else:
return Infinity()

def __hash__(self):
return (self.__class__, self.positive).__hash__()


inf = Infinity()


def is_infinite(value):
return value == inf or value == -inf
72 changes: 54 additions & 18 deletions traces/timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@
import itertools
from queue import PriorityQueue

from infinity import inf
from sortedcontainers import SortedDict

from . import histogram, operations, plot, utils
from . import histogram, infinity, operations, plot, utils

NotGiven = object()

Expand Down Expand Up @@ -164,9 +163,36 @@ def set(self, time, value, compact=False):
self._d[time] = value

def set_interval(self, start, end, value, compact=False):
"""Set the value for the time series on an interval. If compact is
True, only set the value if it's different from what it would
be anyway.
"""Sets the value for the time series within a specified time
interval.
Args:
start: The start time of the interval, inclusive
end: The end time of the interval, exclusive.
value: The value to set within the interval.
compact (optional): If compact is True, only set the value
if it's different from what it would be anyway. Defaults
to False.
Raises:
ValueError: If the start time is equal or after the end
time, indicating an invalid interval.
Example:
>>> ts = TimeSeries(data=[(1, 5), (3, 2), (5, 4), (6, 1)])
>>> ts.set_interval(2, 6, 3)
>>> ts
TimeSeries({1: 5, 2: 3, 6: 1})
Note:
The method sets the value over the interval by removing
measurements points from the time series between start and
end (exclusive), rather than changing the value of any
intermediate points to equal the value.
"""
if start >= end:
Expand All @@ -183,13 +209,23 @@ def set_interval(self, start, end, value, compact=False):
self.set(end, end_value, compact)

def compact(self):
"""Convert this instance to a compact version: the value will be the
same at all times, but repeated measurements are discarded.
"""Convert this instance to a "compact" version: the value
will be the same at all times, but repeated measurements are
discarded.
"""
Compacting the time series can significantly reduce the length
and memory usage for data with many repeated values.
No arguments are required for this method, and it modifies the
time series in place.
# todo: change to to_compact, do not modify in place. mark as deprecated
Example:
>>> ts = TimeSeries(data=[(1, 5), (2, 5), (5, 5), (6, 1)])
>>> ts.compact()
>>> ts
TimeSeries({1: 5, 6: 1})
"""
previous_value = object()
redundant = []
for time, value in self:
Expand Down Expand Up @@ -255,10 +291,8 @@ def __repr__(self):
def format_item(item):
return "{!r}: {!r}".format(*item)

return "{name}({{{items}}})".format(
name=type(self).__name__,
items=", ".join(format_item(_) for _ in self._d.items()),
)
items = dict(self._d.items())
return f"{type(self).__name__}(default={self.default!r}, {items!r})"

def __str__(self):
"""A human-readable string representation (truncated if it gets too
Expand All @@ -284,7 +318,9 @@ def format_item(item):
else:
items = ", ".join(format_item(_) for _ in self._d.items())

return f"{type(self).__name__}({{{items}}})"
return f"{type(self).__name__}(default={self.default!r}, {{{items}}})"

# return f"{type(self).__name__}({{{items}}})"

def iterintervals(self, n=2):
"""Iterate over groups of `n` consecutive measurement points in the
Expand Down Expand Up @@ -781,8 +817,8 @@ def distribution(

def n_points(
self,
start=-inf,
end=+inf,
start=-infinity.inf,
end=+infinity.inf,
mask=None,
include_start=True,
include_end=False,
Expand Down Expand Up @@ -1165,10 +1201,10 @@ def __ne__(self, other):

def _check_boundary(self, value, allow_infinite, lower_or_upper):
if lower_or_upper == "lower":
infinity_value = -inf
infinity_value = -infinity.inf
method_name = "first_key"
elif lower_or_upper == "upper":
infinity_value = inf
infinity_value = infinity.inf
method_name = "last_key"
else:
msg = (
Expand Down
Loading

0 comments on commit 4a5db62

Please sign in to comment.