mspu 0.0.1__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.
mspu-0.0.1/.gitignore ADDED
@@ -0,0 +1,172 @@
1
+ #https://github.com/github/gitignore/blob/main/Python.gitignore
2
+
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ share/python-wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+ MANIFEST
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ *.py,cover
52
+ .hypothesis/
53
+ .pytest_cache/
54
+ cover/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ .pybuilder/
78
+ target/
79
+
80
+ # Jupyter Notebook
81
+ .ipynb_checkpoints
82
+
83
+ # IPython
84
+ profile_default/
85
+ ipython_config.py
86
+
87
+ # pyenv
88
+ # For a library or package, you might want to ignore these files since the code is
89
+ # intended to run in multiple environments; otherwise, check them in:
90
+ # .python-version
91
+
92
+ # pipenv
93
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
95
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
96
+ # install all needed dependencies.
97
+ #Pipfile.lock
98
+
99
+ # poetry
100
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
101
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
102
+ # commonly ignored for libraries.
103
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
104
+ #poetry.lock
105
+
106
+ # pdm
107
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
108
+ #pdm.lock
109
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
110
+ # in version control.
111
+ # https://pdm.fming.dev/#use-with-ide
112
+ .pdm.toml
113
+
114
+ # PEP 582; used by e.g. github.com/user/pyflow and github.com/pdm-project/pdm
115
+ __pypackages__/
116
+
117
+ # Celery stuff
118
+ celerybeat-schedule
119
+ celerybeat.pid
120
+
121
+ # SageMath parsed files
122
+ *.sage.py
123
+
124
+ # Environments
125
+ .env
126
+ .venv
127
+ env/
128
+ venv/
129
+ ENV/
130
+ env.bak/
131
+ venv.bak/
132
+
133
+ # Spyder project settings
134
+ .spyderproject
135
+ .spyproject
136
+
137
+ # Rope project settings
138
+ .ropeproject
139
+
140
+ # build
141
+ /_build
142
+
143
+ # mkdocs documentation
144
+ /site
145
+
146
+ # sphinx documentation
147
+ /docs/api/api
148
+
149
+ # mypy
150
+ .mypy_cache/
151
+ .dmypy.json
152
+ dmypy.json
153
+
154
+ # Pyre type checker
155
+ .pyre/
156
+
157
+ # pytype static type analyzer
158
+ .pytype/
159
+
160
+ # Cython debug symbols
161
+ cython_debug/
162
+
163
+ # PyCharm
164
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
165
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
167
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168
+ #.idea/
169
+ Footer
170
+
171
+ # Visual Studio Code settings
172
+ .vscode/
mspu-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Sean Ma
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
mspu-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,32 @@
1
+ Metadata-Version: 2.4
2
+ Name: mspu
3
+ Version: 0.0.1
4
+ Summary: Ma's python utils package.
5
+ Author-email: Sean Ma <sean.sl.ma@gmail.com>
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.12
9
+ Requires-Dist: numpy
10
+ Requires-Dist: pandas
11
+ Requires-Dist: polars
12
+ Description-Content-Type: text/markdown
13
+
14
+ # mspu
15
+
16
+ My python utils package. It includes some commonly used functions, like `gen_rand_df` and `explode_date_range`.
17
+
18
+ ## How to install `mspu`
19
+
20
+ Using `pip`:
21
+ ```sh
22
+ pip install mspu
23
+ ```
24
+
25
+ Using `uv`:
26
+ ```sh
27
+ uv pip install mspu
28
+ ```
29
+
30
+ ## The document for `mspu`
31
+
32
+ Visit the [document](https://seanslma.github.io/mspu) for more details.
mspu-0.0.1/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # mspu
2
+
3
+ My python utils package. It includes some commonly used functions, like `gen_rand_df` and `explode_date_range`.
4
+
5
+ ## How to install `mspu`
6
+
7
+ Using `pip`:
8
+ ```sh
9
+ pip install mspu
10
+ ```
11
+
12
+ Using `uv`:
13
+ ```sh
14
+ uv pip install mspu
15
+ ```
16
+
17
+ ## The document for `mspu`
18
+
19
+ Visit the [document](https://seanslma.github.io/mspu) for more details.
@@ -0,0 +1,22 @@
1
+ /* Force line break before ALL parameters including the first */
2
+ dt.sig.sig-object em.sig-param::before {
3
+ content: "\A ";
4
+ white-space: pre;
5
+ }
6
+
7
+ /* Ensure commas stay inline */
8
+ dt.sig.sig-object .w {
9
+ display: inline;
10
+ }
11
+
12
+ /* Add comma after last parameter and force line break after it */
13
+ dt.sig.sig-object em.sig-param:last-of-type::after {
14
+ content: ",\A";
15
+ white-space: pre;
16
+ }
17
+
18
+ /* Alternative: target the closing parenthesis directly */
19
+ dt.sig.sig-object span.sig-paren:last-of-type::before {
20
+ content: "\A";
21
+ white-space: pre;
22
+ }
@@ -0,0 +1 @@
1
+ {{ copyright_html }}
@@ -0,0 +1,111 @@
1
+ # -- Path setup --------------------------------------------------------------
2
+ import os
3
+ import sys
4
+ from datetime import datetime
5
+
6
+ # Add the project root to the path so Sphinx can find the 'mspu' package
7
+ sys.path.insert(0, os.path.abspath('../../'))
8
+
9
+ # -- Project information -----------------------------------------------------
10
+ project = 'mspu'
11
+ copyright = '2026, Sean Ma'
12
+ author = 'Sean Ma'
13
+ release = '0.0.1'
14
+
15
+ # -- General configuration ---------------------------------------------------
16
+ extensions = [
17
+ # Core Sphinx extensions
18
+ 'sphinx.ext.autodoc', # To include documentation from docstrings
19
+ 'sphinx.ext.viewcode', # To link to the source code
20
+ 'sphinx.ext.autosummary', # To automatically generate summary tables
21
+ # Additional utility extensions
22
+ # 'sphinx_autodoc_typehints', # To display type hints nicely
23
+ 'numpydoc', # To support NumPy style docstrings
24
+ 'sphinx_design', # For badges, cards, etc.
25
+ 'sphinx.ext.autodoc',
26
+ 'sphinx.ext.napoleon',
27
+ 'sphinx_copybutton', # To add copy buttons to code blocks
28
+ ]
29
+
30
+ # Strip the >>> and ... prompts so copied code is clean
31
+ copybutton_prompt_text = '>>> |\\.\\.\\. '
32
+ copybutton_prompt_is_regexp = True
33
+
34
+ # The suffix(es) of source filenames.
35
+ source_suffix = '.rst'
36
+
37
+ # The master toctree document.
38
+ master_doc = 'index'
39
+
40
+ # Add any paths that contain templates here, relative to this directory.
41
+ templates_path = ['_templates']
42
+
43
+ # List of patterns, relative to source directory, that match files and
44
+ # directories to ignore when looking for source files.
45
+ # This pattern also affects html_static_path and html_extra_path.
46
+ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
47
+
48
+ # -- Options for HTML output -------------------------------------------------
49
+ # The theme to use. This enables the PyData Sphinx Theme.
50
+ html_theme = 'pydata_sphinx_theme'
51
+
52
+ # The theme options
53
+ html_theme_options = {
54
+ 'github_url': 'https://github.com/seanslma/mspu',
55
+ 'secondary_sidebar_items': [], # Disable the secondary sidebar items (page toc)
56
+ }
57
+
58
+ # Add any paths that contain custom static files (such as style sheets) here,
59
+ # relative to this directory. They are copied after the builtin static files,
60
+ # so a file named "default.css" will overwrite the builtin "default.css".
61
+ html_static_path = ['_static']
62
+
63
+ # Custom CSS files
64
+ html_css_files = [
65
+ 'custom.css',
66
+ ]
67
+
68
+ # If true, the rest sources are included in the HTML build as _sources/foo.txt.
69
+ html_copy_source = False
70
+
71
+ # disable default copyright
72
+ html_show_copyright = False
73
+
74
+ # Add back to home link and copyright in the footer
75
+ html_context = {
76
+ 'copyright_html': f'<a href="/" title="Go to Main Home Page">🏠 Back to Home</a><br>Copyright &copy; {datetime.now().year} Sean Ma'
77
+ }
78
+
79
+ # If true, "Created using Sphinx" is shown in the HTML footer.
80
+ html_show_sphinx = True
81
+
82
+ # -- Autodoc configuration ---------------------------------------------------
83
+ # Type hints: show in signature only (not in description)
84
+ # autodoc_typehints = "signature"
85
+
86
+ # Use short format for type hints
87
+ # autodoc_typehints_format = "short"
88
+
89
+ # Preserve the defaults in signatures
90
+ autodoc_preserve_defaults = True
91
+
92
+ # -- Sphinx autodoc typehints configuration ----------------------------------
93
+ # This prevents duplicate parameter documentation in the body
94
+ # typehints_defaults = "comma"
95
+
96
+ # -- Numpydoc configuration ---------------------------------------------------
97
+ # Don't show class members automatically
98
+ numpydoc_show_class_members = False
99
+
100
+ # Don't show type hints in the parameter descriptions since they're in signature
101
+ numpydoc_show_type_hint = False
102
+
103
+ # Mock imports for modules that are not available in the documentation environment
104
+ autodoc_mock_imports = []
105
+
106
+ # Global setup for doctests
107
+ doctest_global_setup = """
108
+ import numpy as np
109
+ import polars as pl
110
+ # anything else needed globally
111
+ """
@@ -0,0 +1,15 @@
1
+ .. _api.data:
2
+
3
+ data
4
+ ======
5
+
6
+ .. currentmodule:: mspu.data
7
+
8
+ Functions
9
+ ~~~~~~~~~
10
+
11
+ .. autosummary::
12
+ :toctree: api/
13
+ :nosignatures:
14
+
15
+ gen_rand_df
@@ -0,0 +1,20 @@
1
+ .. mspu documentation master file
2
+
3
+ mspu API Reference
4
+ ==================
5
+
6
+ .. toctree::
7
+ :maxdepth: 2
8
+ :caption: Contents:
9
+
10
+ mspu
11
+ data
12
+ pandas
13
+ polars
14
+
15
+ Indices and tables
16
+ ==================
17
+
18
+ * :ref:`genindex`
19
+ * :ref:`modindex`
20
+ * :ref:`search`
@@ -0,0 +1,14 @@
1
+ mspu
2
+ ====
3
+
4
+ My python utils package.
5
+
6
+ Submodules
7
+ ----------
8
+
9
+ .. toctree::
10
+ :maxdepth: 1
11
+
12
+ data
13
+ pandas
14
+ polars
@@ -0,0 +1,18 @@
1
+ .. _api.pandas:
2
+
3
+ pandas
4
+ ======
5
+
6
+ .. currentmodule:: mspu.pandas
7
+
8
+ Functions
9
+ ~~~~~~~~~
10
+
11
+ .. autosummary::
12
+ :toctree: api/
13
+ :nosignatures:
14
+
15
+ pd_ht
16
+ df_diffs
17
+ explode_date_range
18
+ pa_mod
@@ -0,0 +1,20 @@
1
+ .. _api.polars:
2
+
3
+ polars
4
+ ======
5
+
6
+ .. currentmodule:: mspu.polars
7
+
8
+ Functions
9
+ ~~~~~~~~~
10
+
11
+ .. autosummary::
12
+ :toctree: api/
13
+ :nosignatures:
14
+
15
+ pl_ht
16
+ inf_count
17
+ nan_count
18
+ nul_count
19
+ lowercase_polars_df
20
+ to_float32_polars_df
@@ -0,0 +1,19 @@
1
+ #!/bin/bash
2
+
3
+ # Step 1: Clean any old builds
4
+ rm -rf _build/html/
5
+
6
+ # Step 2: Change to the docs directory
7
+ cd docs
8
+
9
+ # Step 3: Build the MkDocs guide first (creates the '_build/html' folder)
10
+ mkdocs build --site-dir ../_build/html
11
+
12
+ # Step 4: Build Sphinx directly into the compiled MkDocs '_build/api' folder
13
+ sphinx-build -b html api ../_build/html/api
14
+
15
+ # Step 5: Return to the root directory
16
+ cd ..
17
+
18
+ # Copy to the final build directory
19
+ cp -a ./_build/html/. ../seanslma.github.io/mspu/
@@ -0,0 +1,13 @@
1
+ # Welcome to mspu
2
+
3
+ mspu is a Python package designed for providing some commonly used functions.
4
+
5
+ This user guide is intended to walk you through getting started, providing examples, and explaining core concepts.
6
+
7
+ ## Structure
8
+
9
+ User Guide (You Are Here): Conceptual overviews, installation steps, and tutorials.
10
+
11
+ API Reference (External Link): Detailed, auto-generated documentation for every function and class (powered by Sphinx).
12
+
13
+ Check out the Tutorial to see how mspu works!
@@ -0,0 +1,117 @@
1
+ # Quick Tutorial: Using explode_date_range
2
+
3
+ This tutorial shows you how to use the `mspu.pandas.explode_date_range` function.
4
+
5
+ ## 1. Install the package
6
+
7
+ First, ensure you have the `mspu` package installed:
8
+ ```sh
9
+ pip install mspu
10
+ ```
11
+
12
+ ## 2. Displaying dataframe
13
+
14
+ When you print a pandas DataFrame, sometimes the default settings are not good enough so you need to adjust the display width, number of rows and columns. Here we provide a simple function for your convinence.
15
+
16
+ ```py
17
+ import pandas as pd
18
+ from mspu.pandas import pd_ht
19
+ pd.DataFrame.ht = pd_ht
20
+ df = pd.DataFrame({
21
+ 'foo': [1.12345, 2.98765, 3.14159],
22
+ 'bar': [7, 8, 9],
23
+ 'ham': ['x', 'y', 'z'],
24
+ })
25
+ df.ht(n=1, c=2, r=3)
26
+ ```
27
+
28
+ The output:
29
+ ```
30
+ shape: (3, 3)
31
+ foo ... ham
32
+ 0 1.123 ... x
33
+ 2 3.142 ... z
34
+ ```
35
+
36
+ ## 3. Creating random data
37
+
38
+ The `gen_rand_df` can be used to create random data in a pandas DataFrame for testing.
39
+
40
+ In this example, we'll create a dataframe with one string column, two timestamp columns, one integer column, and two float columns, for one year with a resolution of one minute.
41
+
42
+ ```py
43
+ from mspu.data import gen_rand_df
44
+
45
+ df = gen_rand_df(
46
+ nrow=100,
47
+ str_cols=1,
48
+ ts_cols={
49
+ 'count': 2,
50
+ 'name': ['start_date', 'end_date'],
51
+ 'start_date': ['2020-01-01', '2023-01-01'],
52
+ 'end_date': ['2023-01-01', '2025-01-01'],
53
+ 'freq': 'MS',
54
+ 'random': True,
55
+ },
56
+ int_cols=1,
57
+ float_cols=2,
58
+ )
59
+ df.ht(1, c=-1, r=2)
60
+ ```
61
+ Outputs:
62
+ ```
63
+ shape: (100, 6)
64
+ s1 start_date end_date i1 f1 f2
65
+ 0 IZD8v 2022-10-01 2023-12-01 0 1.43 1.78
66
+ 99 y5HeH 2020-12-01 2024-07-01 0 1.13 1.11
67
+
68
+ ```
69
+
70
+ ## 4. Using the `explode_date_range` function
71
+
72
+ This function can be used to explode two datetime columns in a pandas DataFrame to a list of datetime values as a new column. It's about `30x` faster than using the pandas `df.explode` function.
73
+ ```py
74
+ import time
75
+ from mspu.pandas import explode_date_range
76
+
77
+ # assume we already created the df in the previous section
78
+ t0 = time.time()
79
+ df_exploded = explode_date_range(
80
+ df=df,
81
+ start_date_col='start_date',
82
+ end_date_col='end_date',
83
+ date_col='ts',
84
+ freq='30min',
85
+ inclusive='left',
86
+ drop_date_cols=True,
87
+ )
88
+ print(f'mspu explode time: {time.time() - t0:.3f} seconds')
89
+ df_exploded.ht(2,r=2)
90
+ ```
91
+ Outputs:
92
+ ```
93
+ mspu explode time: 0.235 seconds
94
+ shape: (4415424, 5)
95
+ s1 i1 f1 f2 ts
96
+ 0 IZD8v 0 1.43 1.78 2022-10-01 00:00:00
97
+ 1 IZD8v 0 1.43 1.78 2022-10-01 00:30:00
98
+ 4415422 y5HeH 0 1.13 1.11 2024-06-30 23:00:00
99
+ 4415423 y5HeH 0 1.13 1.11 2024-06-30 23:30:00
100
+ ```
101
+
102
+ Now let's use `explode` from pandas:
103
+ ```py
104
+ t1 = time.time()
105
+ df['ts'] = [
106
+ pd.date_range(start, end, freq='30min', inclusive='left')
107
+ for start, end in zip(df['start_date'].values, df['end_date'].values)
108
+ ]
109
+ df_exploded_pandas = df.drop(columns=['start_date', 'end_date']).explode('ts')
110
+ print(f'pandas explode time: {time.time() - t1:.3f} seconds')
111
+ print(df_exploded.equals(df_exploded_pandas.reset_index(drop=True)))
112
+ ```
113
+ Outputs:
114
+ ```
115
+ pandas explode time: 4.117 seconds
116
+ True
117
+ ```
@@ -0,0 +1,50 @@
1
+ import re
2
+ import datetime
3
+
4
+
5
+ def on_page_markdown(markdown, **kwargs):
6
+ """
7
+ Add blank line before lists that don't have one.
8
+ Matches: text\n- item (no blank line)
9
+ Replaces with: text\n\n- item (adds blank line)
10
+ """
11
+ # Pattern: non-empty line followed by newline and list item
12
+ # Negative lookbehind ensures previous line isn't already blank
13
+ pattern = r'(?<!\n)\n([-*+]\s)'
14
+ replacement = r'\n\n\1'
15
+
16
+ return re.sub(pattern, replacement, markdown)
17
+
18
+
19
+ def on_config(config):
20
+ # Replace {year} once globally
21
+ now = datetime.datetime.now()
22
+ # date = now.strftime('%-d %b %Y')
23
+ copyright = config.get('copyright', '')
24
+ config['raw_copyright'] = copyright.replace('{year}', str(now.year))
25
+
26
+ return config
27
+
28
+
29
+ def on_page_context(context, page, config, nav):
30
+ # Determine which date to use
31
+ if page.is_homepage:
32
+ display_date = datetime.datetime.now().strftime('%-d %b %Y')
33
+ else:
34
+ # Try to get the Git date from plugin metadata
35
+ display_date = (
36
+ page.meta.get('git_revision_date_localized')
37
+ or page.meta.get('revision_date')
38
+ or datetime.datetime.now().strftime('%-d %b %Y')
39
+ )
40
+ updated_at = f'Last updated on {display_date}'
41
+
42
+ # Remove it from metadata to avoid auto creating `last updated` field
43
+ page.meta.pop('git_revision_date_localized', None)
44
+
45
+ # Build a per-page footer WITHOUT mutating the global config
46
+ # Use context['copyright'] instead of config['copyright']
47
+ copyright = config['raw_copyright']
48
+ context['config']['copyright'] = f'{copyright}<br>{updated_at}'
49
+
50
+ return context