diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index bf260959..01a5263c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -29,7 +29,7 @@ jobs: build-app-packages: strategy: matrix: - os: [ubuntu-latest, macos-13, windows-latest] + os: [ubuntu-latest, macos-latest, windows-latest] fail-fast: false defaults: run: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dc644639..78e85903 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,6 +71,7 @@ jobs: vulnerability-service: osv # Ignore issues with pip and setuptools versions used by the action itself ignore-vulns: | + GHSA-cx63-2mw6-8hw5 GHSA-mq26-g339-26xf PYSEC-2023-228 PYSEC-2022-43012 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..4c485d7d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,76 @@ +# Dev container with PySide6 built from source +FROM stateoftheartio/qt6:6.7-gcc-aqt +ARG QT_VERSION=6.7 + +# Install python 3.11 +USER root +RUN apt-get update \ + && apt-get install -y software-properties-common \ + && add-apt-repository -y ppa:deadsnakes/ppa \ + && apt-get update \ + && apt-get install -y \ + libgl1-mesa-dev \ + git \ + p7zip \ + libpython3-dev \ + python3.11-dev \ + python3.11-venv \ + python3.11-distutils +# clang \ +# libclang-10-dev \ +# ENV LLVM_INSTALL_DIR=/usr/lib/llvm-10 + +# Cleanup +RUN sudo apt-get clean && sudo rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# Set up virtualenv +USER user +WORKDIR /home/user +RUN mkdir -p ~/.virtualenvs \ + && python3.11 -m venv ~/.virtualenvs/pyside6 \ + && . ~/.virtualenvs/pyside6/bin/activate \ + && python -m pip install -U pip setuptools + +# Install pre-built libclang +RUN curl -fLo libclang.7z https://download.qt.io/development_releases/prebuilt/libclang/libclang-release_140-based-linux-Ubuntu20.04-gcc9.3-x86_64.7z \ + && 7zr x libclang.7z \ + && rm libclang.7z +ENV LLVM_INSTALL_DIR=/home/user/libclang + +# Check out pyside6 setup repo +RUN git clone https://code.qt.io/pyside/pyside-setup \ + && cd /home/user/pyside-setup \ + && QT_TAG=$(git tag | grep '^[v?]${QT_VERSION}' | tail -n 1) \ + && echo "Selecting PySide6 $QT_TAG" \ + && git checkout $QT_TAG + +# Install dependencies and build with setuptools wrapper scripts +RUN cd /home/user/pyside-setup \ + && . ~/.virtualenvs/pyside6/bin/activate \ + && python -m pip install -r requirements.txt \ + && python setup.py build --parallel=4 --ignore-git \ + && python setup.py install --parallel=4 + +# Alternative: Build with cmake only, without setuptools +# BROKEN; Must be missing some cmake flags + +# Misc hacks +# Why is this needed?? Otherwise fails with: +# stdcomplex.cpp:8:1: error: function 'StdComplex::StdComplex()' defaulted on its redeclaration with an exception-specification that differs from the implicit exception-specification '' +# sed -i /home/user/pyside-setup/sources/shiboken6/tests/libsample/stdcomplex.cpp -e 's/StdComplex::StdComplex() noexcept = default;//' +# hiddenobject.cpp:18:29: error: use of deleted function 'HiddenObject::HiddenObject()' +# In file included from /home/user/pyside-setup/sources/pyside6/tests/pysidetest/hiddenobject.cpp:4: +# hiddenobject.h:16:5: note: 'HiddenObject::HiddenObject() noexcept' is implicitly deleted because its exception-specification does not match the implicit exception-specification '' +# sed -i /home/user/pyside-setup/sources/pyside6/tests/pysidetest/hiddenobject.h -e 's/HiddenObject::HiddenObject() noexcept = default;//' + +# Python headers not found +# export CPPFLAGS=-I/usr/include/python3.11 +# export CMAKE_INCLUDE_PATH=/usr/include/python3.11 + +# Build with cmake (BROKEN) +# RUN cmake -B /home/user/pyside-setup/build \ +# -S /home/user/pyside-setup \ +# -DCMAKE_INSTALL_PREFIX=/home/user/pyside-setup/dist \ +# -DPython_EXECUTABLE=$HOME/.virtualenvs/pyside6/bin/python \ +# && cmake --build /home/user/pyside-setup/build --parallel 2 \ +# && cmake --install /home/user/pyside-setup/build diff --git a/docs/conf.py b/docs/conf.py index b53e0782..58101400 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,7 +36,6 @@ 'modules/modules.rst', 'modules/naturtag.rst', 'modules/naturtag.constants.rst', - 'modules/naturtag.utils.rst', ] # Replace '{{version}}' in md files with current version diff --git a/docs/reference.md b/docs/reference.md index 4559e5af..472136a2 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -47,13 +47,10 @@ refresh_tags(['~/observations/'], recursive=True) :maxdepth: 1 modules/naturtag.app +modules/naturtag.cli modules/naturtag.controllers modules/naturtag.metadata +modules/naturtag.storage modules/naturtag.widgets - -modules/naturtag.cli -modules/naturtag.client -modules/naturtag.settings -modules/naturtag.utils.image_glob -modules/naturtag.utils.thumbnails +modules/naturtag.utils ``` diff --git a/naturtag/app/app.py b/naturtag/app/app.py index ef38c774..b91444f8 100755 --- a/naturtag/app/app.py +++ b/naturtag/app/app.py @@ -22,12 +22,11 @@ from naturtag.app.controls import Toolbar, UserDirs from naturtag.app.settings_menu import SettingsMenu -from naturtag.app.style import fa_icon, set_theme from naturtag.app.threadpool import ThreadPool from naturtag.constants import APP_ICON, APP_LOGO, ASSETS_DIR, DOCS_URL, REPO_URL from naturtag.controllers import ImageController, ObservationController, TaxonController from naturtag.storage import ImageSession, Settings, iNatDbClient, setup -from naturtag.widgets import VerticalLayout, init_handler +from naturtag.widgets import VerticalLayout, fa_icon, init_handler, set_theme # Provide an application group so Windows doesn't use the default 'python' icon try: diff --git a/naturtag/app/controls.py b/naturtag/app/controls.py index d9208617..96df66db 100644 --- a/naturtag/app/controls.py +++ b/naturtag/app/controls.py @@ -14,8 +14,8 @@ from PySide6.QtGui import QAction, QKeySequence from PySide6.QtWidgets import QApplication, QFileDialog, QMenu, QSizePolicy, QToolBar, QWidget -from naturtag.app.style import fa_icon from naturtag.storage import Settings +from naturtag.widgets.style import fa_icon HOME_DIR = str(Path.home()) logger = getLogger(__name__) diff --git a/naturtag/cli.py b/naturtag/cli.py index 5aa53669..70cb4c88 100644 --- a/naturtag/cli.py +++ b/naturtag/cli.py @@ -174,6 +174,7 @@ def tag( include_sidecars=True, ) if not metadata_objs: + click.secho('No search results found', fg='red') return click.echo(f'{len(metadata_objs)} images tagged') diff --git a/naturtag/controllers/image_gallery.py b/naturtag/controllers/image_gallery.py index bbc1ba2f..48e2a528 100644 --- a/naturtag/controllers/image_gallery.py +++ b/naturtag/controllers/image_gallery.py @@ -3,7 +3,7 @@ import webbrowser from logging import getLogger from pathlib import Path -from typing import Callable, Iterable, Optional +from typing import TYPE_CHECKING, Callable, Iterable, Optional from PySide6.QtCore import ( QEasingCurve, @@ -26,8 +26,6 @@ QWidget, ) -from naturtag.app.style import fa_icon -from naturtag.app.threadpool import ThreadPool from naturtag.constants import IMAGE_FILETYPES, SIZE_DEFAULT, Dimensions, PathOrStr from naturtag.controllers import BaseController from naturtag.metadata import MetaMetadata @@ -41,6 +39,10 @@ VerticalLayout, ) from naturtag.widgets.images import HoverMixin, PixmapLabel +from naturtag.widgets.style import fa_icon + +if TYPE_CHECKING: + from naturtag.app.threadpool import ThreadPool logger = getLogger(__name__) @@ -217,7 +219,7 @@ def load_image(self): self.image.setPixmap(pixmap) self.set_metadata(metadata) - def load_image_async(self, threadpool: ThreadPool): + def load_image_async(self, threadpool: 'ThreadPool'): """Load thumbnail + metadata in a separate thread""" self.image.set_pixmap_meta_async(threadpool, self.image_path) self.image.on_load_metadata.connect(self.set_metadata) @@ -315,7 +317,7 @@ def get_pixmap_meta(self, path: PathOrStr) -> tuple[QPixmap, MetaMetadata]: """ return generate_thumbnail(path, self.thumbnail_size), MetaMetadata(path) - def set_pixmap_meta_async(self, threadpool: ThreadPool, path: Optional[PathOrStr] = None): + def set_pixmap_meta_async(self, threadpool: 'ThreadPool', path: Optional[PathOrStr] = None): """Generate a photo thumbnail and read its metadata from a separate thread, and render it in the main thread when complete """ diff --git a/naturtag/controllers/observation_controller.py b/naturtag/controllers/observation_controller.py index 77c91bee..7464e1e0 100644 --- a/naturtag/controllers/observation_controller.py +++ b/naturtag/controllers/observation_controller.py @@ -5,10 +5,10 @@ from PySide6.QtCore import Qt, QThread, QTimer, Signal, Slot from PySide6.QtWidgets import QLabel, QPushButton -from naturtag.app.style import fa_icon from naturtag.constants import DEFAULT_PAGE_SIZE from naturtag.controllers import BaseController, ObservationInfoSection from naturtag.widgets import HorizontalLayout, ObservationInfoCard, ObservationList, VerticalLayout +from naturtag.widgets.style import fa_icon logger = getLogger(__name__) diff --git a/naturtag/controllers/observation_view.py b/naturtag/controllers/observation_view.py index d1e470f1..4e41fefc 100644 --- a/naturtag/controllers/observation_view.py +++ b/naturtag/controllers/observation_view.py @@ -10,7 +10,6 @@ from PySide6.QtCore import Qt, QThread, Signal from PySide6.QtWidgets import QGroupBox, QLabel, QPushButton -from naturtag.app.style import fa_icon from naturtag.constants import SIZE_SM from naturtag.widgets import ( GridLayout, @@ -22,6 +21,7 @@ set_pixmap_async, ) from naturtag.widgets.observation_images import GEOPRIVACY_ICONS, QUALITY_GRADE_ICONS +from naturtag.widgets.style import fa_icon logger = getLogger(__name__) diff --git a/naturtag/controllers/taxon_controller.py b/naturtag/controllers/taxon_controller.py index e64c19db..1f811056 100644 --- a/naturtag/controllers/taxon_controller.py +++ b/naturtag/controllers/taxon_controller.py @@ -5,7 +5,6 @@ from PySide6.QtCore import QSize, Qt, QThread, QTimer, Signal, Slot from PySide6.QtWidgets import QTabWidget, QWidget -from naturtag.app.style import fa_icon from naturtag.constants import MAX_DISPLAY_OBSERVED from naturtag.controllers import ( BaseController, @@ -16,6 +15,7 @@ ) from naturtag.storage import AppState from naturtag.widgets import HorizontalLayout, TaxonInfoCard, TaxonList, VerticalLayout +from naturtag.widgets.style import fa_icon logger = getLogger(__name__) diff --git a/naturtag/controllers/taxon_search.py b/naturtag/controllers/taxon_search.py index fc8d61bd..b818e378 100644 --- a/naturtag/controllers/taxon_search.py +++ b/naturtag/controllers/taxon_search.py @@ -8,7 +8,6 @@ from PySide6.QtGui import QIcon from PySide6.QtWidgets import QApplication, QComboBox, QLabel, QPushButton, QWidget -from naturtag.app.style import fa_icon from naturtag.constants import COMMON_RANKS, RANKS, SELECTABLE_ICONIC_TAXA from naturtag.controllers import get_app from naturtag.widgets import ( @@ -20,6 +19,7 @@ VerticalLayout, ) from naturtag.widgets.images import FAIcon +from naturtag.widgets.style import fa_icon logger = getLogger(__name__) diff --git a/naturtag/controllers/taxon_view.py b/naturtag/controllers/taxon_view.py index c7d7b556..bb3a817c 100644 --- a/naturtag/controllers/taxon_view.py +++ b/naturtag/controllers/taxon_view.py @@ -9,7 +9,6 @@ from PySide6.QtCore import Qt, QThread, Signal from PySide6.QtWidgets import QGroupBox, QPushButton -from naturtag.app.style import fa_icon from naturtag.constants import SIZE_SM from naturtag.storage import AppState from naturtag.widgets import ( @@ -21,6 +20,7 @@ set_pixmap_async, ) from naturtag.widgets.layouts import VerticalLayout +from naturtag.widgets.style import fa_icon from naturtag.widgets.taxon_images import TaxonPhoto logger = getLogger(__name__) diff --git a/naturtag/metadata/inat_metadata.py b/naturtag/metadata/inat_metadata.py index e3ec0019..5c7e5760 100644 --- a/naturtag/metadata/inat_metadata.py +++ b/naturtag/metadata/inat_metadata.py @@ -193,7 +193,8 @@ def _format_key(k): return f'Xmp.{namespace}.{term}' if namespace in DWC_NAMESPACES else None # Convert and add DwC metadata - dwc = to_dwc(observations=[observation], taxa=[observation.taxon])[0] + tag_observations = [observation] if observation.id else None + dwc = to_dwc(observations=tag_observations, taxa=[observation.taxon])[0] dwc_xmp = {_format_key(k): v for k, v in dwc.items() if _format_key(k)} metadata.update(dwc_xmp) diff --git a/naturtag/storage/client.py b/naturtag/storage/client.py index 848149e7..7cbbc45a 100644 --- a/naturtag/storage/client.py +++ b/naturtag/storage/client.py @@ -36,7 +36,9 @@ def from_id( # Get observation record, if available if observation_id: observation = self.observations(observation_id, refresh=True) - taxon_id = observation.taxon.id + if not observation: + return None + taxon_id = observation.taxon.id if observation.taxon else None # Otherwise, use an empty placeholder observation else: observation = Observation() diff --git a/naturtag/widgets/__init__.py b/naturtag/widgets/__init__.py index 39ab827d..82016a29 100644 --- a/naturtag/widgets/__init__.py +++ b/naturtag/widgets/__init__.py @@ -7,6 +7,7 @@ StylableWidget, VerticalLayout, ) +from naturtag.widgets.style import fa_icon, set_theme from naturtag.widgets.autocomplete import TaxonAutocomplete from naturtag.widgets.images import ( FullscreenPhoto, diff --git a/naturtag/widgets/autocomplete.py b/naturtag/widgets/autocomplete.py index ed6d0427..00ea5a85 100644 --- a/naturtag/widgets/autocomplete.py +++ b/naturtag/widgets/autocomplete.py @@ -4,8 +4,7 @@ from PySide6.QtCore import QEvent, QStringListModel, Qt, Signal, Slot from PySide6.QtWidgets import QCompleter, QLineEdit, QToolButton -from naturtag.app.style import fa_icon -from naturtag.controllers import get_app +from naturtag.widgets.style import fa_icon logger = getLogger(__name__) @@ -19,6 +18,8 @@ class TaxonAutocomplete(QLineEdit): on_tab = Signal() #: Tab key was pressed def __init__(self): + from naturtag.controllers import get_app + super().__init__() self.setClearButtonEnabled(True) self.findChild(QToolButton).setIcon(fa_icon('mdi.backspace')) @@ -51,6 +52,8 @@ def next_result(self): # TODO: Input delay def search(self, q: str): + from naturtag.controllers import get_app + if len(q) > 1 and q not in self.taxa: app = get_app() language = app.settings.locale if app.settings.search_locale else None diff --git a/naturtag/widgets/images.py b/naturtag/widgets/images.py index e3a58389..53d518ac 100644 --- a/naturtag/widgets/images.py +++ b/naturtag/widgets/images.py @@ -10,10 +10,10 @@ from PySide6.QtGui import QBrush, QFont, QIcon, QPainter, QPixmap from PySide6.QtWidgets import QLabel, QLayout, QScrollArea, QSizePolicy, QWidget -from naturtag.app.style import fa_icon from naturtag.constants import SIZE_ICON, SIZE_ICON_SM, SIZE_SM, IconDimensions, IntOrStr, PathOrStr from naturtag.widgets import StylableWidget, VerticalLayout from naturtag.widgets.layouts import GridLayout, HorizontalLayout +from naturtag.widgets.style import fa_icon if TYPE_CHECKING: MIXIN_BASE: TypeAlias = QWidget diff --git a/naturtag/widgets/inputs.py b/naturtag/widgets/inputs.py index 9f6a97a1..7c630ff6 100644 --- a/naturtag/widgets/inputs.py +++ b/naturtag/widgets/inputs.py @@ -5,7 +5,7 @@ from PySide6.QtGui import QAction, QIntValidator from PySide6.QtWidgets import QLineEdit, QToolButton -from naturtag.app.style import fa_icon +from naturtag.widgets.style import fa_icon logger = getLogger(__name__) diff --git a/naturtag/app/style.py b/naturtag/widgets/style.py similarity index 100% rename from naturtag/app/style.py rename to naturtag/widgets/style.py diff --git a/poetry.lock b/poetry.lock index b5a25840..cfbf7242 100644 --- a/poetry.lock +++ b/poetry.lock @@ -457,43 +457,38 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "42.0.8" +version = "43.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, - {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, - {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, - {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, - {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, - {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, - {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, + {file = "cryptography-43.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:64c3f16e2a4fc51c0d06af28441881f98c5d91009b8caaff40cf3548089e9c74"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dcdedae5c7710b9f97ac6bba7e1052b95c7083c9d0e9df96e02a1932e777895"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d9a1eca329405219b605fac09ecfc09ac09e595d6def650a437523fcd08dd22"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ea9e57f8ea880eeea38ab5abf9fbe39f923544d7884228ec67d666abd60f5a47"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9a8d6802e0825767476f62aafed40532bd435e8a5f7d23bd8b4f5fd04cc80ecf"}, + {file = "cryptography-43.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:cc70b4b581f28d0a254d006f26949245e3657d40d8857066c2ae22a61222ef55"}, + {file = "cryptography-43.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4a997df8c1c2aae1e1e5ac49c2e4f610ad037fc5a3aadc7b64e39dea42249431"}, + {file = "cryptography-43.0.0-cp37-abi3-win32.whl", hash = "sha256:6e2b11c55d260d03a8cf29ac9b5e0608d35f08077d8c087be96287f43af3ccdc"}, + {file = "cryptography-43.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:31e44a986ceccec3d0498e16f3d27b2ee5fdf69ce2ab89b52eaad1d2f33d8778"}, + {file = "cryptography-43.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:7b3f5fe74a5ca32d4d0f302ffe6680fcc5c28f8ef0dc0ae8f40c0f3a1b4fca66"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac1955ce000cb29ab40def14fd1bbfa7af2017cca696ee696925615cafd0dce5"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:299d3da8e00b7e2b54bb02ef58d73cd5f55fb31f33ebbf33bd00d9aa6807df7e"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ee0c405832ade84d4de74b9029bedb7b31200600fa524d218fc29bfa371e97f5"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cb013933d4c127349b3948aa8aaf2f12c0353ad0eccd715ca789c8a0f671646f"}, + {file = "cryptography-43.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fdcb265de28585de5b859ae13e3846a8e805268a823a12a4da2597f1f5afc9f0"}, + {file = "cryptography-43.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2905ccf93a8a2a416f3ec01b1a7911c3fe4073ef35640e7ee5296754e30b762b"}, + {file = "cryptography-43.0.0-cp39-abi3-win32.whl", hash = "sha256:47ca71115e545954e6c1d207dd13461ab81f4eccfcb1345eac874828b5e3eaaf"}, + {file = "cryptography-43.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:0663585d02f76929792470451a5ba64424acc3cd5227b03921dab0e2f27b1709"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2c6d112bf61c5ef44042c253e4859b3cbbb50df2f78fa8fae6747a7814484a70"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:844b6d608374e7d08f4f6e6f9f7b951f9256db41421917dfb2d003dde4cd6b66"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:51956cf8730665e2bdf8ddb8da0056f699c1a5715648c1b0144670c1ba00b48f"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:aae4d918f6b180a8ab8bf6511a419473d107df4dbb4225c7b48c5c9602c38c7f"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:232ce02943a579095a339ac4b390fbbe97f5b5d5d107f8a08260ea2768be8cc2"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5bcb8a5620008a8034d39bce21dc3e23735dfdb6a33a06974739bfa04f853947"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:08a24a7070b2b6804c1940ff0f910ff728932a9d0e80e7814234269f9d46d069"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e9c5266c432a1e23738d178e51c2c7a5e2ddf790f248be939448c0ba2021f9d1"}, + {file = "cryptography-43.0.0.tar.gz", hash = "sha256:b88075ada2d51aa9f18283532c9f60e72170041bba88d7f37e49cbb10275299e"}, ] [package.dependencies] @@ -506,7 +501,7 @@ nox = ["nox"] pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "cryptography-vectors (==43.0.0)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] @@ -533,24 +528,24 @@ files = [ [[package]] name = "docutils" -version = "0.19" +version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = true -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"}, - {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, ] [[package]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] @@ -599,20 +594,20 @@ six = ">=1.12,<2.0" [[package]] name = "furo" -version = "2023.9.10" +version = "2024.7.18" description = "A clean customisable Sphinx documentation theme." optional = true python-versions = ">=3.8" files = [ - {file = "furo-2023.9.10-py3-none-any.whl", hash = "sha256:513092538537dc5c596691da06e3c370714ec99bc438680edc1debffb73e5bfc"}, - {file = "furo-2023.9.10.tar.gz", hash = "sha256:5707530a476d2a63b8cad83b4f961f3739a69f4b058bcf38a03a39fa537195b2"}, + {file = "furo-2024.7.18-py3-none-any.whl", hash = "sha256:b192c7c1f59805494c8ed606d9375fdac6e6ba8178e747e72bc116745fb7e13f"}, + {file = "furo-2024.7.18.tar.gz", hash = "sha256:37b08c5fccc95d46d8712c8be97acd46043963895edde05b0f4f135d58325c83"}, ] [package.dependencies] beautifulsoup4 = "*" pygments = ">=2.7" sphinx = ">=6.0,<8.0" -sphinx-basic-ng = "*" +sphinx-basic-ng = ">=1.0.0.beta2" [[package]] name = "greenlet" @@ -1032,17 +1027,17 @@ files = [ [[package]] name = "myst-parser" -version = "2.0.0" +version = "3.0.1" description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," optional = true python-versions = ">=3.8" files = [ - {file = "myst_parser-2.0.0-py3-none-any.whl", hash = "sha256:7c36344ae39c8e740dad7fdabf5aa6fc4897a813083c6cc9990044eb93656b14"}, - {file = "myst_parser-2.0.0.tar.gz", hash = "sha256:ea929a67a6a0b1683cdbe19b8d2e724cd7643f8aa3e7bb18dd65beac3483bead"}, + {file = "myst_parser-3.0.1-py3-none-any.whl", hash = "sha256:6457aaa33a5d474aca678b8ead9b3dc298e89c68e67012e73146ea6fd54babf1"}, + {file = "myst_parser-3.0.1.tar.gz", hash = "sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87"}, ] [package.dependencies] -docutils = ">=0.16,<0.21" +docutils = ">=0.18,<0.22" jinja2 = "*" markdown-it-py = ">=3.0,<4.0" mdit-py-plugins = ">=0.4,<1.0" @@ -1052,9 +1047,9 @@ sphinx = ">=6,<8" [package.extras] code-style = ["pre-commit (>=3.0,<4.0)"] linkify = ["linkify-it-py (>=2.0,<3.0)"] -rtd = ["ipython", "pydata-sphinx-theme (==v0.13.0rc4)", "sphinx-autodoc2 (>=0.4.2,<0.5.0)", "sphinx-book-theme (==1.0.0rc2)", "sphinx-copybutton", "sphinx-design2", "sphinx-pyscript", "sphinx-tippy (>=0.3.1)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.8.2,<0.9.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] -testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=7,<8)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx-pytest"] -testing-docutils = ["pygments", "pytest (>=7,<8)", "pytest-param-files (>=0.3.4,<0.4.0)"] +rtd = ["ipython", "sphinx (>=7)", "sphinx-autodoc2 (>=0.5.0,<0.6.0)", "sphinx-book-theme (>=1.1,<2.0)", "sphinx-copybutton", "sphinx-design", "sphinx-pyscript", "sphinx-tippy (>=0.4.3)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.9.0,<0.10.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] +testing = ["beautifulsoup4", "coverage[toml]", "defusedxml", "pytest (>=8,<9)", "pytest-cov", "pytest-param-files (>=0.6.0,<0.7.0)", "pytest-regressions", "sphinx-pytest"] +testing-docutils = ["pygments", "pytest (>=8,<9)", "pytest-param-files (>=0.6.0,<0.7.0)"] [[package]] name = "nodeenv" @@ -1103,6 +1098,51 @@ nox = ">=2020.8.22" packaging = ">=20.9" tomlkit = ">=0.7" +[[package]] +name = "numpy" +version = "1.26.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, + {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, + {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, +] + [[package]] name = "packaging" version = "24.1" @@ -1370,29 +1410,31 @@ docs = ["furo (>=2023.7,<2024.0)", "ipython (>=8.12,<9.0)", "linkify-it-py (>=2. [[package]] name = "pyinaturalist-convert" -version = "0.6.3" +version = "0.6.5" description = "Data conversion tools for iNaturalist observations and taxonomy" optional = false python-versions = ">=3.8,<4.0" files = [ - {file = "pyinaturalist_convert-0.6.3-py3-none-any.whl", hash = "sha256:ac04539a4e98c20c263ba381e1f319f0584fc4937879d26f3c60eb02b827910b"}, - {file = "pyinaturalist_convert-0.6.3.tar.gz", hash = "sha256:1876b954e8c5f96b0f31067bbd1588dc9a2787ab55afd74b9ea70564650fc348"}, + {file = "pyinaturalist_convert-0.6.5-py3-none-any.whl", hash = "sha256:c31ae757c4ebae3efa8559bf1bbf7abd557fa41e9d6c6eb4037c61608aefb216"}, + {file = "pyinaturalist_convert-0.6.5.tar.gz", hash = "sha256:a7b20b58f9ebf74a5093effb3510cb43e953484a32ddf3e499a0a22bc2a3a1a5"}, ] [package.dependencies] flatten-dict = ">=0.4" +numpy = "<2.0" pyinaturalist = ">=0.18" +tablib = ">=3.0" [package.extras] -all = ["boto3 (>=1.20)", "geojson (>=2.5)", "gpxpy (>=1.4)", "odfpy (>=1.4)", "openpyxl (>=2.6)", "pandas (>=1.2)", "pyarrow (>=10.0)", "pyyaml (>=6.0)", "sqlalchemy (>=2.0,<3.0)", "tables (>=3.6)", "tablib (>=3.0)", "tabulate", "xlrd", "xlwt", "xmltodict (>=0.12)"] +all = ["boto3 (>=1.20)", "geojson (>=2.5)", "gpxpy (>=1.4)", "odfpy (>=1.4)", "openpyxl (>=2.6)", "pandas (>=1.2)", "pyarrow (>=10.0)", "pyyaml (>=6.0)", "sqlalchemy (>=2.0,<3.0)", "tables (>=3.6)", "tabulate", "xlrd", "xlwt", "xmltodict (>=0.12)"] db = ["sqlalchemy (>=2.0,<3.0)"] -docs = ["furo (>=2023.9,<2025.0)", "myst-parser (>1.0)", "sphinx (>=6.2,<7.0)", "sphinx-autodoc-typehints (==1.20)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.5)"] +docs = ["furo (>=2024.5,<2025.0)", "myst-parser (>1.0)", "sphinx (>=6.2,<7.0)", "sphinx-autodoc-typehints (==1.20)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.5)"] dwc = ["xmltodict (>=0.12)"] feather = ["pandas (>=1.2)", "pyarrow (>=10.0)"] geojson = ["geojson (>=2.5)"] gpx = ["gpxpy (>=1.4)"] hdf = ["pandas (>=1.2)", "tables (>=3.6)"] -html = ["markuppy (>=1.12)", "tablib (>=3.0)"] +html = ["markuppy (>=1.12)"] odp = ["boto3 (>=1.20)"] parquet = ["pandas (>=1.2)", "pyarrow (>=10.0)"] xlsx = ["openpyxl (>=2.6)", "pandas (>=1.2)"] @@ -1528,13 +1570,13 @@ shiboken6 = "6.7.2" [[package]] name = "pytest" -version = "8.2.2" +version = "8.3.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, - {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, + {file = "pytest-8.3.1-py3-none-any.whl", hash = "sha256:e9600ccf4f563976e2c99fa02c7624ab938296551f280835ee6516df8bc4ae8c"}, + {file = "pytest-8.3.1.tar.gz", hash = "sha256:7e8e5c5abd6e93cb1cc151f23e57adc31fcf8cfd2a3ff2da63e23f732de35db6"}, ] [package.dependencies] @@ -1542,7 +1584,7 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=1.5,<2.0" +pluggy = ">=1.5,<2" tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] @@ -1810,18 +1852,19 @@ jeepney = ">=0.6" [[package]] name = "setuptools" -version = "70.3.0" +version = "71.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc"}, - {file = "setuptools-70.3.0.tar.gz", hash = "sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5"}, + {file = "setuptools-71.1.0-py3-none-any.whl", hash = "sha256:33874fdc59b3188304b2e7c80d9029097ea31627180896fb549c578ceb8a0855"}, + {file = "setuptools-71.1.0.tar.gz", hash = "sha256:032d42ee9fb536e33087fb66cac5f840eb9391ed05637b3f2a76a7c8fb477936"}, ] [package.extras] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "shiboken6" @@ -1871,56 +1914,57 @@ files = [ [[package]] name = "sphinx" -version = "6.2.1" +version = "7.4.7" description = "Python documentation generator" optional = true -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "Sphinx-6.2.1.tar.gz", hash = "sha256:6d56a34697bb749ffa0152feafc4b19836c755d90a7c59b72bc7dfd371b9cc6b"}, - {file = "sphinx-6.2.1-py3-none-any.whl", hash = "sha256:97787ff1fa3256a3eef9eda523a63dbf299f7b47e053cfcf684a1c2a8380c912"}, + {file = "sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239"}, + {file = "sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe"}, ] [package.dependencies] -alabaster = ">=0.7,<0.8" -babel = ">=2.9" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.18.1,<0.20" +alabaster = ">=0.7.14,<0.8.0" +babel = ">=2.13" +colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} +docutils = ">=0.20,<0.22" imagesize = ">=1.3" -Jinja2 = ">=3.0" -packaging = ">=21.0" -Pygments = ">=2.13" -requests = ">=2.25.0" -snowballstemmer = ">=2.0" +Jinja2 = ">=3.1" +packaging = ">=23.0" +Pygments = ">=2.17" +requests = ">=2.30.0" +snowballstemmer = ">=2.2" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" sphinxcontrib-htmlhelp = ">=2.0.0" sphinxcontrib-jsmath = "*" sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = ">=1.1.5" +sphinxcontrib-serializinghtml = ">=1.1.9" +tomli = {version = ">=2", markers = "python_version < \"3.11\""} [package.extras] docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] -test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] +lint = ["flake8 (>=6.0)", "importlib-metadata (>=6.0)", "mypy (==1.10.1)", "pytest (>=6.0)", "ruff (==0.5.2)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-docutils (==0.21.0.20240711)", "types-requests (>=2.30.0)"] +test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"] [[package]] name = "sphinx-autodoc-typehints" -version = "1.23.0" +version = "1.25.3" description = "Type hints (PEP 484) support for the Sphinx autodoc extension" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "sphinx_autodoc_typehints-1.23.0-py3-none-any.whl", hash = "sha256:ac099057e66b09e51b698058ba7dd76e57e1fe696cd91b54e121d3dad188f91d"}, - {file = "sphinx_autodoc_typehints-1.23.0.tar.gz", hash = "sha256:5d44e2996633cdada499b6d27a496ddf9dbc95dd1f0f09f7b37940249e61f6e9"}, + {file = "sphinx_autodoc_typehints-1.25.3-py3-none-any.whl", hash = "sha256:d3da7fa9a9761eff6ff09f8b1956ae3090a2d4f4ad54aebcade8e458d6340835"}, + {file = "sphinx_autodoc_typehints-1.25.3.tar.gz", hash = "sha256:70db10b391acf4e772019765991d2de0ff30ec0899b9ba137706dc0b3c4835e0"}, ] [package.dependencies] -sphinx = ">=5.3" +sphinx = ">=7.1.2" [package.extras] -docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23.4)"] -testing = ["covdefaults (>=2.2.2)", "coverage (>=7.2.2)", "diff-cover (>=7.5)", "nptyping (>=2.5)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "sphobjinv (>=2.3.1)", "typing-extensions (>=4.5)"] -type-comment = ["typed-ast (>=1.5.4)"] +docs = ["furo (>=2023.9.10)"] +numpy = ["nptyping (>=2.5)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "sphobjinv (>=2.3.1)", "typing-extensions (>=4.8)"] [[package]] name = "sphinx-basic-ng" @@ -2030,13 +2074,13 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "2.0.5" +version = "2.0.6" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = true python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_htmlhelp-2.0.5-py3-none-any.whl", hash = "sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04"}, - {file = "sphinxcontrib_htmlhelp-2.0.5.tar.gz", hash = "sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015"}, + {file = "sphinxcontrib_htmlhelp-2.0.6-py3-none-any.whl", hash = "sha256:1b9af5a2671a61410a868fce050cab7ca393c218e6205cbc7f590136f207395c"}, + {file = "sphinxcontrib_htmlhelp-2.0.6.tar.gz", hash = "sha256:c6597da06185f0e3b4dc952777a04200611ef563882e0c244d27a15ee22afa73"}, ] [package.extras] @@ -2060,19 +2104,19 @@ test = ["flake8", "mypy", "pytest"] [[package]] name = "sphinxcontrib-qthelp" -version = "1.0.7" +version = "1.0.8" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = true python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_qthelp-1.0.7-py3-none-any.whl", hash = "sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182"}, - {file = "sphinxcontrib_qthelp-1.0.7.tar.gz", hash = "sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6"}, + {file = "sphinxcontrib_qthelp-1.0.8-py3-none-any.whl", hash = "sha256:323d6acc4189af76dfe94edd2a27d458902319b60fcca2aeef3b2180c106a75f"}, + {file = "sphinxcontrib_qthelp-1.0.8.tar.gz", hash = "sha256:db3f8fa10789c7a8e76d173c23364bdf0ebcd9449969a9e6a3dd31b8b7469f03"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] standalone = ["Sphinx (>=5)"] -test = ["pytest"] +test = ["defusedxml (>=0.7.1)", "pytest"] [[package]] name = "sphinxcontrib-serializinghtml" @@ -2317,4 +2361,4 @@ docs = ["furo", "linkify-it-py", "myst-parser", "sphinx", "sphinx-autodoc-typehi [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.12" -content-hash = "7d137ba6ff95551cc94bf58da95ec1fa8be48fadaae95b09bb6107b777ffe8e5" +content-hash = "86d71a1e256c86a7c319d4e5efa569b515aa4cf28317cd70f1a15a8102dfe6c9" diff --git a/pyproject.toml b/pyproject.toml index 6ded65a3..5772fbfe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,8 +42,8 @@ click-help-colors = '>=0.9' pillow = '>=10.0' pyexiv2 = '>=2.10' pyinaturalist = '>=0.19' -pyinaturalist-convert = '>=0.6.2' -pyside6 = '^6.6.0' +pyinaturalist-convert = '>=0.6.5' +pyside6 = '^6.7.2' pyqtdarktheme = '^2.1.0' pyyaml = '>=6.0' qtawesome = '^1.1.1' @@ -51,10 +51,10 @@ sqlalchemy = '^2.0.23' tablib = '^3.0' # Documentation dependencies needed for Readthedocs builds -furo = {optional=true, version='^2023.9'} +furo = {optional=true, version='^2024.7'} linkify-it-py = {optional=true, version='^2.0'} -myst-parser = {optional=true, version='^2.0'} -sphinx = {optional=true, version='^6.2'} +myst-parser = {optional=true, version='^3.0'} +sphinx = {optional=true, version='^7.4'} sphinx-autodoc-typehints = {optional=true, version='^1.17'} sphinx-copybutton = {optional=true, version='>=0.5'} sphinx-design = {optional=true, version='>=0.2'}