Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .flake8

This file was deleted.

1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ examples/example3.wav filter=lfs diff=lfs merge=lfs -text
examples/example4.wav filter=lfs diff=lfs merge=lfs -text
examples/example1.wav filter=lfs diff=lfs merge=lfs -text
examples/example2.wav filter=lfs diff=lfs merge=lfs -text
batbot/classifier/models/onnx/batbot.mobilenet.9dc57ea3.onnx filter=lfs diff=lfs merge=lfs -text
143 changes: 59 additions & 84 deletions .github/workflows/python-publish.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Wheel
name: Python distributions

on:
pull_request:
Expand All @@ -9,123 +9,98 @@ on:
- main
tags:
- v*
schedule:
- cron: '0 16 * * *' # Every day at 16:00 UTC (~09:00 PT)

jobs:
build_wheels:
name: Build on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
python-version: [3.12]

steps:
- name: Checkout code
uses: nschloe/action-cached-lfs-checkout@v1.2.3
with:
exclude: "examples/example[2-4].wav"

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Build wheel
run: |
pip install --upgrade pip
pip install build
python -m build --wheel --outdir dist/ .

- uses: actions/upload-artifact@v6
with:
name: artifact-wheel-${{ matrix.os }}-${{ matrix.python-version }}
path: ./dist/*.whl

build_sdist:
name: Build source distribution
build:
name: Build wheel and source distribution
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: nschloe/action-cached-lfs-checkout@v1.2.3
with:
exclude: "examples/example[2-4].wav"

- name: Set up Python 3.12
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
python-version: '3.11'
cache: pip

- name: Build sdist
- name: Build and validate distributions
run: |
pip install --upgrade pip
pip install build
python -m build --sdist --outdir dist/ .
python -m pip install --upgrade pip
python -m pip install build twine
python -m build --outdir dist/ .
python -m twine check dist/*

- uses: actions/upload-artifact@v6
- name: Upload distributions
uses: actions/upload-artifact@v6
with:
name: artifact-sdist
path: ./dist/*.tar.gz
name: python-distributions
path: dist/
if-no-files-found: error

test_wheel:
needs: [build_wheels, build_sdist]
test-wheel:
name: Test the installed wheel and bundled model
needs: build
runs-on: ubuntu-latest

# test wheel
if: github.event_name == 'push'
steps:
- name: Set up Python 3.12
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
python-version: '3.11'
cache: pip

- uses: actions/download-artifact@v7
- name: Download distributions
uses: actions/download-artifact@v7
with:
path: artifact
name: python-distributions
path: dist

- name: Install wheel
run: |
pip install --upgrade pip
pip install wheel
find .
mkdir dist
cp artifact/*-ubuntu-*/*.whl dist/
cp artifact/*/*.tar.gz dist/
pip install dist/*.whl
python -m pip install --upgrade pip
python -m pip install dist/*.whl

- name: Test module
- name: Smoke test wheel outside the checkout
working-directory: ${{ runner.temp }}
run: |
python -c "import batbot;"

# - name: Test CLI
# run: |
# batbot example

upload_pypi:
needs: [test_wheel]
runs-on: ubuntu-latest
# upload to PyPI on every tag starting with 'v'
python -I -c "import batbot; assert batbot.__version__"
batbot --help
python -I - <<'PY'
import tempfile
from pathlib import Path

import cv2
import numpy as np

from batbot import classifier

with tempfile.TemporaryDirectory() as directory:
image = Path(directory) / 'smoke.png'
cv2.imwrite(str(image), np.zeros((300, 700, 3), dtype=np.uint8))
result = classifier.Classifier().classify(image)[0]
assert result['label'] in classifier.CLASSES
assert len(result['scores']) == len(classifier.CLASSES)
PY

publish:
name: Publish to PyPI
needs: test-wheel
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v')
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/batbot
permissions:
id-token: write
contents: read
steps:
- uses: actions/download-artifact@v7
- name: Download distributions
uses: actions/download-artifact@v7
with:
path: artifact
name: python-distributions
path: dist

- name: Install wheel
run: |
find .
mkdir dist
cp artifact/*-ubuntu-*/*.whl dist/
cp artifact/*/*.tar.gz dist/

- name: Publish package distributions to PyPI
- name: Publish distributions with trusted publishing
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.BATBOT_PYPI_TOKEN }}
28 changes: 12 additions & 16 deletions .github/workflows/testing.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
# This workflow will install Python dependencies, run tests and lint with multiple versions of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Testing

on: push
on:
push:
pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.9', '3.10', '3.11', '3.12']
python-version: ['3.11', '3.12', '3.13', '3.14']

env:
OS: ubuntu-latest
PYTHON: ${{ matrix.python-version }}

steps:
# Checkout and env setup
- name: Checkout code
uses: nschloe/action-cached-lfs-checkout@v1.2.3
with:
Expand All @@ -28,25 +28,21 @@ jobs:
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
cache: pip

- name: Install dependencies
- name: Install project and test tools
run: |
python -m pip install --upgrade pip
pip install -r requirements/runtime.txt
pip install -r requirements/optional.txt
pip install -e .
python -m pip install -e ".[test]" pre-commit

- name: Check with pre-commit
run: |
SKIP=hadolint pre-commit
SKIP=hadolint pre-commit run --all-files
run: SKIP=hadolint pre-commit run --all-files

- name: Run tests and coverage
run: |
set -ex
pytest --cov=batbot --cov-append --cov-report=xml --random-order-seed=1
run: pytest --cov-report=xml --random-order-seed=1

- name: Upload coverage to Codecov
if: matrix.python-version == '3.11'
continue-on-error: true
uses: codecov/codecov-action@v5
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ example*.json
.vscode/*

assets/*.key
assets/*.png
22 changes: 11 additions & 11 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,46 @@
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/hadolint/hadolint
rev: v2.13.1-beta
rev: v2.15.1
hooks:
- id: hadolint
name: Hadolint for Dockerfiles
- repo: https://github.com/asottile/pyupgrade
rev: v3.20.0
rev: v3.21.2
hooks:
- id: pyupgrade
name: pyupgrade
description: Run PyUpgrade on Python code.
args: [--py311-plus]
- repo: https://github.com/pycqa/isort
rev: 6.0.1
rev: 9.0.0b5
hooks:
- id: isort
args: [--settings-path setup.cfg]
args: [--settings-path, pyproject.toml]
name: isort
description: Run import sorting (isort) on Python code.
- repo: https://github.com/psf/black
rev: 25.1.0
rev: 26.5.1
hooks:
- id: black
name: Black for Python code formatting
language_version: python3
args: ["--skip-string-normalization", "--target-version", "py310", "--line-length", "100"]
- repo: https://github.com/pycqa/flake8
rev: 7.2.0
rev: 7.3.0
hooks:
- id: flake8
name: Flake8 for Python code linting
args: ["--config", ".flake8"]
additional_dependencies: [flake8-pyproject==1.2.4]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
rev: v6.0.0
hooks:
- id: double-quote-string-fixer
name: Format single quotes
- id: requirements-txt-fixer
name: Format requirements.txt
- id: check-yaml
name: Format YAML files
args: ['--unsafe']
- id: check-toml
name: Format TOML files
- id: trailing-whitespace
name: Fix Whitespace
- id: mixed-line-ending
Expand Down
7 changes: 4 additions & 3 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ version: 2

# Set the version of Python and other tools you might need
build:
os: ubuntu-22.04
os: ubuntu-24.04
tools:
python: "3.10"
python: "3.11"

# Build documentation in the docs/ directory with Sphinx
sphinx:
Expand All @@ -18,6 +18,7 @@ sphinx:
# Optionally declare the Python requirements required to build your docs
python:
install:
- requirements: requirements/documentation.txt
- method: pip
path: .
extra_requirements:
- docs
8 changes: 7 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
=========
Changelog
=========

Version 0.2.0
-------------

* Add MobileNet ONNX species classification for spectrogram images and WAV files.
* Add ``classify``, ``classify-wav``, and ``classify-bulk`` CLI commands.
* Add mirrored model retrieval, bulk species summaries, and a performance plotting example.

TODO
----

Expand Down
5 changes: 1 addition & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,8 @@ WORKDIR /code

COPY ./ /code

RUN python3 -m venv /venv

# hadolint ignore=DL3003,DL3013
RUN /venv/bin/pip install --no-cache-dir -r requirements/runtime.txt \
&& /venv/bin/pip install --no-cache-dir -r requirements/optional.txt \
RUN python3 -m venv /venv \
&& /venv/bin/pip install --no-cache-dir -e .
# && if [ "$(uname -m)" != "aarch64" ] \
# ; then \
Expand Down
1 change: 0 additions & 1 deletion ISSUES.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
============
Known Issues
============

Expand Down
4 changes: 4 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ include LICENSE

# Include examples files for testing
include examples/example1.wav
include examples/plot_classifier_performance.py

# Include the classifier model in source distributions
recursive-include batbot/classifier/models/onnx *.onnx
Loading
Loading