toolbox-utils 5.2.1__tar.gz → 5.2.3__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.
Files changed (74) hide show
  1. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/.github/workflows/pypi-package.yml +2 -2
  2. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/.github/workflows/tests.yml +24 -32
  3. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/.pre-commit-config.yaml +9 -11
  4. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/CHANGELOG.md +21 -0
  5. {toolbox_utils-5.2.1/src/toolbox_utils.egg-info → toolbox_utils-5.2.3}/PKG-INFO +11 -11
  6. toolbox_utils-5.2.3/VERSION +1 -0
  7. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/pyproject.toml +29 -35
  8. toolbox_utils-5.2.3/src/toolbox_utils/readers/plotgen.py +43 -0
  9. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/src/toolbox_utils/readers/wdm.py +9 -7
  10. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/src/toolbox_utils/tsutils.py +151 -294
  11. toolbox_utils-5.2.3/src/toolbox_utils/utils.py +170 -0
  12. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3/src/toolbox_utils.egg-info}/PKG-INFO +11 -11
  13. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/src/toolbox_utils.egg-info/SOURCES.txt +1 -0
  14. toolbox_utils-5.2.3/src/toolbox_utils.egg-info/requires.txt +9 -0
  15. toolbox_utils-5.2.3/tests/data_plotgen.plt +758 -0
  16. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/test_asbestfreq.py +12 -4
  17. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/test_period_timestamp.py +46 -27
  18. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/test_read.py +4 -3
  19. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/test_wdm.py +21 -3
  20. toolbox_utils-5.2.1/VERSION +0 -1
  21. toolbox_utils-5.2.1/src/toolbox_utils/readers/plotgen.py +0 -55
  22. toolbox_utils-5.2.1/src/toolbox_utils.egg-info/requires.txt +0 -13
  23. toolbox_utils-5.2.1/tests/data_plotgen.plt +0 -758
  24. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/.deepsource.toml +0 -0
  25. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/.github/dependabot.yml +0 -0
  26. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/.github/workflows/clean-workflow-runs.yml +0 -0
  27. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/.gitignore +0 -0
  28. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/.sourcery.yaml +0 -0
  29. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/AUTHORS.rst +0 -0
  30. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/BADGES.rst +0 -0
  31. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/CONTRIBUTING.rst +0 -0
  32. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/LICENSE.txt +0 -0
  33. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/README.rst +0 -0
  34. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/docs/Makefile +0 -0
  35. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/docs/authors.rst +0 -0
  36. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/docs/conf.py +0 -0
  37. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/docs/contributing.rst +0 -0
  38. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/docs/index.rst +0 -0
  39. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/docs/license.rst +0 -0
  40. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/docs/make.bat +0 -0
  41. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/docs/readme.rst +0 -0
  42. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/setup.cfg +0 -0
  43. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/src/toolbox_utils/__init__.py +0 -0
  44. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/src/toolbox_utils/readers/__init__.py +0 -0
  45. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/src/toolbox_utils/readers/hbn.py +0 -0
  46. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/src/toolbox_utils.egg-info/dependency_links.txt +0 -0
  47. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/src/toolbox_utils.egg-info/top_level.txt +0 -0
  48. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data.wdm +0 -0
  49. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_bi_daily.csv +0 -0
  50. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_bivl.hbn +0 -0
  51. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_end.bivl.csv +0 -0
  52. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_end.daily.csv +0 -0
  53. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_end.monthly.csv +0 -0
  54. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_end.yearly.csv +0 -0
  55. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_flow_stage.xlsx +0 -0
  56. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_period.bivl.csv +0 -0
  57. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_period.daily.csv +0 -0
  58. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_period.monthly.csv +0 -0
  59. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_period.yearly.csv +0 -0
  60. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_simple.csv +0 -0
  61. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_start.bivl.csv +0 -0
  62. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_start.daily.csv +0 -0
  63. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_start.monthly.csv +0 -0
  64. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_start.yearly.csv +0 -0
  65. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_wdm_1.csv +0 -0
  66. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_wdm_2.csv +0 -0
  67. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/data_yearly.hbn +0 -0
  68. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/test_date_slice.py +0 -0
  69. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/test_dateparse.py +0 -0
  70. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/test_extract.py +0 -0
  71. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/test_hbn.py +0 -0
  72. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/test_make_list.py +0 -0
  73. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/test_plotgen.py +0 -0
  74. {toolbox_utils-5.2.1 → toolbox_utils-5.2.3}/tests/test_range_to_numlist.py +0 -0
@@ -28,7 +28,7 @@ jobs:
28
28
 
29
29
  steps:
30
30
  - name: Checkout source
31
- uses: actions/checkout@v4
31
+ uses: actions/checkout@v6
32
32
  with:
33
33
  submodules: recursive
34
34
 
@@ -38,7 +38,7 @@ jobs:
38
38
  python -m build
39
39
 
40
40
  - name: Download artifact
41
- uses: actions/download-artifact@v4
41
+ uses: actions/download-artifact@v7
42
42
  with:
43
43
  path: dist
44
44
  merge-multiple: true
@@ -21,46 +21,36 @@ jobs:
21
21
  fail-fast: false
22
22
  matrix:
23
23
  os: [ubuntu-latest, macos-latest, windows-latest]
24
- python-versions: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
25
- pandas-versions: [1.5.3, 2.0.0, 2.2.0, 2.2.3]
26
- toolchain:
27
- - {compiler: gcc, version: 13}
24
+ python-versions: ['3.10', '3.11', '3.12', '3.13', '3.14']
25
+ pandas-versions: [pandas==1.*, pandas==2.*, pandas==3.*]
26
+ numpy-versions: [numpy==1.*, numpy==2.*]
27
+
28
28
  exclude:
29
+ - python-versions: '3.12'
30
+ pandas-versions: pandas==1.*
29
31
  - python-versions: '3.13'
30
- pandas-versions: 1.5.3
31
- - python-versions: '3.13'
32
- pandas-versions: 2.0.0
32
+ pandas-versions: pandas==1.*
33
+ - python-versions: '3.14'
34
+ pandas-versions: pandas==1.*
35
+ - python-versions: '3.12'
36
+ numpy-versions: numpy==1.*
33
37
  - python-versions: '3.13'
34
- pandas-versions: 2.2.0
35
- - python-versions: '3.8'
36
- pandas-versions: 2.2.0
37
- - python-versions: '3.8'
38
- pandas-versions: 2.2.3
39
- - os: windows-latest
40
- python-versions: '3.8'
41
- - os: windows-latest
42
- python-versions: '3.9'
43
- pandas-versions: 2.2.0
44
- - os: windows-latest
45
- python-versions: '3.10'
46
- pandas-versions: 2.2.0
47
- - os: windows-latest
48
- python-versions: '3.11'
49
- pandas-versions: 2.2.0
50
- - os: windows-latest
51
- python-versions: '3.12'
52
- pandas-versions: 2.2.0
53
- - os: windows-latest
54
- python-versions: '3.13'
38
+ numpy-versions: numpy==1.*
39
+ - python-versions: '3.14'
40
+ numpy-versions: numpy==1.*
41
+ - pandas-versions: pandas==1.*
42
+ numpy-versions: numpy==2.*
43
+ - python-versions: '3.10'
44
+ pandas-versions: pandas==3.*
55
45
 
56
46
  steps:
57
47
  - name: Checkout repository
58
- uses: actions/checkout@v4
48
+ uses: actions/checkout@v6
59
49
  with:
60
50
  submodules: recursive
61
51
 
62
52
  - name: Set up Python ${{ matrix.python-versions }}
63
- uses: actions/setup-python@v5
53
+ uses: actions/setup-python@v6
64
54
  with:
65
55
  python-version: ${{ matrix.python-versions }}
66
56
 
@@ -74,10 +64,12 @@ jobs:
74
64
  version ${{ matrix.pandas-versions }}
75
65
  run: >
76
66
  python -m pip install
77
- pandas==${{ matrix.pandas-versions }} 'numpy<2' .
67
+ '${{ matrix.pandas-versions }}'
68
+ '${{ matrix.numpy-versions }}' .
78
69
 
79
70
  - name: Test with pytest
80
- run: python -m pytest --cov
71
+ run: |
72
+ python -m pytest --cov
81
73
 
82
74
  - name: Upload coverage data to coveralls.io
83
75
  uses: coverallsapp/github-action@v2
@@ -11,7 +11,7 @@ exclude: |
11
11
 
12
12
  repos:
13
13
  - repo: https://github.com/pre-commit/pre-commit-hooks
14
- rev: v5.0.0
14
+ rev: v6.0.0
15
15
  hooks:
16
16
  - id: check-case-conflict
17
17
  - id: check-docstring-first
@@ -23,15 +23,13 @@ repos:
23
23
  - id: check-xml
24
24
  - id: end-of-file-fixer
25
25
  exclude: notebooks/tstoolbox_plot_bash.sh
26
- - id: fix-encoding-pragma
27
- args: [--remove]
28
26
  - id: mixed-line-ending
29
27
  - id: trailing-whitespace
30
28
  exclude: notebooks/tstoolbox_plot_bash.sh
31
29
 
32
30
  - repo: https://github.com/astral-sh/ruff-pre-commit
33
31
  # Ruff version.
34
- rev: v0.12.0
32
+ rev: v0.15.2
35
33
  hooks:
36
34
  # Run the linter.
37
35
  - id: ruff
@@ -42,7 +40,7 @@ repos:
42
40
  types_or: [python, pyi, jupyter]
43
41
 
44
42
  - repo: https://github.com/pycqa/isort
45
- rev: 6.0.1
43
+ rev: 8.0.0
46
44
  hooks:
47
45
  - id: isort
48
46
  name: isort (python)
@@ -54,13 +52,13 @@ repos:
54
52
  types: [pyi]
55
53
 
56
54
  - repo: https://github.com/pappasam/toml-sort
57
- rev: v0.24.2
55
+ rev: v0.24.3
58
56
  hooks:
59
57
  - id: toml-sort-fix
60
58
  args: [--in-place, --spaces-indent-inline-array, '4']
61
59
 
62
60
  - repo: https://github.com/adrienverge/yamllint.git
63
- rev: v1.37.1
61
+ rev: v1.38.0
64
62
  hooks:
65
63
  - id: yamllint
66
64
  args: [--format, parsable, --strict]
@@ -77,23 +75,23 @@ repos:
77
75
  args: [-s, bash]
78
76
 
79
77
  - repo: https://github.com/lovesegfault/beautysh
80
- rev: v6.2.1
78
+ rev: v6.4.2
81
79
  hooks:
82
80
  - id: beautysh
83
81
  args: [--indent-size, '4']
84
82
 
85
83
  - repo: https://github.com/asottile/blacken-docs
86
- rev: 1.19.1
84
+ rev: 1.20.0
87
85
  hooks:
88
86
  - id: blacken-docs
89
87
 
90
88
  - repo: https://github.com/asottile/pyupgrade
91
- rev: v3.20.0
89
+ rev: v3.21.2
92
90
  hooks:
93
91
  - id: pyupgrade
94
92
 
95
93
  - repo: https://github.com/commitizen-tools/commitizen
96
- rev: v4.8.3
94
+ rev: v4.13.8
97
95
  hooks:
98
96
  - id: commitizen
99
97
  stages: [commit-msg]
@@ -1,3 +1,24 @@
1
+ ## v5.2.3 (2026-03-06)
2
+
3
+ ### Fix
4
+
5
+ - additional checks for RecursionError
6
+ - wrap the RecursionError in a try/except block
7
+ - test to fix recursive error with older version of numpy/pandas
8
+ - possible fix for recursion problem with older numpy/pandas
9
+ - include support for pandas 3.0
10
+ - another fix for time offset differences by pandas versions
11
+ - fixed wdm pandas offsets
12
+ - use .where instead of .replace to avoid RecursionError in pandas 1.5.x
13
+ - fixed PLTGEN reader
14
+
15
+ ## v5.2.2 (2025-11-13)
16
+
17
+ ### Fix
18
+
19
+ - use .where instead of .replace to avoid RecursionError in pandas 1.5.x
20
+ - fixed PLTGEN reader
21
+
1
22
  ## v5.2.1 (2025-07-20)
2
23
 
3
24
  ### Fix
@@ -1,38 +1,38 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: toolbox_utils
3
- Version: 5.2.1
3
+ Version: 5.2.3
4
4
  Summary: Python toolbox for common utilities
5
5
  Author-email: Tim Cera <tim@cerazone.net>
6
6
  License: BSD-3-Clause
7
+ Project-URL: bitbucket, https://bitbucket.org/timcera/toolbox_utils/src/main/
7
8
  Project-URL: documentation, https://timcera.bitbucket.io/toolbox_utils/docs/index.html#toolbox_utils-documentation
8
9
  Project-URL: github, https://github.com/timcera/toolbox_utils
9
- Project-URL: bitbucket, https://bitbucket.org/timcera/toolbox_utils/src/main/
10
- Keywords: time-series,cli-app,aggregate,fill,filter
10
+ Keywords: aggregate,cli-app,fill,filter,time-series
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
- Classifier: Intended Audience :: Science/Research
13
- Classifier: Intended Audience :: End Users/Desktop
14
- Classifier: Intended Audience :: Developers
15
12
  Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: End Users/Desktop
15
+ Classifier: Intended Audience :: Science/Research
16
16
  Classifier: License :: OSI Approved :: BSD License
17
17
  Classifier: Natural Language :: English
18
18
  Classifier: Operating System :: OS Independent
19
19
  Classifier: Programming Language :: Python :: 3 :: Only
20
- Classifier: Programming Language :: Python :: 3.8
21
- Classifier: Programming Language :: Python :: 3.9
22
20
  Classifier: Programming Language :: Python :: 3.10
23
21
  Classifier: Programming Language :: Python :: 3.11
24
22
  Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Programming Language :: Python :: 3.14
25
25
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
26
26
  Classifier: Topic :: Scientific/Engineering
27
27
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
28
- Requires-Python: >=3.8
28
+ Requires-Python: >=3.10
29
29
  Description-Content-Type: text/x-rst
30
30
  License-File: LICENSE.txt
31
31
  Requires-Dist: dateparser
32
- Requires-Dist: numpy<2.0,>=1.20; python_version <= "3.9"
32
+ Requires-Dist: numpy
33
33
  Requires-Dist: openpyxl
34
34
  Requires-Dist: pandas[excel]
35
- Requires-Dist: pint!=0.21.*,<0.22; python_version < "3.9"
35
+ Requires-Dist: pint
36
36
  Requires-Dist: pint-pandas
37
37
  Requires-Dist: pydantic
38
38
  Requires-Dist: scipy
@@ -0,0 +1 @@
1
+ 5.2.3
@@ -1,71 +1,67 @@
1
1
  [build-system]
2
2
  build-backend = "setuptools.build_meta"
3
3
  requires = [
4
- "setuptools>=45",
5
- "setuptools_scm[toml]>=6.2",
6
- "wheel"
4
+ "setuptools-scm[simple]>=8",
5
+ "setuptools>=80"
7
6
  ]
8
7
 
9
8
  [project]
10
- name = "toolbox_utils"
11
- dynamic = ["readme", "version"]
12
- description = "Python toolbox for common utilities"
13
- dependencies = [
14
- "dateparser",
15
- "numpy >= 1.20, < 2.0 ; python_version <= '3.9'",
16
- "openpyxl",
17
- "pandas[excel]",
18
- "pint != 0.21.*, < 0.22 ; python_version < '3.9'",
19
- "pint-pandas",
20
- "pydantic",
21
- "scipy",
22
- "tabulate"
23
- ]
24
- # Unused dependencies found: matplotlib, odfpy, openpyxl, pint, pyxlsb, tables,
25
- # typing-extensions, xlrd, xlsxwriter that should be added to the projects that
26
- # depend on this toolbox_utils.
27
9
  authors = [
28
- {name = "Tim Cera", email = "tim@cerazone.net"}
10
+ {email = "tim@cerazone.net", name = "Tim Cera"}
29
11
  ]
30
12
  classifiers = [
31
13
  "Development Status :: 5 - Production/Stable",
32
- "Intended Audience :: Science/Research",
33
- "Intended Audience :: End Users/Desktop",
34
- "Intended Audience :: Developers",
35
14
  "Environment :: Console",
15
+ "Intended Audience :: Developers",
16
+ "Intended Audience :: End Users/Desktop",
17
+ "Intended Audience :: Science/Research",
36
18
  "License :: OSI Approved :: BSD License",
37
19
  "Natural Language :: English",
38
20
  "Operating System :: OS Independent",
39
21
  "Programming Language :: Python :: 3 :: Only",
40
- "Programming Language :: Python :: 3.8",
41
- "Programming Language :: Python :: 3.9",
42
22
  "Programming Language :: Python :: 3.10",
43
23
  "Programming Language :: Python :: 3.11",
44
24
  "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Programming Language :: Python :: 3.14",
45
27
  "Topic :: Scientific/Engineering :: Information Analysis",
46
28
  "Topic :: Scientific/Engineering",
47
29
  "Topic :: Software Development :: Libraries :: Python Modules"
30
+ ] # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
31
+ dependencies = [
32
+ "dateparser",
33
+ "numpy",
34
+ "openpyxl",
35
+ "pandas[excel]",
36
+ "pint",
37
+ "pint-pandas",
38
+ "pydantic",
39
+ "scipy",
40
+ "tabulate"
48
41
  ]
42
+ description = "Python toolbox for common utilities"
43
+ dynamic = ["readme", "version"]
49
44
  keywords = [
50
- "time-series",
51
- "cli-app",
52
45
  "aggregate",
46
+ "cli-app",
53
47
  "fill",
54
- "filter"
48
+ "filter",
49
+ "time-series"
55
50
  ]
56
51
  license = {text = "BSD-3-Clause"}
57
- requires-python = ">=3.8"
52
+ name = "toolbox_utils"
53
+ requires-python = ">=3.10"
58
54
 
59
55
  [project.urls]
56
+ bitbucket = "https://bitbucket.org/timcera/toolbox_utils/src/main/"
60
57
  documentation = "https://timcera.bitbucket.io/toolbox_utils/docs/index.html#toolbox_utils-documentation"
61
58
  github = "https://github.com/timcera/toolbox_utils"
62
- bitbucket = "https://bitbucket.org/timcera/toolbox_utils/src/main/"
63
59
 
64
60
  [tool.commitizen]
65
61
  name = "cz_conventional_commits"
66
62
  tag_format = "v$version"
67
63
  update_changelog_on_bump = true
68
- version = "5.2.1"
64
+ version = "5.2.3"
69
65
  version_files = ["VERSION"]
70
66
 
71
67
  [tool.isort]
@@ -75,8 +71,8 @@ profile = "black"
75
71
  testpaths = ["tests"]
76
72
 
77
73
  [tool.setuptools]
78
- license-files = ["LICENSE.txt"]
79
74
  include-package-data = true
75
+ license-files = ["LICENSE.txt"]
80
76
 
81
77
  [tool.setuptools.dynamic]
82
78
  readme = {file = "README.rst"}
@@ -84,5 +80,3 @@ version = {file = "VERSION"}
84
80
 
85
81
  [tool.setuptools.packages.find]
86
82
  where = ["src"]
87
-
88
- [tool.setuptools_scm]
@@ -0,0 +1,43 @@
1
+ """For reading HSPF plotgen files."""
2
+
3
+ import pandas as pd
4
+
5
+
6
+ def plotgen_extract(filename):
7
+ """Reads HSPF PLTGEN files and creates a DataFrame."""
8
+ found_column_names = False
9
+ column_names = []
10
+ with open(filename, encoding="ascii") as fpointer:
11
+ for i, line in enumerate(fpointer):
12
+ if "LINTYP" in line:
13
+ found_column_names = True
14
+ continue
15
+ if line[5:].startswith("Time series"):
16
+ break
17
+ if found_column_names:
18
+ if column_name := line[4:30].strip():
19
+ column_names.append(column_name)
20
+ pgdf = pd.read_fwf(
21
+ fpointer,
22
+ colspecs=[(5, 10), (10, 13), (13, 16), (16, 19), (19, 22)]
23
+ + [(22 + i * 14, 36 + i * 14) for i in range(len(column_names))],
24
+ skiprows=3,
25
+ names=["Year", "Month", "Day", "Hour", "Minute"] + column_names,
26
+ )
27
+
28
+ # .replace causes RecursionError in 1.5.* versions of pandas and so use
29
+ # .where instead.
30
+ pgdf = pgdf.where(pgdf != -1e30, pd.NA).dropna(how="all", subset=column_names)
31
+
32
+ # Can't let read_fwf parse dates because HSPF can use 24:00 for midnight of
33
+ # the following day, where pandas can't work with that. So we create
34
+ # manually here by creating an HH:MM delta and adding to the date.
35
+ pgdf["delta"] = pd.to_timedelta(
36
+ pgdf["Hour"].astype(int), unit="h"
37
+ ) + pd.to_timedelta(pgdf["Minute"].astype(int), unit="m")
38
+ pgdf["Datetime"] = pd.to_datetime(pgdf[["Year", "Month", "Day"]]) + pgdf["delta"]
39
+
40
+ pgdf = pgdf.drop(columns=["Year", "Month", "Day", "Hour", "Minute", "delta"])
41
+ pgdf = pgdf.set_index(["Datetime"])
42
+
43
+ return pgdf
@@ -7,6 +7,8 @@ from datetime import datetime
7
7
  import numpy as np
8
8
  import pandas as pd
9
9
 
10
+ from ..utils import pandas_offset_by_version
11
+
10
12
  # look up attributes NAME, data type (Integer; Real; String) and data length by attribute number
11
13
  attrinfo = {
12
14
  1: ("TSTYPE", "S", 4),
@@ -37,13 +39,13 @@ attrinfo = {
37
39
  }
38
40
 
39
41
  freq = {
40
- 7: "100YS",
41
- 6: "YS",
42
- 5: "MS",
43
- 4: "D",
44
- 3: "H",
45
- 2: "min",
46
- 1: "S",
42
+ 7: f"100{pandas_offset_by_version('YS')}",
43
+ 6: pandas_offset_by_version("YS"),
44
+ 5: pandas_offset_by_version("MS"),
45
+ 4: pandas_offset_by_version("D"),
46
+ 3: pandas_offset_by_version("h"),
47
+ 2: pandas_offset_by_version("min"),
48
+ 1: pandas_offset_by_version("s"),
47
49
  } # pandas date_range() frequency by TCODE, TGROUP
48
50
 
49
51