From ea55e3b10a8455f1c51eff4bc0661b9876b5ea79 Mon Sep 17 00:00:00 2001 From: Bomme <13520622+Bomme@users.noreply.github.com> Date: Sun, 2 Nov 2025 21:12:14 +0100 Subject: [PATCH 1/6] switch to uv to build project - Updated pyproject.toml with project metadata, dependencies, and build system configuration. - Removed setup.py as it is no longer needed with the new configuration. - Modified GitHub Actions workflow to support multiple Python versions and updated installation steps. --- .github/workflows/python-smoke-test.yml | 22 ++- .gitignore | 195 ++++++++++++++++++++++++ .python-version | 1 + pyproject.toml | 37 +++++ setup.py | 9 -- 5 files changed, 248 insertions(+), 16 deletions(-) create mode 100644 .python-version delete mode 100644 setup.py diff --git a/.github/workflows/python-smoke-test.yml b/.github/workflows/python-smoke-test.yml index a3da3e2..3d1213e 100644 --- a/.github/workflows/python-smoke-test.yml +++ b/.github/workflows/python-smoke-test.yml @@ -13,19 +13,27 @@ jobs: build: runs-on: ubuntu-latest + + strategy: + max-parallel: 1 + fail-fast: true + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v3 - - name: Set up Python 3.10 - uses: actions/setup-python@v4 + - name: Install uv + uses: astral-sh/setup-uv@v5 with: - python-version: "3.10" + version: "latest" + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -e . + run: uv sync - name: Run smoke test env: FREESOUND_API_KEY: ${{ secrets.FREESOUND_API_KEY }} run: | - python examples.py + uv run python examples.py diff --git a/.gitignore b/.gitignore index 17a8d54..f110c92 100755 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,198 @@ build *.pyc *.bak + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# uv +uv.lock + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ + + +tmp/ diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..24ee5b1 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/pyproject.toml b/pyproject.toml index 5bf0d9b..7486065 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,40 @@ +[project] +name = "freesound" +version = "1.1" +description = "A Python client for the Freesound APIv2" +readme = "Readme.md" +requires-python = ">=3.7" +license = {file = "COPYING.txt"} +dependencies = [ + "requests>=2.27,<3.0", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Multimedia :: Sound/Audio", +] + +[project.urls] +Homepage = "https://github.com/MTG/freesound-python" +Repository = "https://github.com/MTG/freesound-python.git" + + +[build-system] +requires = ["hatchling >= 1.26"] +build-backend = "hatchling.build" + +[tool.hatch.build] +include = ["freesound.py"] + [tool.yapf] based_on_style = "google" spaces_before_comment = 4 diff --git a/setup.py b/setup.py deleted file mode 100644 index b2f6273..0000000 --- a/setup.py +++ /dev/null @@ -1,9 +0,0 @@ -from distutils.core import setup - -setup( - name="freesound-python", - version="1.1", - py_modules=["freesound"], - install_requires=["requests<3.0,>2.27"], - python_requires=">=3.6", -) From d38a245a4b3dbb8e17005bbbf3f3eaddfce5d468 Mon Sep 17 00:00:00 2001 From: Bomme <13520622+Bomme@users.noreply.github.com> Date: Sun, 2 Nov 2025 21:12:45 +0100 Subject: [PATCH 2/6] Update installation instructions in Readme.md and add GitHub Actions workflow for publishing to PyPI --- .github/workflows/publish.yml | 48 +++++++++++++++++++++++++++++++++++ Readme.md | 15 ++++++++--- 2 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..f00fb4c --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,48 @@ +name: Publish to PyPI + +on: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v5 + + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + version: "latest" + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.x" + + - name: Build package + run: uv build + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: python-package-distributions + path: dist/ + + publish: + needs: build + runs-on: ubuntu-latest + environment: pypi + permissions: + id-token: write # Required for trusted publishing + + steps: + - name: Download artifacts + uses: actions/download-artifact@v3 + with: + name: python-package-distributions + path: dist/ + + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/Readme.md b/Readme.md index 976f3c6..f439e95 100644 --- a/Readme.md +++ b/Readme.md @@ -29,18 +29,25 @@ for sound in results: ``` ## Installation -1) clone or download -2) run: +The easiest way to install is using pip: + ``` -python setup.py install +pip install freesound ``` -Alternatively you should also be able to install directly from GitHub with: +Alternatively, you can install directly from GitHub: + ``` pip install git+https://github.com/MTG/freesound-python ``` +Or clone the repository and install manually: + +``` +python -m pip install . +``` + ## Advanced usage ### Modifying the requests' session: From bcd7247ee2b3ea2384ff78b0a718456480a23a50 Mon Sep 17 00:00:00 2001 From: Bomme <13520622+Bomme@users.noreply.github.com> Date: Sun, 2 Nov 2025 21:22:53 +0100 Subject: [PATCH 3/6] Update GitHub Actions workflow to use Ubuntu 22.04 for smoke tests python 3.7 is no longer supported in ubuntu-latest --- .github/workflows/python-smoke-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-smoke-test.yml b/.github/workflows/python-smoke-test.yml index 3d1213e..c484b5a 100644 --- a/.github/workflows/python-smoke-test.yml +++ b/.github/workflows/python-smoke-test.yml @@ -12,7 +12,7 @@ permissions: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: max-parallel: 1 From 30e6dfd2ce2c24e45ca39c227e15ac4cfa14cf03 Mon Sep 17 00:00:00 2001 From: Benno Weck <13520622+Bomme@users.noreply.github.com> Date: Thu, 22 Oct 2026 20:21:59 +0200 Subject: [PATCH 4/6] Prepare packaging for release - Require Python >=3.9 and update classifiers (3.9-3.14) - Use SPDX license expression (MIT) with license-files; require hatchling >=1.27 - Add Issues/Documentation URLs and a dev dependency group - publish workflow: bump retired upload/download-artifact@v3 to v5 and drop redundant setup-python step - smoke test workflow: test 3.9-3.14 on ubuntu-latest using setup-uv --- .github/workflows/publish.yml | 11 ++--------- .github/workflows/python-smoke-test.yml | 14 +++++--------- pyproject.toml | 17 +++++++++++------ 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f00fb4c..cc23b05 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,19 +13,12 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v7 - with: - version: "latest" - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.x" - name: Build package run: uv build - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v5 with: name: python-package-distributions path: dist/ @@ -39,7 +32,7 @@ jobs: steps: - name: Download artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v5 with: name: python-package-distributions path: dist/ diff --git a/.github/workflows/python-smoke-test.yml b/.github/workflows/python-smoke-test.yml index c484b5a..57af7b5 100644 --- a/.github/workflows/python-smoke-test.yml +++ b/.github/workflows/python-smoke-test.yml @@ -12,22 +12,18 @@ permissions: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest strategy: max-parallel: 1 fail-fast: true matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v3 - - name: Install uv - uses: astral-sh/setup-uv@v5 - with: - version: "latest" - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + - uses: actions/checkout@v5 + - name: Install uv and set up Python ${{ matrix.python-version }} + uses: astral-sh/setup-uv@v7 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/pyproject.toml b/pyproject.toml index 7486065..d071598 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,33 +3,38 @@ name = "freesound" version = "1.1" description = "A Python client for the Freesound APIv2" readme = "Readme.md" -requires-python = ">=3.7" -license = {file = "COPYING.txt"} +requires-python = ">=3.9" +license = "MIT" +license-files = ["COPYING.txt"] dependencies = [ "requests>=2.27,<3.0", ] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Multimedia :: Sound/Audio", ] [project.urls] Homepage = "https://github.com/MTG/freesound-python" Repository = "https://github.com/MTG/freesound-python.git" +Issues = "https://github.com/MTG/freesound-python/issues" +Documentation = "https://freesound.org/docs/api/" +[dependency-groups] +dev = [ + "yapf", +] [build-system] -requires = ["hatchling >= 1.26"] +requires = ["hatchling >= 1.27"] build-backend = "hatchling.build" [tool.hatch.build] From 8508c7f7a62701f58e6d845f86a606aba057a238 Mon Sep 17 00:00:00 2001 From: Benno Weck <13520622+Bomme@users.noreply.github.com> Date: Thu, 22 Oct 2026 20:22:11 +0200 Subject: [PATCH 5/6] Apply yapf formatting --- examples.py | 42 ++++++++++++++++++++++++------------------ freesound.py | 2 +- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/examples.py b/examples.py index f4bd961..8581062 100644 --- a/examples.py +++ b/examples.py @@ -25,12 +25,11 @@ # Get sound info example specifying some request parameters print("Sound info specifying some request parameters:") print("-----------") -sound = freesound_client.get_sound( - 6, fields="id,name,username,duration,spectral_centroid") +sound = freesound_client.get_sound(6, fields="id,name,username,duration,spectral_centroid") print("Getting sound:", sound.name) print("Username:", sound.username) print("Duration:", str(sound.duration), "(s)") -print("Spectral centroid:",str(sound.spectral_centroid), "(Hz)") +print("Spectral centroid:", str(sound.spectral_centroid), "(Hz)") print() # Get sound analysis example @@ -80,15 +79,16 @@ print("Num results:", results_pager.count) for sound in results_pager: - print("\t-", sound.name, "by", sound.username, "with spectral centroid of", sound.spectral_centroid, "Hz and pitch of", sound.pitch, "Hz") + print( + "\t-", sound.name, "by", sound.username, "with spectral centroid of", sound.spectral_centroid, + "Hz and pitch of", sound.pitch, "Hz" + ) print() # We can use the search endpoint for a similarity search which also filters results print("Searching for similar sounds and filtering by a descriptor value:") print("---------------") -results_pager = freesound_client.search( - page_size=10, fields="name,username", similar_to=6, filter="pitch:[110 TO 180]" -) +results_pager = freesound_client.search(page_size=10, fields="name,username", similar_to=6, filter="pitch:[110 TO 180]") for similar_sound in results_pager: print("\t-", similar_sound.name, "by", similar_sound.username) print() @@ -97,7 +97,20 @@ # Note that "similarity_space" must match with the similarity space used to extract the target vector print("Searching for sounds similar to a target vector:") print("---------------") -target_vector = [0.84835537,-0.06019006,0.35139768,-0.01221892,-0.23172645,-0.03798686,-0.03869437,0.02199453,-0.10143687,-0.03342770,0.05464298,-0.02654354,0.05424048,0.04912830,0.01449411,-0.02995046,0.04584143,0.03731462,0.06914231,-0.00702387,-0.02202889,0.01644059,-0.00153376,0.11042101,0.05432773,0.05736105,-0.03779107,-0.00909068,-0.08996461,-0.04300615,0.05610843,0.02214170,-0.02155820,0.05158299,-0.00717155,-0.04345755,-0.00519616,0.02887811,-0.02205723,0.01658933,0.02485796,-0.06228176,0.03574570,-0.04556302,-0.00497004,0.00300936,-0.01974736,-0.01391953,-0.02898939,0.01041939,-0.02836645,0.00853050,-0.03129587,0.00454572,0.00898315,-0.01371797,-0.00918297,-0.01049032,0.02800968,-0.04248178,0.02648444,-0.01034762,0.02105908,-0.01137279,0.02845560,-0.04284714,0.00797986,0.00973879,-0.00850114,-0.01093731,-0.00629640,-0.01862817,0.00829806,0.01137537,0.02601988,0.03015542,-0.01091145,0.00547907,-0.00426657,0.01001693,0.00793383,0.00082211,-0.02848534,-0.00823537,0.01392606,-0.02012341,-0.00788319,0.02797560,-0.01470957,-0.01917517,-0.01177181,0.00952904,-0.00223396,-0.01586017,-0.00566903,0.01150901,-0.00361810,-0.00257769,-0.01509761,0.00552032] +target_vector = [ + 0.84835537, -0.06019006, 0.35139768, -0.01221892, -0.23172645, -0.03798686, -0.03869437, 0.02199453, -0.10143687, + -0.03342770, 0.05464298, -0.02654354, 0.05424048, 0.04912830, 0.01449411, -0.02995046, 0.04584143, 0.03731462, + 0.06914231, -0.00702387, -0.02202889, 0.01644059, -0.00153376, 0.11042101, 0.05432773, 0.05736105, -0.03779107, + -0.00909068, -0.08996461, -0.04300615, 0.05610843, 0.02214170, -0.02155820, 0.05158299, -0.00717155, -0.04345755, + -0.00519616, 0.02887811, -0.02205723, 0.01658933, 0.02485796, -0.06228176, 0.03574570, -0.04556302, -0.00497004, + 0.00300936, -0.01974736, -0.01391953, -0.02898939, 0.01041939, -0.02836645, 0.00853050, -0.03129587, 0.00454572, + 0.00898315, -0.01371797, -0.00918297, -0.01049032, 0.02800968, -0.04248178, 0.02648444, -0.01034762, 0.02105908, + -0.01137279, 0.02845560, -0.04284714, 0.00797986, 0.00973879, -0.00850114, -0.01093731, -0.00629640, -0.01862817, + 0.00829806, 0.01137537, 0.02601988, 0.03015542, -0.01091145, 0.00547907, -0.00426657, 0.01001693, 0.00793383, + 0.00082211, -0.02848534, -0.00823537, 0.01392606, -0.02012341, -0.00788319, 0.02797560, -0.01470957, -0.01917517, + -0.01177181, 0.00952904, -0.00223396, -0.01586017, -0.00566903, 0.01150901, -0.00361810, -0.00257769, -0.01509761, + 0.00552032 +] results_pager = freesound_client.search( page_size=10, fields="name,username", similar_to=target_vector, similarity_space="freesound_classic" ) @@ -108,10 +121,7 @@ # Search sounds and sort them by distance to a given audio descriptors target print("Sort sounds by distance to audio descriptors target:") print("---------------") -results_pager = freesound_client.search( - filter="pitch_var:[* TO 20]", - sort='pitch_salience:1.0,pitch:440' -) +results_pager = freesound_client.search(filter="pitch_var:[* TO 20]", sort='pitch_salience:1.0,pitch:440') for sound in results_pager: print("\t-", sound.name, "by", sound.username, "distance:", sound.distance_to_target) @@ -138,9 +148,7 @@ print("-----------") user = freesound_client.get_user("Headphaze") print("User name:", user.username) -results_pager = user.get_sounds( - page_size=10, fields="name,username,samplerate,duration" -) +results_pager = user.get_sounds(page_size=10, fields="name,username,samplerate,duration") print("Num results:", results_pager.count) print("\t----- PAGE 1 -----") @@ -179,9 +187,7 @@ print("-----------") pack = freesound_client.get_pack(3524) print("Pack name:", pack.name) -results_pager = pack.get_sounds( - page_size=5, fields="id,name,username,duration,spectral_flatness" -) +results_pager = pack.get_sounds(page_size=5, fields="id,name,username,duration,spectral_flatness") print("Num results:", results_pager.count) print("\t----- PAGE 1 -----") for sound in results_pager: diff --git a/freesound.py b/freesound.py index 17eace5..e39d0bb 100644 --- a/freesound.py +++ b/freesound.py @@ -123,7 +123,7 @@ def search(self, **params): vector = params['similar_to'] vector_str = ','.join(['{0:.5f}'.format(v) for v in vector]) params['similar_to'] = '[' + vector_str + ']' - + uri = URIS.uri(URIS.SEARCH) return FSRequest.request(uri, params, self, Pager) From fa59e1625e961934f0de0e41f19e8fa8078fe83c Mon Sep 17 00:00:00 2001 From: Benno Weck <13520622+Bomme@users.noreply.github.com> Date: Thu, 22 Oct 2026 20:36:10 +0200 Subject: [PATCH 6/6] Space out smoke test runs to respect the API rate limit Run examples.py live on every supported Python (3.9-3.14), one version at a time with a 30s pause before each run, to stay under Freesound's throttling (60 requests/minute). Also check that the package imports and builds in each job. --- .github/workflows/python-smoke-test.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python-smoke-test.yml b/.github/workflows/python-smoke-test.yml index 57af7b5..b89ec84 100644 --- a/.github/workflows/python-smoke-test.yml +++ b/.github/workflows/python-smoke-test.yml @@ -10,13 +10,15 @@ permissions: contents: read jobs: - build: - + # Live smoke test against the Freesound API on every supported Python version. + # The API is rate limited (60 requests/minute, 2000/day per key, see + # https://freesound.org/docs/api/) and one run of examples.py makes ~20 requests, + # so the runs are serialized and spaced out. + smoke-test: runs-on: ubuntu-latest - + strategy: max-parallel: 1 - fail-fast: true matrix: python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] @@ -28,6 +30,12 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: uv sync + - name: Check the package imports and builds + run: | + uv run python -c "import freesound" + uv build + - name: Wait to stay under the API rate limit + run: sleep 30 - name: Run smoke test env: FREESOUND_API_KEY: ${{ secrets.FREESOUND_API_KEY }}