time-split 0.5.0__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {time_split-0.5.0 → time_split-0.7.0}/PKG-INFO +30 -23
- {time_split-0.5.0 → time_split-0.7.0}/README.md +11 -8
- {time_split-0.5.0 → time_split-0.7.0}/pyproject.toml +56 -61
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/__init__.py +2 -2
- time_split-0.7.0/src/time_split/__main__.py +9 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_backend/_limits.py +15 -7
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_backend/_schedule.py +2 -2
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_backend/_splitter.py +1 -23
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_docstrings.py +2 -9
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_frontend/_plot.py +15 -5
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_frontend/_progress.py +2 -3
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_frontend/_to_string.py +64 -26
- time_split-0.7.0/src/time_split/app/__init__.py +11 -0
- {time_split-0.5.0/src/time_split/support → time_split-0.7.0/src/time_split/app}/_create_explorer_link.py +16 -10
- time_split-0.7.0/src/time_split/cli.py +29 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/settings.py +30 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/support/__init__.py +3 -5
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/types.py +3 -1
- time_split-0.5.0/src/time_split/_compat.py +0 -49
- time_split-0.5.0/src/time_split/streamlit/README.md +0 -82
- time_split-0.5.0/src/time_split/streamlit/__init__.py +0 -1
- time_split-0.5.0/src/time_split/streamlit/_logging.py +0 -75
- time_split-0.5.0/src/time_split/streamlit/_support.py +0 -67
- time_split-0.5.0/src/time_split/streamlit/_views.py +0 -125
- time_split-0.5.0/src/time_split/streamlit/config.py +0 -68
- time_split-0.5.0/src/time_split/streamlit/widgets/__init__.py +0 -1
- time_split-0.5.0/src/time_split/streamlit/widgets/data/__init__.py +0 -7
- time_split-0.5.0/src/time_split/streamlit/widgets/data/_data.py +0 -336
- time_split-0.5.0/src/time_split/streamlit/widgets/data/_datasets.py +0 -123
- time_split-0.5.0/src/time_split/streamlit/widgets/data/_sample_data.py +0 -147
- time_split-0.5.0/src/time_split/streamlit/widgets/data/load.py +0 -111
- time_split-0.5.0/src/time_split/streamlit/widgets/data/sample.csv +0 -397
- time_split-0.5.0/src/time_split/streamlit/widgets/display/__init__.py +0 -15
- time_split-0.5.0/src/time_split/streamlit/widgets/display/_aggregate.py +0 -227
- time_split-0.5.0/src/time_split/streamlit/widgets/display/_code.py +0 -175
- time_split-0.5.0/src/time_split/streamlit/widgets/display/_overview.py +0 -51
- time_split-0.5.0/src/time_split/streamlit/widgets/display/_performance.py +0 -176
- time_split-0.5.0/src/time_split/streamlit/widgets/display/_plot_folds.py +0 -92
- time_split-0.5.0/src/time_split/streamlit/widgets/parameters/__init__.py +0 -21
- time_split-0.5.0/src/time_split/streamlit/widgets/parameters/_datetime.py +0 -30
- time_split-0.5.0/src/time_split/streamlit/widgets/parameters/_duration.py +0 -78
- time_split-0.5.0/src/time_split/streamlit/widgets/parameters/_expand_limits.py +0 -141
- time_split-0.5.0/src/time_split/streamlit/widgets/parameters/_schedule.py +0 -135
- time_split-0.5.0/src/time_split/streamlit/widgets/parameters/_schedule_filter.py +0 -43
- time_split-0.5.0/src/time_split/streamlit/widgets/parameters/_span.py +0 -122
- time_split-0.5.0/src/time_split/streamlit/widgets/parameters/_splitter_kwargs.py +0 -29
- time_split-0.5.0/src/time_split/streamlit/widgets/ruff.toml +0 -6
- time_split-0.5.0/src/time_split/streamlit/widgets/types.py +0 -351
- {time_split-0.5.0 → time_split-0.7.0}/LICENSE.md +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_backend/__init__.py +1 -1
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_backend/_datetime_index_like.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_backend/_process_available.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_backend/_span.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_frontend/__init__.py +2 -2
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_frontend/_split.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_frontend/_weight.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/_support.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/integration/__init__.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/integration/_log_progress.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/integration/base.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/integration/pandas/__init__.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/integration/pandas/_impl.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/integration/polars/__init__.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/integration/polars/_impl.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/integration/sklearn/__init__.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/integration/sklearn/_impl.py +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/py.typed +0 -0
- {time_split-0.5.0 → time_split-0.7.0}/src/time_split/support/types.py +0 -0
|
@@ -1,34 +1,38 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: time-split
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Time-based k-fold validation splits for heterogeneous data.
|
|
5
|
-
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: hyper,parameter,optimization,cross,validation,time,temporal,heterogenous,data
|
|
6
7
|
Author: Richard Sundqvist
|
|
7
8
|
Author-email: richard.sundqvist@live.se
|
|
8
9
|
Requires-Python: >=3.11
|
|
9
|
-
Classifier: Development Status ::
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
11
|
Classifier: Intended Audience :: Developers
|
|
11
12
|
Classifier: Intended Audience :: Science/Research
|
|
12
|
-
Classifier:
|
|
13
|
-
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
14
|
Classifier: Operating System :: MacOS
|
|
15
15
|
Classifier: Operating System :: Microsoft :: Windows
|
|
16
|
-
Classifier:
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Natural Language :: English
|
|
18
|
+
Classifier: Typing :: Typed
|
|
17
19
|
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
-
Classifier: Programming Language :: Python :: 3
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Provides-Extra: app
|
|
21
25
|
Provides-Extra: plotting
|
|
22
|
-
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist: matplotlib ; extra == "plotting" or extra == "streamlit"
|
|
26
|
+
Requires-Dist: click ; extra == "app"
|
|
27
|
+
Requires-Dist: matplotlib ; extra == "plotting"
|
|
25
28
|
Requires-Dist: pandas (>=2.0.3)
|
|
26
|
-
Requires-Dist: rics (>=
|
|
27
|
-
Requires-Dist: seaborn ; extra == "plotting"
|
|
28
|
-
Requires-Dist:
|
|
29
|
+
Requires-Dist: rics (>=6.0.1)
|
|
30
|
+
Requires-Dist: seaborn ; extra == "plotting"
|
|
31
|
+
Requires-Dist: time-split-app ; extra == "app"
|
|
29
32
|
Project-URL: Bug Tracker, https://github.com/rsundqvist/time-split/issues
|
|
30
33
|
Project-URL: Changelog, https://github.com/rsundqvist/time-split/blob/master/CHANGELOG.md
|
|
31
|
-
Project-URL: Documentation, https://time-split
|
|
34
|
+
Project-URL: Documentation, https://time-split
|
|
35
|
+
Project-URL: Homepage, https://github.com/rsundqvist/time-split
|
|
32
36
|
Project-URL: Repository, https://github.com/rsundqvist/time-split
|
|
33
37
|
Description-Content-Type: text/markdown
|
|
34
38
|
|
|
@@ -64,26 +68,29 @@ strong non-stationary characteristics.
|
|
|
64
68
|
schedule itself.
|
|
65
69
|
- Automatically extract and [normalize](https://time-split.readthedocs.io/en/stable/guide/expand_limits.html) data limits for
|
|
66
70
|
supported data types.
|
|
67
|
-
- [Plotting function](https://time-split.readthedocs.io/en/stable/
|
|
71
|
+
- [Plotting function](https://time-split.readthedocs.io/en/stable/api/time_split.html#time_split.plot) for
|
|
68
72
|
visualization of folds. Display fold sizes (hour/row count), or
|
|
69
73
|
[use custom text](https://time-split.readthedocs.io/en/stable/auto_examples/plotting_with_metrics.html).
|
|
70
|
-
- [Integrations](https://time-split.readthedocs.io/en/stable/
|
|
74
|
+
- [Integrations](https://time-split.readthedocs.io/en/stable/api/time_split.integration.html) for popular
|
|
71
75
|
libraries such as `pandas`, `polars` and `scikit-learn`.
|
|
72
76
|
- Convenient [web application](#experimenting-with-parameters) for exploring folds with different parameters.
|
|
73
77
|
|
|
74
78
|
## Experimenting with parameters
|
|
75
|
-
The **Time
|
|
76
|
-
(available [here](
|
|
79
|
+
The **Time Split** application
|
|
80
|
+
(available [here](https://time-split.streamlit.app/?data=1554942900-1557610200&schedule=0+0+%2A+%2A+MON%2CFRI&n_splits=2&step=2&show_removed=True))
|
|
77
81
|
is designed to help evaluate the effects of different
|
|
78
82
|
[parameters](https://time-split.readthedocs.io/en/stable/#parameter-overview).
|
|
79
|
-
To start it locally
|
|
80
|
-
[](https://hub.docker.com/r/rsundqvist/time-split/)
|
|
81
|
-
Docker, run
|
|
83
|
+
To start it locally, run
|
|
82
84
|
```sh
|
|
83
85
|
docker run -p 8501:8501 rsundqvist/time-split
|
|
84
86
|
```
|
|
87
|
+
or
|
|
88
|
+
```bash
|
|
89
|
+
pip install time-split[app]
|
|
90
|
+
python -m time_split app start
|
|
91
|
+
```
|
|
85
92
|
in the terminal. You may use
|
|
86
|
-
[`create_explorer_link()`](https://time-split.readthedocs.io/en/stable/
|
|
93
|
+
[`create_explorer_link()`](https://time-split.readthedocs.io/en/stable/api/time_split.app.html#time_split.app.create_explorer_link)
|
|
87
94
|
to build application URLs with preselected splitting parameters.
|
|
88
95
|
|
|
89
96
|
## Installation
|
|
@@ -30,26 +30,29 @@ strong non-stationary characteristics.
|
|
|
30
30
|
schedule itself.
|
|
31
31
|
- Automatically extract and [normalize](https://time-split.readthedocs.io/en/stable/guide/expand_limits.html) data limits for
|
|
32
32
|
supported data types.
|
|
33
|
-
- [Plotting function](https://time-split.readthedocs.io/en/stable/
|
|
33
|
+
- [Plotting function](https://time-split.readthedocs.io/en/stable/api/time_split.html#time_split.plot) for
|
|
34
34
|
visualization of folds. Display fold sizes (hour/row count), or
|
|
35
35
|
[use custom text](https://time-split.readthedocs.io/en/stable/auto_examples/plotting_with_metrics.html).
|
|
36
|
-
- [Integrations](https://time-split.readthedocs.io/en/stable/
|
|
36
|
+
- [Integrations](https://time-split.readthedocs.io/en/stable/api/time_split.integration.html) for popular
|
|
37
37
|
libraries such as `pandas`, `polars` and `scikit-learn`.
|
|
38
38
|
- Convenient [web application](#experimenting-with-parameters) for exploring folds with different parameters.
|
|
39
39
|
|
|
40
40
|
## Experimenting with parameters
|
|
41
|
-
The **Time
|
|
42
|
-
(available [here](
|
|
41
|
+
The **Time Split** application
|
|
42
|
+
(available [here](https://time-split.streamlit.app/?data=1554942900-1557610200&schedule=0+0+%2A+%2A+MON%2CFRI&n_splits=2&step=2&show_removed=True))
|
|
43
43
|
is designed to help evaluate the effects of different
|
|
44
44
|
[parameters](https://time-split.readthedocs.io/en/stable/#parameter-overview).
|
|
45
|
-
To start it locally
|
|
46
|
-
[](https://hub.docker.com/r/rsundqvist/time-split/)
|
|
47
|
-
Docker, run
|
|
45
|
+
To start it locally, run
|
|
48
46
|
```sh
|
|
49
47
|
docker run -p 8501:8501 rsundqvist/time-split
|
|
50
48
|
```
|
|
49
|
+
or
|
|
50
|
+
```bash
|
|
51
|
+
pip install time-split[app]
|
|
52
|
+
python -m time_split app start
|
|
53
|
+
```
|
|
51
54
|
in the terminal. You may use
|
|
52
|
-
[`create_explorer_link()`](https://time-split.readthedocs.io/en/stable/
|
|
55
|
+
[`create_explorer_link()`](https://time-split.readthedocs.io/en/stable/api/time_split.app.html#time_split.app.create_explorer_link)
|
|
53
56
|
to build application URLs with preselected splitting parameters.
|
|
54
57
|
|
|
55
58
|
## Installation
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
[
|
|
1
|
+
[project]
|
|
2
2
|
name = "time-split"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.0"
|
|
4
4
|
description = "Time-based k-fold validation splits for heterogeneous data."
|
|
5
|
-
authors = [
|
|
6
|
-
|
|
5
|
+
authors = [
|
|
6
|
+
{ name = "Richard Sundqvist", email = "richard.sundqvist@live.se" },
|
|
7
|
+
]
|
|
8
|
+
license = { text = "MIT" }
|
|
7
9
|
readme = "README.md"
|
|
8
|
-
|
|
9
|
-
repository = "https://github.com/rsundqvist/time-split"
|
|
10
|
-
documentation = "https://time-split.readthedocs.io"
|
|
10
|
+
keywords = ["hyper", "parameter", "optimization", "cross", "validation", "time", "temporal", "heterogenous", "data"]
|
|
11
11
|
classifiers = [
|
|
12
|
-
"Development Status ::
|
|
12
|
+
"Development Status :: 4 - Beta",
|
|
13
13
|
"Intended Audience :: Developers",
|
|
14
14
|
"Intended Audience :: Science/Research",
|
|
15
15
|
"Operating System :: POSIX :: Linux",
|
|
@@ -17,55 +17,54 @@ classifiers = [
|
|
|
17
17
|
"Operating System :: Microsoft :: Windows",
|
|
18
18
|
"License :: OSI Approved :: MIT License",
|
|
19
19
|
"Natural Language :: English",
|
|
20
|
+
"Typing :: Typed",
|
|
20
21
|
"Programming Language :: Python :: 3",
|
|
21
22
|
"Programming Language :: Python :: 3 :: Only",
|
|
22
23
|
"Programming Language :: Python :: 3.11",
|
|
23
24
|
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
24
26
|
]
|
|
27
|
+
requires-python = ">=3.11"
|
|
25
28
|
|
|
29
|
+
dependencies = [
|
|
30
|
+
"pandas >= 2.0.3",
|
|
31
|
+
"rics >= 6.0.1",
|
|
32
|
+
]
|
|
26
33
|
|
|
27
|
-
[
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
app = ["click", "time-split-app"] # Constraints managed by app.
|
|
36
|
+
plotting = ["matplotlib", "seaborn"]
|
|
37
|
+
|
|
38
|
+
[project.urls]
|
|
39
|
+
homepage = "https://github.com/rsundqvist/time-split"
|
|
40
|
+
repository = "https://github.com/rsundqvist/time-split"
|
|
41
|
+
documentation = "https://time-split"
|
|
28
42
|
"Bug Tracker" = "https://github.com/rsundqvist/time-split/issues"
|
|
29
43
|
"Changelog" = "https://github.com/rsundqvist/time-split/blob/master/CHANGELOG.md"
|
|
30
44
|
|
|
31
|
-
[
|
|
45
|
+
[project.entry-points."rics.cli"]
|
|
46
|
+
time-split = "time_split.cli:main"
|
|
32
47
|
|
|
33
|
-
[tool.poetry.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
pandas = ">=2.0.3"
|
|
37
|
-
rics = ">=4.1.1"
|
|
38
|
-
|
|
39
|
-
# plotting
|
|
40
|
-
matplotlib = { version = "*", optional = true }
|
|
41
|
-
seaborn = { version = "*", optional = true }
|
|
42
|
-
|
|
43
|
-
# explorer
|
|
44
|
-
streamlit = { version = "*", optional = true }
|
|
45
|
-
croniter = { version = "*", optional = true }
|
|
46
|
-
|
|
47
|
-
[tool.poetry.extras]
|
|
48
|
-
plotting = ["matplotlib", "seaborn"]
|
|
49
|
-
streamlit = ["matplotlib", "seaborn", "streamlit", "croniter"]
|
|
48
|
+
[tool.poetry.requires-plugins]
|
|
49
|
+
poetry-plugin-export = ">=1.8"
|
|
50
50
|
|
|
51
51
|
[tool.poetry.group.manual-extras.dependencies]
|
|
52
52
|
# Extras that must be available for docs + tests go here. Doc/test-only deps go in their respective groups.
|
|
53
|
-
croniter = "^
|
|
54
|
-
pyarrow = "
|
|
55
|
-
polars = { version = "^
|
|
56
|
-
streamlit = "*"
|
|
53
|
+
croniter = "^6.0.0"
|
|
54
|
+
pyarrow = "^19.0.0"
|
|
55
|
+
polars = { version = "^1.21.0", extras = ["pandas"] }
|
|
57
56
|
|
|
58
57
|
[tool.poetry.group.docs]
|
|
59
58
|
[tool.poetry.group.docs.dependencies]
|
|
60
59
|
# duplicate object warnings for sphinx>=4
|
|
61
60
|
# description: https://github.com/astropy/astropy/issues/11723
|
|
62
61
|
# https://github.com/astropy/astropy/pull/12270
|
|
63
|
-
sphinx = "
|
|
64
|
-
sphinx-gallery = "^0.
|
|
65
|
-
pydata-sphinx-theme = "^0.
|
|
66
|
-
myst-parser = "
|
|
67
|
-
nbsphinx = "^0.9.
|
|
68
|
-
ipython = "^8.
|
|
62
|
+
sphinx = "~8.1.3"
|
|
63
|
+
sphinx-gallery = "^0.18.0"
|
|
64
|
+
pydata-sphinx-theme = "^0.16.1"
|
|
65
|
+
myst-parser = "^4.0.0"
|
|
66
|
+
nbsphinx = "^0.9.6"
|
|
67
|
+
ipython = "^8.31.0"
|
|
69
68
|
|
|
70
69
|
[tool.poetry.group.notebooks]
|
|
71
70
|
optional = true
|
|
@@ -76,26 +75,22 @@ jupyterlab-execute-time = "*"
|
|
|
76
75
|
tqdm = "*"
|
|
77
76
|
|
|
78
77
|
[tool.poetry.group.test.dependencies]
|
|
79
|
-
pytest = "^8.
|
|
80
|
-
xdoctest = "^1.
|
|
81
|
-
coverage = "^7.
|
|
82
|
-
pytest-cov = "^
|
|
83
|
-
|
|
84
|
-
scikit-learn = "^1.
|
|
85
|
-
|
|
86
|
-
# dask.datasets.timeseries() warns:
|
|
87
|
-
# UserWarning: dask_expr does not support the DataFrameIOFunction protocol for column projection
|
|
88
|
-
# on dask == 2024.3.1
|
|
89
|
-
dask = { version = "==2024.5.0", extras = ["dataframe"] }
|
|
78
|
+
pytest = "^8.3.4"
|
|
79
|
+
xdoctest = "^1.2.0"
|
|
80
|
+
coverage = "^7.6.10"
|
|
81
|
+
pytest-cov = "^6.0.0"
|
|
82
|
+
|
|
83
|
+
scikit-learn = "^1.6.1"
|
|
84
|
+
dask = { version = "^2025.1.0", extras = ["dataframe"] }
|
|
90
85
|
|
|
91
86
|
[tool.poetry.group.devops.dependencies]
|
|
92
|
-
invoke = "
|
|
93
|
-
mypy = "
|
|
94
|
-
ruff = "
|
|
87
|
+
invoke = "~2.2.0"
|
|
88
|
+
mypy = "~1.17.0"
|
|
89
|
+
ruff = "~0.12.3"
|
|
95
90
|
|
|
96
|
-
safety = "
|
|
97
|
-
codespell = "
|
|
98
|
-
bump2version = "
|
|
91
|
+
safety = "~3.5.1"
|
|
92
|
+
codespell = "~2.4.1"
|
|
93
|
+
bump2version = "~1.0.1"
|
|
99
94
|
|
|
100
95
|
[tool.ruff]
|
|
101
96
|
line-length = 120
|
|
@@ -140,8 +135,6 @@ select = [
|
|
|
140
135
|
"TRY",
|
|
141
136
|
]
|
|
142
137
|
ignore = [
|
|
143
|
-
"ANN101", # Missing type annotation for `self` in method
|
|
144
|
-
"ANN102", # Missing type annotation for `cls` in method
|
|
145
138
|
"D105", # Missing docstring in magic method
|
|
146
139
|
"D107", # Missing docstring in `__init__`
|
|
147
140
|
"ANN401",
|
|
@@ -152,8 +145,9 @@ ignore = [
|
|
|
152
145
|
"PLR0913", #
|
|
153
146
|
"SIM108", # Use ternary operator - coverage issue, see https://github.com/nedbat/coveragepy/issues/509
|
|
154
147
|
"TD003", # Missing issue link
|
|
148
|
+
"TC006", # Add quotes to type expression in `typing.cast()`
|
|
149
|
+
"UP038", # https://github.com/astral-sh/ruff/issues/7871
|
|
155
150
|
]
|
|
156
|
-
allowed-confusables = ["ℹ"]
|
|
157
151
|
|
|
158
152
|
[tool.ruff.lint.per-file-ignores]
|
|
159
153
|
"tests/*" = [
|
|
@@ -174,6 +168,10 @@ allowed-confusables = ["ℹ"]
|
|
|
174
168
|
"ARG002", # Unused method argument: `groups`
|
|
175
169
|
]
|
|
176
170
|
|
|
171
|
+
"**/time_split/app/*" = [
|
|
172
|
+
"S101" # Allow 'assert' keyword
|
|
173
|
+
]
|
|
174
|
+
|
|
177
175
|
[tool.ruff.lint.pydocstyle]
|
|
178
176
|
convention = "google"
|
|
179
177
|
[tool.ruff.lint.pycodestyle]
|
|
@@ -184,13 +182,10 @@ max-line-length = 150
|
|
|
184
182
|
filterwarnings = [
|
|
185
183
|
"error",
|
|
186
184
|
"ignore:Matplotlib is currently using agg:UserWarning",
|
|
187
|
-
"ignore:.*
|
|
185
|
+
"ignore:.*'mode' parameter.*Pillow 13.*:DeprecationWarning",
|
|
188
186
|
]
|
|
189
187
|
log_file_level = 10
|
|
190
188
|
log_file = "pytest.log"
|
|
191
|
-
norecursedirs = [
|
|
192
|
-
"**/cli_modules/*",
|
|
193
|
-
]
|
|
194
189
|
|
|
195
190
|
[build-system]
|
|
196
191
|
requires = ["poetry-core>=1.0.8"]
|
|
@@ -5,12 +5,12 @@ import logging as _logging
|
|
|
5
5
|
from ._frontend import log_split_progress, plot, split
|
|
6
6
|
|
|
7
7
|
__all__ = [
|
|
8
|
+
"__version__", # Make MyPy happy
|
|
8
9
|
"log_split_progress",
|
|
9
10
|
"plot",
|
|
10
11
|
"split",
|
|
11
|
-
"__version__", # Make MyPy happy
|
|
12
12
|
]
|
|
13
13
|
|
|
14
|
-
__version__ = "0.
|
|
14
|
+
__version__ = "0.7.0"
|
|
15
15
|
|
|
16
16
|
_logging.getLogger(__name__).addHandler(_logging.NullHandler())
|
|
@@ -4,7 +4,7 @@ from typing import NamedTuple
|
|
|
4
4
|
|
|
5
5
|
from pandas import Timedelta, Timestamp
|
|
6
6
|
|
|
7
|
-
from ..settings import auto_expand_limits
|
|
7
|
+
from ..settings import auto_expand_limits, misc
|
|
8
8
|
from ..types import ExpandLimits, TimedeltaTypes
|
|
9
9
|
|
|
10
10
|
LimitsTuple = tuple[Timestamp, Timestamp]
|
|
@@ -23,6 +23,8 @@ def expand_limits(
|
|
|
23
23
|
) -> LimitsTuple:
|
|
24
24
|
"""Derive the `"real"` bounds of `limits`.
|
|
25
25
|
|
|
26
|
+
Use :attr:`time_split.settings.misc.round_limits` to allow inward "expansion".
|
|
27
|
+
|
|
26
28
|
Args:
|
|
27
29
|
limits: A tuple ``(min, max)`` of timestamps.
|
|
28
30
|
spec: Expansion spec as described in the :ref:`User guide`. Also supports level-tuples
|
|
@@ -61,6 +63,7 @@ def expand_limits(
|
|
|
61
63
|
>>> expand_limits(limits, "d<14h")
|
|
62
64
|
(Timestamp('2019-05-11 00:00:00'), Timestamp('2019-05-11 11:05:30'))
|
|
63
65
|
|
|
66
|
+
To disable this restriction, set :attr:`round_limits=True <.misc.round_limits>` in the settings.
|
|
64
67
|
"""
|
|
65
68
|
if limits[0] >= limits[1]:
|
|
66
69
|
msg = f"Bad limits. Expected limits[1] > limits[0], but got {limits=}."
|
|
@@ -102,19 +105,24 @@ def _from_levels(limits: LimitsTuple, *, levels: Iterable[_TimedeltaTuple] | Non
|
|
|
102
105
|
def _apply(limits: LimitsTuple, *, level: _TimedeltaTuple) -> LimitsTuple:
|
|
103
106
|
lo, hi = limits
|
|
104
107
|
|
|
105
|
-
|
|
108
|
+
round = misc.round_limits
|
|
109
|
+
lo_floor = lo.round(level.round_to) if round else lo.floor(level.round_to)
|
|
106
110
|
if abs(lo_floor - lo) > level.tolerance:
|
|
107
111
|
return limits
|
|
108
112
|
|
|
109
|
-
hi_ceil = hi.ceil(level.round_to)
|
|
113
|
+
hi_ceil = hi.round(level.round_to) if round else hi.ceil(level.round_to)
|
|
110
114
|
if abs(hi_ceil - hi) > level.tolerance:
|
|
111
115
|
return limits
|
|
112
116
|
|
|
113
117
|
if auto_expand_limits.SANITY_CHECK:
|
|
114
|
-
if
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
if round:
|
|
119
|
+
if lo_floor == hi_ceil:
|
|
120
|
+
return limits
|
|
121
|
+
else:
|
|
122
|
+
if lo.round(level.round_to) != lo_floor:
|
|
123
|
+
return limits
|
|
124
|
+
if hi.round(level.round_to) != hi_ceil:
|
|
125
|
+
return limits
|
|
118
126
|
|
|
119
127
|
return lo_floor, hi_ceil
|
|
120
128
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import NamedTuple,
|
|
1
|
+
from typing import NamedTuple, get_args
|
|
2
2
|
|
|
3
3
|
from pandas import DatetimeIndex, NaT, Timedelta, Timestamp, date_range
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ from ..types import DatetimeIterable, ExpandLimits, Schedule, TimedeltaTypes
|
|
|
6
6
|
from ._limits import LimitsTuple
|
|
7
7
|
from ._process_available import ProcessAvailableResult, process_available
|
|
8
8
|
|
|
9
|
-
NO_LIMITS =
|
|
9
|
+
NO_LIMITS: LimitsTuple = NaT, NaT
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class MaterializedSchedule(NamedTuple):
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
from dataclasses import asdict, dataclass
|
|
3
|
-
from functools import lru_cache
|
|
4
2
|
from typing import cast, get_args
|
|
5
3
|
|
|
6
4
|
from pandas import Timedelta
|
|
@@ -17,12 +15,9 @@ from ..types import (
|
|
|
17
15
|
Span,
|
|
18
16
|
TimedeltaTypes,
|
|
19
17
|
)
|
|
20
|
-
from ._limits import LimitsTuple
|
|
21
18
|
from ._schedule import MaterializedSchedule, materialize_schedule
|
|
22
19
|
from ._span import OffsetCalculator, to_strict_span
|
|
23
20
|
|
|
24
|
-
LOGGER = logging.getLogger("time_split")
|
|
25
|
-
|
|
26
21
|
|
|
27
22
|
@dataclass(frozen=True)
|
|
28
23
|
class DatetimeIndexSplitter:
|
|
@@ -39,7 +34,6 @@ class DatetimeIndexSplitter:
|
|
|
39
34
|
def get_splits(self, available: DatetimeIterable | None = None) -> DatetimeSplits:
|
|
40
35
|
"""Compute a split of given user data."""
|
|
41
36
|
ms = self._materialize_schedule(available)
|
|
42
|
-
self._log_expansion(ms.available_metadata.limits, expanded=ms.available_metadata.expanded_limits)
|
|
43
37
|
return self._make_bounds_list(ms)
|
|
44
38
|
|
|
45
39
|
def get_plot_data(self, available: DatetimeIterable | None = None) -> tuple[DatetimeSplits, MaterializedSchedule]:
|
|
@@ -70,7 +64,7 @@ class DatetimeIndexSplitter:
|
|
|
70
64
|
return ms
|
|
71
65
|
|
|
72
66
|
from_end = ms.available_metadata.expanded_limits[1] - (ms.schedule[-1] + Timedelta(self.after))
|
|
73
|
-
from_end = from_end.floor(schedule_frequency.base)
|
|
67
|
+
from_end = from_end.floor(schedule_frequency.base) # TODO(settings): should this depend on misc.round_limits?
|
|
74
68
|
|
|
75
69
|
return ms._replace(schedule=ms.schedule + from_end)
|
|
76
70
|
|
|
@@ -109,7 +103,6 @@ class DatetimeIndexSplitter:
|
|
|
109
103
|
|
|
110
104
|
Returns:
|
|
111
105
|
Filtered splits.
|
|
112
|
-
|
|
113
106
|
"""
|
|
114
107
|
if self.step != 1:
|
|
115
108
|
step = abs(self.step)
|
|
@@ -127,21 +120,6 @@ class DatetimeIndexSplitter:
|
|
|
127
120
|
|
|
128
121
|
return [s for s in splits if settings.filter(*s)]
|
|
129
122
|
|
|
130
|
-
def _log_expansion(self, original: LimitsTuple, *, expanded: LimitsTuple) -> None:
|
|
131
|
-
from .._frontend import format_expanded_limits
|
|
132
|
-
|
|
133
|
-
if original == expanded or not LOGGER.isEnabledFor(logging.INFO):
|
|
134
|
-
return
|
|
135
|
-
|
|
136
|
-
message = format_expanded_limits(original, expanded=expanded, expand_limits=self.expand_limits)
|
|
137
|
-
self._emit_once(message)
|
|
138
|
-
|
|
139
|
-
@staticmethod
|
|
140
|
-
@lru_cache(8)
|
|
141
|
-
def _emit_once(message: str) -> None:
|
|
142
|
-
"""Emit if **not** in the eight most recent emission messages."""
|
|
143
|
-
LOGGER.info(message)
|
|
144
|
-
|
|
145
123
|
def __post_init__(self) -> None:
|
|
146
124
|
# Verify n_splits
|
|
147
125
|
if self.n_splits < 0:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from time_split._compat import deprecated_params
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import ParamSpec, TypeVar
|
|
4
3
|
|
|
5
4
|
P = ParamSpec("P")
|
|
6
5
|
T = TypeVar("T")
|
|
@@ -15,12 +14,6 @@ def docs(__func: Callable[P, T], /) -> Callable[P, T]:
|
|
|
15
14
|
"""Add info the docstring of a function."""
|
|
16
15
|
assert __func.__doc__ is not None # noqa: S101
|
|
17
16
|
__func.__doc__ = __func.__doc__.format(**_DOCSTRINGS)
|
|
18
|
-
|
|
19
|
-
if isinstance(__func, type):
|
|
20
|
-
__func.__init__ = deprecated_params(__func.__init__)
|
|
21
|
-
else:
|
|
22
|
-
__func = deprecated_params(__func)
|
|
23
|
-
|
|
24
17
|
return __func
|
|
25
18
|
|
|
26
19
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
from collections.abc import Sized
|
|
1
2
|
from dataclasses import asdict, dataclass, replace
|
|
2
|
-
from typing import TYPE_CHECKING, Any, Literal
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
3
4
|
|
|
4
5
|
import pandas as pd
|
|
5
6
|
from pandas import Timestamp
|
|
6
7
|
from rics.misc import format_kwargs, get_public_module
|
|
7
|
-
|
|
8
|
-
from time_split._compat import fmt_sec
|
|
8
|
+
from rics.strings import format_seconds as fmt_sec
|
|
9
9
|
|
|
10
10
|
from .._backend import DatetimeIndexSplitter
|
|
11
11
|
from .._backend._datetime_index_like import DatetimeIndexLike
|
|
@@ -65,7 +65,7 @@ def plot(
|
|
|
65
65
|
after: Span = 1,
|
|
66
66
|
step: int = 1,
|
|
67
67
|
n_splits: int = 0,
|
|
68
|
-
available: DatetimeIterable | None = None,
|
|
68
|
+
available: DatetimeIterable | pd.DataFrame | pd.Series | None = None,
|
|
69
69
|
expand_limits: ExpandLimits = "auto",
|
|
70
70
|
ignore_filters: bool = False,
|
|
71
71
|
# Split plot args
|
|
@@ -112,6 +112,15 @@ def plot(
|
|
|
112
112
|
"""
|
|
113
113
|
import matplotlib.pyplot as plt
|
|
114
114
|
|
|
115
|
+
if (
|
|
116
|
+
available is not None
|
|
117
|
+
and hasattr(available, "index")
|
|
118
|
+
and not callable(available.index)
|
|
119
|
+
and hasattr(available, "shape")
|
|
120
|
+
and len(available.shape) != 1
|
|
121
|
+
):
|
|
122
|
+
available = available.index
|
|
123
|
+
|
|
115
124
|
splitter = DatetimeIndexSplitter(
|
|
116
125
|
schedule,
|
|
117
126
|
before=before,
|
|
@@ -121,6 +130,7 @@ def plot(
|
|
|
121
130
|
expand_limits=expand_limits,
|
|
122
131
|
ignore_filters=ignore_filters,
|
|
123
132
|
)
|
|
133
|
+
|
|
124
134
|
plot_data = _get_plot_data(available, splitter, row_count_bin=row_count_bin, show_removed=show_removed)
|
|
125
135
|
|
|
126
136
|
if bar_labels is True:
|
|
@@ -249,7 +259,7 @@ def _add_bar_labels(
|
|
|
249
259
|
unit=unit_or_labels,
|
|
250
260
|
)
|
|
251
261
|
|
|
252
|
-
for bar, label in zip(ax.containers, labels):
|
|
262
|
+
for bar, label in zip(ax.containers, labels, strict=True):
|
|
253
263
|
ax.bar_label(bar, labels=[label], **kwargs) # type: ignore[arg-type]
|
|
254
264
|
|
|
255
265
|
|
|
@@ -6,8 +6,7 @@ from typing import Any, Generic
|
|
|
6
6
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
from rics.collections.dicts import flatten_dict
|
|
9
|
-
|
|
10
|
-
from time_split._compat import fmt_sec
|
|
9
|
+
from rics.strings import format_seconds as fmt_sec
|
|
11
10
|
|
|
12
11
|
from ..settings import log_split_progress as settings
|
|
13
12
|
from ..types import DatetimeSplitBounds, FormatMetrics, GetMetrics, LoggerArg, MetricsType, SplitProgressExtras
|
|
@@ -122,7 +121,7 @@ class _ProgressTracker(Generic[MetricsType]):
|
|
|
122
121
|
n_splits = len(splits)
|
|
123
122
|
|
|
124
123
|
for n, split in enumerate(splits, start=1):
|
|
125
|
-
default_extras = SplitProgressExtras(
|
|
124
|
+
default_extras = SplitProgressExtras[MetricsType](
|
|
126
125
|
n=n,
|
|
127
126
|
n_splits=n_splits,
|
|
128
127
|
start=split.start.isoformat(),
|