[project] name = "garminconnect" version = "0.3.11" description = "Python 3 API wrapper for Garmin Connect" authors = [ { name = "Ron Klinkien", email = "ron@cyberjunky.nl" }, ] dependencies = [ "requests>=2.33.0", "ua-generator>=1.0", ] readme = "README.md" classifiers = [ "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "License :: OSI Approved :: MIT License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX :: Linux", "Operating System :: OS Independent", ] keywords = [ "garmin connect", "api", "garmin", ] requires-python = ">=3.12" [project.license] text = "MIT" [project.urls] Homepage = "https://github.com/cyberjunky/python-garminconnect" Issues = "https://github.com/cyberjunky/python-garminconnect/issues" Changelog = "https://github.com/cyberjunky/python-garminconnect/releases" [project.optional-dependencies] tls = [ "curl_cffi>=0.15.0", ] dev = [ "ipython", "ipdb", "ipykernel", "pandas", "matplotlib", ] workout = [ "pydantic>=2.4.0", ] typed = [ "pydantic>=2.4.0", ] security = [ "bandit[toml]", "pip-audit", ] linting = [ "black[jupyter]", "ruff", "mypy", "isort", "types-requests", "pre-commit", "codespell", ] testing = [ "coverage", "pytest", "pytest-vcr>=1.0.2", "vcrpy>=7.0.0", ] example = [ "readchar", ] [build-system] requires = [ "pdm-backend", ] build-backend = "pdm.backend" [tool.pytest.ini_options] addopts = "--ignore=__pypackages__ --ignore-glob=*.yaml -m 'not integration'" markers = [ "integration: requires a real Garmin account or a private VCR recording", ] [tool.mypy] ignore_missing_imports = true python_version = "3.12" disallow_untyped_defs = true warn_unused_ignores = true [[tool.mypy.overrides]] module = [ "test_garmin", "test_garmin_unit", "test_retry_decorator", "test_workout_constants", "test_strength_workout", "test_login_recovery", "test_token_permissions", "test_widget_mfa", "test_cassette_sanitization", "test_activity_details", "test_demo_security", "conftest", ] disallow_untyped_defs = false warn_unused_ignores = false [tool.isort] profile = "black" line_length = 88 known_first_party = "garminconnect" skip_glob = [ "tests/*", "test_data/*", ] [tool.pdm] distribution = true [tool.pdm.build] excludes = [ "tests/**", "test_data/**", ".github/**", ] [tool.pdm.scripts] install = "pdm install --group :all" codespell = "pre-commit run codespell --all-files" clean = "python -c \"import shutil, pathlib; [shutil.rmtree(p, ignore_errors=True) for p in pathlib.Path('.').rglob('__pycache__')]; [p.unlink(missing_ok=True) for p in pathlib.Path('.').rglob('*.py[co]')]\"" pre-commit-install = "pre-commit install" pre-commit-run = "pre-commit run --all-files" pre-commit-run-staged = "pre-commit run" pre-commit-update = "pre-commit autoupdate" build = "pdm build" clean-vcr = "python3 -c \"import pathlib; p=pathlib.Path('tests/cassettes'); [f.unlink() for f in p.glob('*.yaml')]\"" [tool.pdm.scripts.format] composite = [ "pdm run ruff check . --fix --unsafe-fixes", "pdm run isort . --skip-gitignore", "pdm run black -l 88 .", ] [tool.pdm.scripts.lint] composite = [ "pdm run isort --check-only . --skip-gitignore", "pdm run ruff check .", "pdm run black -l 88 . --check --diff", "pdm run mypy garminconnect tests", ] [tool.pdm.scripts.test] cmd = "pdm run coverage run -m pytest -v --durations=10" [tool.pdm.scripts.testcov] composite = [ "test", "pdm run coverage html", "pdm run coverage xml -o coverage/coverage.xml", ] [tool.pdm.scripts.publish] composite = [ "build", "pdm publish", ] [tool.pdm.scripts.record-vcr] cmd = "pdm run pytest tests/test_garmin.py -v --vcr-record=new_episodes" [tool.pdm.scripts.record-vcr.env] GARMINTOKENS = "~/.garminconnect" [tool.pdm.scripts.reset-vcr] composite = [ "clean-vcr", "record-vcr", ] [tool.pdm.scripts.all] composite = [ "lint", "codespell", "pre-commit-run", "test", ] [tool.pdm.dev-dependencies] dev = [ "ipython", "ipdb", "ipykernel", "pandas", "matplotlib", ] linting = [ "black[jupyter]", "ruff", "mypy", "isort", "types-requests", "pre-commit", "codespell", ] testing = [ "coverage", "pytest", "pytest-vcr>=1.0.2", "vcrpy>=7.0.0", ] example = [ "readchar", ] [tool.ruff] line-length = 88 target-version = "py312" exclude = [ ".git", ".venv", "__pycache__", ".pytest_cache", "build", "dist", "tests", "test_data", ] [tool.ruff.lint] select = [ "E", "W", "F", "I", "B", "C4", "UP", "ARG", "SIM", "S", "D", "PTH", "PL", "RUF", "TRY", "PERF", "LOG", "G", "T20", "PIE", "RET", "TCH", "ERA", ] ignore = [ "E501", "B008", "C901", "D100", "D104", "D105", "D107", "D203", "D213", "PLR0913", "PLR0917", "PLR2004", "PLR0912", "PLR0915", "PLC0415", "TRY003", "TRY004", "TRY301", "G004", "D205", "D401", "D102", "D106", "D417", "TRY401", "TRY203", "TRY300", "ERA001", ] unfixable = [] [tool.ruff.lint.per-file-ignores] "tests/*" = [ "ARG", "S101", "D103", ] "garminconnect/fit.py" = [ "D", "RUF012", "PLW2901", ] "garminconnect/workout.py" = [ "D401", ] "demo.py" = [ "T20", "S101", "ERA", "RUF001", "PTH", "PERF401", "PERF203", "PLR0911", "D103", ] "example.py" = [ "S110", "PLR0911", "T20", "PERF203", ] "test_strategy.py" = [ "T20", "D103", ] "scripts/*" = [ "T20", "D103", ] "tests/test_token_permissions.py" = [ "S105", ] [tool.coverage.run] source = [ "garminconnect", ] omit = [ "*/tests/*", "*/test_*", ] [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "if self.debug:", "if settings.DEBUG", "raise AssertionError", "raise NotImplementedError", "if 0:", "if __name__ == \"__main__\":", "@(abc\\.)?abstractmethod", ]