commit dae3e49783ede5cddf228dcb5724a2ed500b4de8 Author: Danielle McLean Date: Mon Nov 27 10:39:10 2023 +1100 Initial commit: set up project and dependencies diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f2bc80b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true + +[*.py] +indent_size = 4 +indent_style = tab diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..02ed0fc --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +PATH_add .venv/bin diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a8816c --- /dev/null +++ b/.gitignore @@ -0,0 +1,162 @@ +# 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-project.org/#use-with-ide +.pdm.toml +.pdm-python +.pdm-build/ + +# 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/ + +# 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/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..3314c93 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# mpd-now-playable diff --git a/pdm.lock b/pdm.lock new file mode 100644 index 0000000..c61395e --- /dev/null +++ b/pdm.lock @@ -0,0 +1,200 @@ +# This file is @generated by PDM. +# It is not intended for manual editing. + +[metadata] +groups = ["default", "dev"] +strategy = ["cross_platform"] +lock_version = "4.4" +content_hash = "sha256:d60f3387d2c060bcc57f22fedf3f45cd78f7c7f08a5d5a7764974a079cf6f5bf" + +[[package]] +name = "async-lru" +version = "2.0.4" +requires_python = ">=3.8" +summary = "Simple LRU cache for asyncio" +files = [ + {file = "async-lru-2.0.4.tar.gz", hash = "sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627"}, + {file = "async_lru-2.0.4-py3-none-any.whl", hash = "sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224"}, +] + +[[package]] +name = "attrs" +version = "23.1.0" +requires_python = ">=3.7" +summary = "Classes Without Boilerplate" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] + +[[package]] +name = "mypy" +version = "1.7.1" +requires_python = ">=3.8" +summary = "Optional static typing for Python" +dependencies = [ + "mypy-extensions>=1.0.0", + "typing-extensions>=4.1.0", +] +files = [ + {file = "mypy-1.7.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6dbdec441c60699288adf051f51a5d512b0d818526d1dcfff5a41f8cd8b4aaf1"}, + {file = "mypy-1.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fc3d14ee80cd22367caaaf6e014494415bf440980a3045bf5045b525680ac33"}, + {file = "mypy-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c6e4464ed5f01dc44dc9821caf67b60a4e5c3b04278286a85c067010653a0eb"}, + {file = "mypy-1.7.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d9b338c19fa2412f76e17525c1b4f2c687a55b156320acb588df79f2e6fa9fea"}, + {file = "mypy-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:204e0d6de5fd2317394a4eff62065614c4892d5a4d1a7ee55b765d7a3d9e3f82"}, + {file = "mypy-1.7.1-py3-none-any.whl", hash = "sha256:f7c5d642db47376a0cc130f0de6d055056e010debdaf0707cd2b0fc7e7ef30ea"}, + {file = "mypy-1.7.1.tar.gz", hash = "sha256:fcb6d9afb1b6208b4c712af0dafdc650f518836065df0d4fb1d800f5d6773db2"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +requires_python = ">=3.5" +summary = "Type system extensions for programs checked with the mypy type checker." +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "pyobjc-core" +version = "10.0" +requires_python = ">=3.8" +summary = "Python<->ObjC Interoperability Module" +files = [ + {file = "pyobjc-core-10.0.tar.gz", hash = "sha256:3dd0a7b3acd7e0b8ffd3f5331b29a3aaebe79a03323e61efeece38627a6020b3"}, + {file = "pyobjc_core-10.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:2843ca32e86a01ccee67d7ad82a325ddd72d754929d1f2c0d96bc8741dc9af09"}, +] + +[[package]] +name = "pyobjc-framework-avfoundation" +version = "10.0" +requires_python = ">=3.8" +summary = "Wrappers for the framework AVFoundation on macOS" +dependencies = [ + "pyobjc-core>=10.0", + "pyobjc-framework-Cocoa>=10.0", + "pyobjc-framework-CoreAudio>=10.0", + "pyobjc-framework-CoreMedia>=10.0", + "pyobjc-framework-Quartz>=10.0", +] +files = [ + {file = "pyobjc-framework-AVFoundation-10.0.tar.gz", hash = "sha256:40366a8c6bb964e7b7263e8cf060350f69ad365e6a5356d6ccab9f256a9987f7"}, + {file = "pyobjc_framework_AVFoundation-10.0-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:b9b2e6731a64425f297bed68c6fc6e31e20965277c96012e62f7fa9059ff544e"}, + {file = "pyobjc_framework_AVFoundation-10.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:917185ff4e3f262b98cca2789ed68d43b0b111b161b9c8bda0bc7e6ab6def41c"}, + {file = "pyobjc_framework_AVFoundation-10.0-cp36-abi3-macosx_11_0_universal2.whl", hash = "sha256:d2bf8c4cfe72a24a4632d4152522c6b1b9b69b1bfadc7d76fd1082e7cc3cec7e"}, +] + +[[package]] +name = "pyobjc-framework-cocoa" +version = "10.0" +requires_python = ">=3.8" +summary = "Wrappers for the Cocoa frameworks on macOS" +dependencies = [ + "pyobjc-core>=10.0", +] +files = [ + {file = "pyobjc-framework-Cocoa-10.0.tar.gz", hash = "sha256:723421eff4f59e4ca9a9bb8ec6dafbc0f778141236fa85a49fdd86732d58a74c"}, + {file = "pyobjc_framework_Cocoa-10.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a81dabdc40268591e3196087388e680c6570fed1b521df9b04733cb3ece0414e"}, +] + +[[package]] +name = "pyobjc-framework-coreaudio" +version = "10.0" +requires_python = ">=3.8" +summary = "Wrappers for the framework CoreAudio on macOS" +dependencies = [ + "pyobjc-core>=10.0", + "pyobjc-framework-Cocoa>=10.0", +] +files = [ + {file = "pyobjc-framework-CoreAudio-10.0.tar.gz", hash = "sha256:6042e9fea80bf5c23a8a3a4a2888243b7152316275ab863ed6bc289eabdef9f1"}, + {file = "pyobjc_framework_CoreAudio-10.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:41c75e7a2e17619841c55a0be8c3c0666fad190a7142f1a80f01451184832cf3"}, +] + +[[package]] +name = "pyobjc-framework-coremedia" +version = "10.0" +requires_python = ">=3.8" +summary = "Wrappers for the framework CoreMedia on macOS" +dependencies = [ + "pyobjc-core>=10.0", + "pyobjc-framework-Cocoa>=10.0", +] +files = [ + {file = "pyobjc-framework-CoreMedia-10.0.tar.gz", hash = "sha256:27d0755cbd3ae3b487ace5e3233f0598b976905f43357b71fd73489865f7b9e1"}, + {file = "pyobjc_framework_CoreMedia-10.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d8bf02036e60c5f47b904a259e0665b7774d915eda95810566ca1b82a1be27e"}, +] + +[[package]] +name = "pyobjc-framework-mediaplayer" +version = "10.0" +requires_python = ">=3.8" +summary = "Wrappers for the framework MediaPlayer on macOS" +dependencies = [ + "pyobjc-core>=10.0", + "pyobjc-framework-AVFoundation>=10.0", +] +files = [ + {file = "pyobjc-framework-MediaPlayer-10.0.tar.gz", hash = "sha256:e3c66443fd13e5ddede01f15fdd9b635492edc239c4cd88fa540b866a76c1602"}, + {file = "pyobjc_framework_MediaPlayer-10.0-py2.py3-none-any.whl", hash = "sha256:19afc844bc204e008eac5f59699b93bae84e6235fa030d72651200414b019fc2"}, +] + +[[package]] +name = "pyobjc-framework-quartz" +version = "10.0" +requires_python = ">=3.8" +summary = "Wrappers for the Quartz frameworks on macOS" +dependencies = [ + "pyobjc-core>=10.0", + "pyobjc-framework-Cocoa>=10.0", +] +files = [ + {file = "pyobjc-framework-Quartz-10.0.tar.gz", hash = "sha256:ff7c938d9c8adff87d577d63e58f9be6e4bc75274384715fa7a20032a1ce8b0e"}, + {file = "pyobjc_framework_Quartz-10.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f0cc89890de411a341e90d2c4148831b6d241fca66e734b5470d27869c04e33c"}, +] + +[[package]] +name = "python-mpd2" +version = "3.1.0" +requires_python = ">=3.6" +summary = "A Python MPD client library" +files = [ + {file = "python-mpd2-3.1.0.tar.gz", hash = "sha256:f33c2cdb0d6baa74a36724f38c1c4a099a7ce2c8ec4a2bb7192150a5855df476"}, + {file = "python_mpd2-3.1.0-py2.py3-none-any.whl", hash = "sha256:c4d44a54e88a675f7301fdb11a1bd31165a6f51a664dd41e8137e92f7b02ebfb"}, +] + +[[package]] +name = "ruff" +version = "0.1.6" +requires_python = ">=3.7" +summary = "An extremely fast Python linter and code formatter, written in Rust." +files = [ + {file = "ruff-0.1.6-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:88b8cdf6abf98130991cbc9f6438f35f6e8d41a02622cc5ee130a02a0ed28703"}, + {file = "ruff-0.1.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5c549ed437680b6105a1299d2cd30e4964211606eeb48a0ff7a93ef70b902248"}, + {file = "ruff-0.1.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cf5f701062e294f2167e66d11b092bba7af6a057668ed618a9253e1e90cfd76"}, + {file = "ruff-0.1.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:05991ee20d4ac4bb78385360c684e4b417edd971030ab12a4fbd075ff535050e"}, + {file = "ruff-0.1.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87455a0c1f739b3c069e2f4c43b66479a54dea0276dd5d4d67b091265f6fd1dc"}, + {file = "ruff-0.1.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:683aa5bdda5a48cb8266fcde8eea2a6af4e5700a392c56ea5fb5f0d4bfdc0240"}, + {file = "ruff-0.1.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:137852105586dcbf80c1717facb6781555c4e99f520c9c827bd414fac67ddfb6"}, + {file = "ruff-0.1.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd98138a98d48a1c36c394fd6b84cd943ac92a08278aa8ac8c0fdefcf7138f35"}, + {file = "ruff-0.1.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a0cd909d25f227ac5c36d4e7e681577275fb74ba3b11d288aff7ec47e3ae745"}, + {file = "ruff-0.1.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8fd1c62a47aa88a02707b5dd20c5ff20d035d634aa74826b42a1da77861b5ff"}, + {file = "ruff-0.1.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fd89b45d374935829134a082617954120d7a1470a9f0ec0e7f3ead983edc48cc"}, + {file = "ruff-0.1.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:491262006e92f825b145cd1e52948073c56560243b55fb3b4ecb142f6f0e9543"}, + {file = "ruff-0.1.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ea284789861b8b5ca9d5443591a92a397ac183d4351882ab52f6296b4fdd5462"}, + {file = "ruff-0.1.6-py3-none-win32.whl", hash = "sha256:1610e14750826dfc207ccbcdd7331b6bd285607d4181df9c1c6ae26646d6848a"}, + {file = "ruff-0.1.6-py3-none-win_amd64.whl", hash = "sha256:4558b3e178145491e9bc3b2ee3c4b42f19d19384eaa5c59d10acf6e8f8b57e33"}, + {file = "ruff-0.1.6-py3-none-win_arm64.whl", hash = "sha256:03910e81df0d8db0e30050725a5802441c2022ea3ae4fe0609b76081731accbc"}, + {file = "ruff-0.1.6.tar.gz", hash = "sha256:1b09f29b16c6ead5ea6b097ef2764b42372aebe363722f1605ecbcd2b9207184"}, +] + +[[package]] +name = "typing-extensions" +version = "4.8.0" +requires_python = ">=3.8" +summary = "Backported and Experimental Type Hints for Python 3.8+" +files = [ + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, +] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..6b2529c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,65 @@ +[project] +name = "mpd-now-playable" +version = "0.0.1" +description = "Expose your MPD server as a 'now playable' app on MacOS" +authors = [ + {name = "Danielle McLean", email = "dani@00dani.me"}, +] +dependencies = [ + "async-lru>=2.0.4", + "attrs>=23.1.0", + "pyobjc-framework-MediaPlayer>=10.0", + "python-mpd2>=3.1.0", +] +requires-python = ">=3.12" +readme = "README.md" +license = {text = "MIT"} + +[project.scripts] +mpd-now-playable = 'mpd_now_playable.cli:main' + +[tool.pdm.scripts] +start = {call = 'mpd_now_playable.cli:main'} +lint = 'ruff check src/mpd_now_playable' +typecheck = 'mypy -p mpd_now_playable' +check = {composite = ['lint', 'typecheck']} + +[tool.pdm.dev-dependencies] +dev = [ + "mypy>=1.7.1", + "ruff>=0.1.6", +] + +[tool.mypy] +mypy_path = 'typings' + +[tool.ruff] +ignore-init-module-imports = true +select = [ + # pycodestyle + "E4", # import + "E7", # statement + "E9", # runtime + # flake8 + "F", # standard flake8 rules + "A", # flake8-builtins + "ANN", # flake8-annotations + "ASYNC", # flake8-async + "B", # flake8-bugbear + "S", # flake8-bandit + "INP", # flake8-no-pep420 + # isort + "I", + # mccabe + "C90", +] +ignore = [ + "ANN101", # missing-type-self +] + +[tool.ruff.lint.flake8-annotations] +mypy-init-return = true + +[tool.ruff.format] +# I prefer tabs for accessibility reasons. +indent-style = "tab"