Prepare ThinkDSP for PyPI packaging#134
Prepare ThinkDSP for PyPI packaging#134hoppa1231 wants to merge 6 commits intoAllenDowney:masterfrom
Conversation
- Implement tests for spectrum generation with both even and odd lengths. - Add tests for ComplexSinusoid, Chirp, ExpoChirp, and wave addition. - Include tests for DCT and impulse signal generation. - Ensure numerical accuracy with assertions for expected results.
Summary
MotivationI wanted to make ThinkDSP installable as a standard Python package from PyPI. Changes
Testing
Notes / Potential Concerns
|
|
This looks really good, thank you! I have held off on making thinkdsp an installable package because (1) it's not necessary for readers, and (2) many readers have problems installing packages. So I don't want to encourage readers to go down this road. But it is nice to give people the option, so I am inclined to merge this PR and put the package on PyPI. In that case we can use the name thinkdsp without the suffix, and drop the language about the distribution being unofficial (also still crediting you as maintainer). What do you think? |
There was a problem hiding this comment.
Pull request overview
This pull request prepares the ThinkDSP codebase for PyPI packaging by restructuring the project into a proper Python package with a src/ layout, adding packaging configuration, tests, CI/CD workflows, and license files.
Changes:
- Reorganized code into a
src/thinkdsp/package structure with proper Python packaging setup - Added pyproject.toml with Poetry configuration for PyPI publishing as "thinkdsp-kim"
- Created GitHub Actions workflow for automated PyPI publishing and added comprehensive .gitignore
- Updated code to use modern NumPy methods (tobytes/frombuffer) and improved IPython Audio import handling
- Added MIT License file, attribution section in README, and pytest-based test suite
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| pyproject.toml | Configures Poetry packaging with metadata, dependencies, and build system for PyPI distribution |
| src/thinkdsp/init.py | Main package module with DSP utilities, updated with modern NumPy methods |
| tests/test_thinkdsp.py | Unit tests for core DSP functionality (Wave, Spectrum, Signal classes) |
| code/thinkdsp.py | Updated original code file with deprecation fixes (tobytes, frombuffer, Audio import) |
| README.md | Added attribution section explaining this is a packaging fork maintained by hoppa1231 |
| LICENSE | Added MIT License file with copyright information for Allen B. Downey |
| .gitignore | Expanded to include Python, Poetry, and packaging-related ignore patterns |
| .github/workflows/publish.yml | GitHub Actions workflow for building and publishing to PyPI on version tags |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| pandas = "^1.1.4" | ||
| scipy = "^1.5.4" | ||
| python = ">=3.9,<4.0" | ||
| numpy = ">=1.22.4,<3.0" |
There was a problem hiding this comment.
The numpy version constraint ">=1.22.4,<3.0" is reasonable, but NumPy 1.22.4 was released in 2022 and requires Python 3.8+. Since the minimum Python version is set to 3.9, consider aligning the numpy minimum version with what's typically available for Python 3.9 environments. NumPy 1.22 dropped support for deprecated functions that might be used in older code. Verify that all numpy usage in the codebase is compatible with numpy 1.22+, particularly the np.fromstring usage (deprecated in favor of np.frombuffer).
| numpy = ">=1.22.4,<3.0" | |
| numpy = ">=1.20,<3.0" |
| scipy = ">=1.13.0,<2.0" | ||
| matplotlib = ">=3.8.0,<4.0" | ||
| jupyter = { version = "^1.0.0", optional = true } | ||
| pandas = { version = "^1.1.4", optional = true } |
There was a problem hiding this comment.
The pandas version constraint uses "^1.1.4" which means ">=1.1.4,<2.0.0". However, pandas 1.1.4 was released in 2020 and is quite old. This package may not be compatible with pandas 2.x which was released in April 2023. Consider testing compatibility with pandas 2.x and updating the constraint to ">=1.1.4,<3.0" if compatible, or explicitly documenting the pandas 2.x incompatibility.
| pandas = { version = "^1.1.4", optional = true } | |
| pandas = { version = ">=1.1.4,<3.0", optional = true } |
| """This file contains code for use with "Think Stats", | ||
| by Allen B. Downey, available from greenteapress.com | ||
|
|
||
| Copyright 2014 Allen B. Downey | ||
| License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html | ||
| """ |
There was a problem hiding this comment.
The test file header incorrectly references "Think Stats" instead of "Think DSP" and mentions GNU GPLv3 license while the LICENSE file and pyproject.toml specify MIT License. This is inconsistent with the actual source code which uses MIT License and references "Think DSP".
| scipy = "^1.5.4" | ||
| python = ">=3.9,<4.0" | ||
| numpy = ">=1.22.4,<3.0" | ||
| scipy = ">=1.13.0,<2.0" |
There was a problem hiding this comment.
The scipy version constraint ">=1.13.0,<2.0" is very restrictive and may cause compatibility issues. SciPy 1.13.0 was released in May 2024, which means users with older Python environments (even Python 3.9-3.11 that are supported) may not be able to install this package if they have older scipy versions. Consider using a more permissive constraint like ">=1.5.4,<2.0" to match the minimum Python 3.9 requirement, or document why scipy 1.13.0 is specifically required.
| scipy = ">=1.13.0,<2.0" | |
| scipy = ">=1.5.4,<2.0" |
| raise ValueError("sampwidth %d unknown" % sampwidth) | ||
|
|
||
| if sampwidth == 3: | ||
| xs = np.fromstring(z_str, dtype=np.int8).astype(np.int32) |
There was a problem hiding this comment.
The code uses np.fromstring which was deprecated in NumPy 1.14 and removed in NumPy 1.24. Since the pyproject.toml specifies numpy>=1.22.4, this will break with NumPy 1.24+. The code should be updated to use np.frombuffer instead, similar to line 113.
| xs = np.fromstring(z_str, dtype=np.int8).astype(np.int32) | |
| xs = np.frombuffer(z_str, dtype=np.int8).astype(np.int32) |
| ## Attribution | ||
|
|
||
| This repository packages the `thinkdsp` code from *Think DSP* by Allen B. Downey. | ||
| Original code and copyright remain with the author under the MIT License. | ||
| This packaging fork is maintained by `hoppa1231` and is not affiliated with the | ||
| original author or publisher. | ||
|
|
There was a problem hiding this comment.
The README does not include installation instructions for the PyPI package (thinkdsp-kim). Consider adding a section explaining how to install the package using pip, such as "pip install thinkdsp-kim" or "pip install thinkdsp-kim[notebooks]" for the optional dependencies. This would help users understand how to use the packaged version.
| from __future__ import print_function, division | ||
|
|
There was a problem hiding this comment.
The test file includes "from future import print_function, division" which is only needed for Python 2 compatibility. Since pyproject.toml specifies python = ">=3.9,<4.0", this import is unnecessary and should be removed as it's redundant in Python 3.9+.
| from __future__ import print_function, division |
| return ys | ||
|
|
||
|
|
||
| class PinkNoise(Noise): |
There was a problem hiding this comment.
This class does not call Noise.init during initialization. (PinkNoise.init may be missing a call to a base class init)
| print(cos_cov, sin_cov, mag((cos_cov, sin_cov))) | ||
| return | ||
|
|
||
| wfile = WavFileWriter() |
There was a problem hiding this comment.
This statement is unreachable.
|
|
||
| __radd__ = __add__ | ||
|
|
||
| def __or__(self, other): |
There was a problem hiding this comment.
This method raises ValueError - should raise an ArithmeticError or return NotImplemented instead.
|
Thanks, AllenDowney — I agree with your reasoning. I’m happy to proceed with an official PyPI release. Publishing as If you’re good with that, I’ll update this PR to:
I’ll also address the Copilot review items in the same update:
Let me know if you’d prefer dropping the PyPI publish workflow from this PR and handling publishing separately. |
|
@hoppa1231 I'm working on getting the If that gets resolved, we can pick it up from there. So hold off for now, thanks! |
No description provided.