pyblu 2.0.2__tar.gz → 2.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "Python 3",
3
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
4
+ "image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye",
5
+
6
+ "postCreateCommand": "bash .devcontainer/setup",
7
+
8
+ "customizations": {
9
+ "vscode": {
10
+ "extensions": [
11
+ "github.copilot"
12
+ ]
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+ curl -sSL https://install.python-poetry.org | python3
3
+ poetry config virtualenvs.in-project true
4
+ poetry install
@@ -0,0 +1,23 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for more information:
4
+ # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5
+ # https://containers.dev/guide/dependabot
6
+
7
+ version: 2
8
+ updates:
9
+ - package-ecosystem: "devcontainers"
10
+ directory: "/"
11
+ schedule:
12
+ interval: monthly
13
+ - package-ecosystem: "pip"
14
+ directory: "/"
15
+ schedule:
16
+ interval: monthly
17
+ groups:
18
+ all:
19
+ patterns:
20
+ - "*"
21
+ update-types:
22
+ - patch
23
+ - minor
@@ -0,0 +1,53 @@
1
+ name: Publish docs
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - '*'
7
+ tags:
8
+ - 'v*'
9
+ paths:
10
+ - src/**
11
+ - docs/**
12
+ - pyproject.toml
13
+ - poetry.lock
14
+ - .github/workflows/docs.yml
15
+
16
+ permissions:
17
+ contents: read
18
+ pages: write
19
+ id-token: write
20
+
21
+ concurrency:
22
+ group: "pages"
23
+ cancel-in-progress: false
24
+
25
+ jobs:
26
+ build:
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - name: Checkout
30
+ uses: actions/checkout@v4
31
+ - uses: actions/setup-python@v5
32
+ with:
33
+ python-version: 3.11
34
+ - name: Install uv
35
+ uses: astral-sh/setup-uv@v6
36
+ - name: Install dependencies
37
+ run: uv sync
38
+ - name: Sphinx build
39
+ run: uv run sphinx-build -b html docs _site
40
+ - name: Upload artifact
41
+ uses: actions/upload-pages-artifact@v3
42
+
43
+ deploy:
44
+ environment:
45
+ name: github-pages
46
+ url: ${{ steps.deployment.outputs.page_url }}
47
+ runs-on: ubuntu-latest
48
+ if: ${{ startsWith(github.ref, 'refs/tags/v') }}
49
+ needs: build
50
+ steps:
51
+ - name: Deploy to GitHub Pages
52
+ id: deployment
53
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,65 @@
1
+ name: Test
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - '*'
7
+ paths:
8
+ - src/**
9
+ - tests/**
10
+ - pyproject.toml
11
+ - .github/workflows/test.yml
12
+
13
+ jobs:
14
+ lint:
15
+ runs-on: ubuntu-latest
16
+
17
+ steps:
18
+ - name: Checkout code
19
+ uses: actions/checkout@v2
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: 3.12
24
+ - name: Install uv
25
+ uses: astral-sh/setup-uv@v6
26
+ - name: Install dependencies
27
+ run: uv sync
28
+ - name: Run pylint
29
+ run: uv run pylint src tests
30
+ - name: Run black
31
+ run: uv run black --check src tests
32
+
33
+ typecheck:
34
+ runs-on: ubuntu-latest
35
+
36
+ steps:
37
+ - name: Checkout code
38
+ uses: actions/checkout@v2
39
+ - name: Set up Python
40
+ uses: actions/setup-python@v5
41
+ with:
42
+ python-version: 3.12
43
+ - name: Install uv
44
+ uses: astral-sh/setup-uv@v6
45
+ - name: Install dependencies
46
+ run: uv sync
47
+ - name: Run mypy
48
+ run: uv run mypy src
49
+
50
+ test:
51
+ runs-on: ubuntu-latest
52
+
53
+ steps:
54
+ - name: Checkout code
55
+ uses: actions/checkout@v2
56
+ - name: Set up Python
57
+ uses: actions/setup-python@v5
58
+ with:
59
+ python-version: 3.12
60
+ - name: Install uv
61
+ uses: astral-sh/setup-uv@v6
62
+ - name: Install dependencies
63
+ run: uv sync
64
+ - name: Run pytest
65
+ run: uv run pytest
pyblu-2.0.3/.gitignore ADDED
@@ -0,0 +1,169 @@
1
+ # uv
2
+ uv.lock
3
+
4
+ # sphinx documentation
5
+ /_site/
6
+
7
+ # JetBrains
8
+ .idea/
9
+
10
+ # Byte-compiled / optimized / DLL files
11
+ __pycache__/
12
+ *.py[cod]
13
+ *$py.class
14
+
15
+ # C extensions
16
+ *.so
17
+
18
+ # Distribution / packaging
19
+ .Python
20
+ build/
21
+ develop-eggs/
22
+ dist/
23
+ downloads/
24
+ eggs/
25
+ .eggs/
26
+ lib/
27
+ lib64/
28
+ parts/
29
+ sdist/
30
+ var/
31
+ wheels/
32
+ share/python-wheels/
33
+ *.egg-info/
34
+ .installed.cfg
35
+ *.egg
36
+ MANIFEST
37
+
38
+ # PyInstaller
39
+ # Usually these files are written by a python script from a template
40
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
41
+ *.manifest
42
+ *.spec
43
+
44
+ # Installer logs
45
+ pip-log.txt
46
+ pip-delete-this-directory.txt
47
+
48
+ # Unit test / coverage reports
49
+ htmlcov/
50
+ .tox/
51
+ .nox/
52
+ .coverage
53
+ .coverage.*
54
+ .cache
55
+ nosetests.xml
56
+ coverage.xml
57
+ *.cover
58
+ *.py,cover
59
+ .hypothesis/
60
+ .pytest_cache/
61
+ cover/
62
+
63
+ # Translations
64
+ *.mo
65
+ *.pot
66
+
67
+ # Django stuff:
68
+ *.log
69
+ local_settings.py
70
+ db.sqlite3
71
+ db.sqlite3-journal
72
+
73
+ # Flask stuff:
74
+ instance/
75
+ .webassets-cache
76
+
77
+ # Scrapy stuff:
78
+ .scrapy
79
+
80
+ # Sphinx documentation
81
+ docs/_build/
82
+
83
+ # PyBuilder
84
+ .pybuilder/
85
+ target/
86
+
87
+ # Jupyter Notebook
88
+ .ipynb_checkpoints
89
+
90
+ # IPython
91
+ profile_default/
92
+ ipython_config.py
93
+
94
+ # pyenv
95
+ # For a library or package, you might want to ignore these files since the code is
96
+ # intended to run in multiple environments; otherwise, check them in:
97
+ # .python-version
98
+
99
+ # pipenv
100
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
101
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
102
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
103
+ # install all needed dependencies.
104
+ #Pipfile.lock
105
+
106
+ # poetry
107
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
108
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
109
+ # commonly ignored for libraries.
110
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
111
+ #poetry.lock
112
+
113
+ # pdm
114
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
115
+ #pdm.lock
116
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
117
+ # in version control.
118
+ # https://pdm.fming.dev/#use-with-ide
119
+ .pdm.toml
120
+
121
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
122
+ __pypackages__/
123
+
124
+ # Celery stuff
125
+ celerybeat-schedule
126
+ celerybeat.pid
127
+
128
+ # SageMath parsed files
129
+ *.sage.py
130
+
131
+ # Environments
132
+ .env
133
+ .venv
134
+ env/
135
+ venv/
136
+ ENV/
137
+ env.bak/
138
+ venv.bak/
139
+
140
+ # Spyder project settings
141
+ .spyderproject
142
+ .spyproject
143
+
144
+ # Rope project settings
145
+ .ropeproject
146
+
147
+ # mkdocs documentation
148
+ /site
149
+
150
+ # mypy
151
+ .mypy_cache/
152
+ .dmypy.json
153
+ dmypy.json
154
+
155
+ # Pyre type checker
156
+ .pyre/
157
+
158
+ # pytype static type analyzer
159
+ .pytype/
160
+
161
+ # Cython debug symbols
162
+ cython_debug/
163
+
164
+ # PyCharm
165
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
166
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
167
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
168
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
169
+ #.idea/
@@ -0,0 +1,20 @@
1
+ <component name="ProjectRunConfigurationManager">
2
+ <configuration default="false" name="Tests" type="tests" factoryName="py.test">
3
+ <module name="pyblu" />
4
+ <option name="ENV_FILES" value="" />
5
+ <option name="INTERPRETER_OPTIONS" value="" />
6
+ <option name="PARENT_ENVS" value="true" />
7
+ <option name="SDK_HOME" value="" />
8
+ <option name="WORKING_DIRECTORY" value="" />
9
+ <option name="IS_MODULE_SDK" value="true" />
10
+ <option name="ADD_CONTENT_ROOTS" value="true" />
11
+ <option name="ADD_SOURCE_ROOTS" value="true" />
12
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
13
+ <option name="_new_keywords" value="&quot;&quot;" />
14
+ <option name="_new_parameters" value="&quot;&quot;" />
15
+ <option name="_new_additionalArguments" value="&quot;&quot;" />
16
+ <option name="_new_target" value="&quot;tests&quot;" />
17
+ <option name="_new_targetType" value="&quot;PYTHON&quot;" />
18
+ <method v="2" />
19
+ </configuration>
20
+ </component>
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "Tests",
6
+ "type": "debugpy",
7
+ "request": "launch",
8
+ "module": "pytest",
9
+ "args": [
10
+ "${workspaceFolder}/tests"
11
+ ],
12
+ }
13
+ ]
14
+ }
@@ -1,19 +1,12 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: pyblu
3
- Version: 2.0.2
4
- Summary:
5
- License: MIT
6
- Author: Louis Christ
7
- Author-email: mail@louischrist.de
8
- Requires-Python: >=3.11,<4.0
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.11
12
- Classifier: Programming Language :: Python :: 3.12
13
- Classifier: Programming Language :: Python :: 3.13
14
- Requires-Dist: aiohttp (>=3.11.11)
15
- Requires-Dist: lxml (>=5.0.0)
16
- Project-URL: Repository, https://github.com/LouisChrist/pyblu
3
+ Version: 2.0.3
4
+ Project-URL: repository, https://github.com/LouisChrist/pyblu
5
+ Author-email: Louis Christ <mail@louischrist.de>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Dist: aiohttp>=3.11.11
9
+ Requires-Dist: lxml>=5.0.0
17
10
  Description-Content-Type: text/markdown
18
11
 
19
12
  # pyblu
@@ -47,4 +40,3 @@ pip install pyblu
47
40
  ```
48
41
 
49
42
 
50
-
@@ -0,0 +1,45 @@
1
+ API Reference
2
+ =============
3
+
4
+ Main Classes
5
+ ------------
6
+
7
+ .. autoclass:: pyblu.Player
8
+ :members:
9
+ :special-members: __init__
10
+
11
+ Data Classes
12
+ ------------
13
+
14
+ .. autoclass:: pyblu.Status
15
+ :members:
16
+
17
+ .. autoclass:: pyblu.Volume
18
+ :members:
19
+
20
+ .. autoclass:: pyblu.SyncStatus
21
+ :members:
22
+
23
+ .. autoclass:: pyblu.PairedPlayer
24
+ :members:
25
+
26
+ .. autoclass:: pyblu.Preset
27
+ :members:
28
+
29
+ .. autoclass:: pyblu.PlayQueue
30
+ :members:
31
+
32
+ .. autoclass:: pyblu.Input
33
+ :members:
34
+
35
+ Exceptions
36
+ ----------
37
+
38
+ .. autoclass:: pyblu.errors.PlayerError
39
+ :members:
40
+
41
+ .. autoclass:: pyblu.errors.PlayerUnreachableError
42
+ :members:
43
+
44
+ .. autoclass:: pyblu.errors.PlayerUnexpectedResponseError
45
+ :members:
@@ -0,0 +1,27 @@
1
+ # Configuration file for the Sphinx documentation builder.
2
+ #
3
+ # For the full list of built-in configuration values, see the documentation:
4
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html
5
+
6
+ # -- Project information -----------------------------------------------------
7
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
8
+
9
+ project = 'pyblu'
10
+ copyright = '2024, Louis Christ'
11
+ author = 'Louis Christ'
12
+
13
+ # -- General configuration ---------------------------------------------------
14
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
15
+
16
+ extensions = ['sphinx.ext.autodoc']
17
+
18
+ templates_path = ['_templates']
19
+ exclude_patterns = []
20
+
21
+
22
+
23
+ # -- Options for HTML output -------------------------------------------------
24
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
25
+
26
+ html_theme = 'alabaster'
27
+ html_static_path = ['_static']
@@ -0,0 +1,22 @@
1
+ pyblu
2
+ ============
3
+
4
+ This is an Python library for interfacing with BluOS player. It uses the
5
+ `BluOS API <https://bluesound-deutschland.de/wp-content/uploads/2022/01/Custom-Integration-API-v1.0_March-2021.pdf>`_
6
+ to control and query the status of BluOS players.
7
+
8
+ Basic usage example:
9
+
10
+ .. code-block:: python
11
+
12
+ from pyblu import Player
13
+
14
+ async def main():
15
+ async with Player("<host>") as player:
16
+ status = await player.status()
17
+ print(status)
18
+
19
+ .. toctree::
20
+ :maxdepth: 2
21
+
22
+ api
@@ -0,0 +1,54 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "pyblu"
7
+ version = "2.0.3"
8
+ description = ""
9
+ license = "MIT"
10
+ authors = [{ name = "Louis Christ", email = "mail@louischrist.de" }]
11
+ readme = "README.md"
12
+ dependencies = [
13
+ "aiohttp >= 3.11.11",
14
+ "lxml >= 5.0.0"]
15
+
16
+ [project.urls]
17
+ repository = "https://github.com/LouisChrist/pyblu"
18
+
19
+ [tool.hatch.build.targets.wheel]
20
+ packages = ["src/pyblu"]
21
+
22
+ [tool.uv]
23
+ dev-dependencies = [
24
+ "pylint >= 3.2.6",
25
+ "black >= 24.8.0",
26
+ "pytest >= 8.3.2",
27
+ "aioresponses >= 0.7.6",
28
+ "pytest-asyncio >= 0.24.0",
29
+ "sphinx >= 8.0.2",
30
+ "invoke >= 2.2.0",
31
+ "semver >= 3.0.2",
32
+ "mypy >= 1.11.2",
33
+ "pygithub >= 2.4.0",
34
+ "types-lxml >= 2024.8.7"]
35
+
36
+ [tool.pylint."messages control"]
37
+ disable = [
38
+ "missing-function-docstring",
39
+ "missing-module-docstring",
40
+ "missing-class-docstring",
41
+ "too-many-instance-attributes",
42
+ "too-many-public-methods",
43
+ "duplicate-code",
44
+ ]
45
+
46
+ [tool.pylint.format]
47
+ max-line-length = 160
48
+
49
+ [tool.black]
50
+ line-length = 160
51
+
52
+ [tool.pytest.ini_options]
53
+ pythonpath = "src"
54
+ asyncio_mode = "auto"
pyblu-2.0.3/tasks.py ADDED
@@ -0,0 +1,120 @@
1
+ import re
2
+ import os
3
+
4
+ from invoke import task, Context
5
+ from semver import Version
6
+ import github
7
+
8
+
9
+ def _commits_with_version_change(ctx: Context):
10
+ commits = ctx.run("git log --pretty=format:'%h'", hide=True).stdout.split("\n")
11
+ for commit in commits[:-1]:
12
+ diff = ctx.run(f"git diff {commit}~ {commit} pyproject.toml", hide=True).stdout.split("\n")
13
+ version_lines = [line for line in diff if line.startswith("+version = ")]
14
+ if not version_lines:
15
+ continue
16
+
17
+ yield commit, version_lines[0].split(" = ")[1].strip('"')
18
+
19
+
20
+ def _get_tagged_versions(ctx: Context):
21
+ tags = ctx.run("git tag", hide=True).stdout.split("\n")
22
+ return [tag[1:] for tag in tags if re.match(r"v\d+\.\d+\.\d+", tag)]
23
+
24
+
25
+ @task
26
+ def add_missing_tags(ctx: Context):
27
+ tagged_versions = _get_tagged_versions(ctx)
28
+ missing_commits_with_versions = [x for x in _commits_with_version_change(ctx) if x[1] not in tagged_versions]
29
+
30
+ if not missing_commits_with_versions:
31
+ print("No new versions to tag")
32
+ return
33
+
34
+ for commit, version in missing_commits_with_versions:
35
+ print(f"Tagging {commit} as {version}")
36
+ ctx.run(f"git tag -m v{version} v{version} {commit}", hide=True)
37
+
38
+
39
+ @task
40
+ def release(ctx: Context):
41
+ githubToken = os.getenv("GITHUB_TOKEN_PYBLU")
42
+ if githubToken is None:
43
+ print("GITHUB_TOKEN_PYBLU environment variable is required")
44
+ exit(1)
45
+ githubAuth = github.Auth.Token(githubToken)
46
+ gh = github.Github(auth=githubAuth)
47
+ try:
48
+ githubRepo = gh.get_repo("LouisChrist/pyblu")
49
+ except github.GithubException:
50
+ print("No access to LouisChrist/pyblue")
51
+ exit(1)
52
+
53
+ current_branch = ctx.run("git branch --show-current", hide=True).stdout.strip()
54
+ if current_branch != "main":
55
+ print("You must be on the main branch to release")
56
+ exit(1)
57
+
58
+ any_changes = ctx.run("git status --porcelain", hide=True).stdout.strip()
59
+ if any_changes:
60
+ print("There are uncommited changes")
61
+ exit(1)
62
+
63
+ version = ctx.run("uv version --short", hide=True).stdout.strip()
64
+ version = Version.parse(version)
65
+
66
+ print(f"patch: {version.bump_patch()}")
67
+ print(f"minor: {version.bump_minor()}")
68
+ print(f"major: {version.bump_major()}")
69
+ choice = input("Select version to bump [patch/minor/major]: ")
70
+ match choice:
71
+ case "patch":
72
+ bumped_version = version.bump_patch()
73
+ case "minor":
74
+ bumped_version = version.bump_minor()
75
+ case "major":
76
+ bumped_version = version.bump_major()
77
+ case _:
78
+ print("Invalid choice")
79
+ exit(1)
80
+
81
+ ctx.run(f"uv version --bump {choice}")
82
+
83
+ print(f"Creating commit with tag v{bumped_version}")
84
+ ctx.run("git add pyproject.toml", hide=True)
85
+ ctx.run(f"git commit -m 'Release v{bumped_version}'", hide=True)
86
+ ctx.run(f"git tag -m v{bumped_version} v{bumped_version}", hide=True)
87
+
88
+ print("Pushing changes")
89
+ ctx.run("git push --follow-tags", hide=True)
90
+
91
+ print("Creating release")
92
+ githubRepo.create_git_release(f"v{bumped_version}", f"v{bumped_version}", generate_release_notes=True)
93
+
94
+ print("Building and publishing package")
95
+ ctx.run("uv build")
96
+ ctx.run("uv publish")
97
+
98
+ print(f"Release v{bumped_version} created and published")
99
+
100
+
101
+ @task
102
+ def format_and_lint(ctx: Context):
103
+ ctx.run("black src tests")
104
+ ctx.run("pylint -f colorized src tests")
105
+
106
+
107
+ @task
108
+ def test(ctx: Context):
109
+ ctx.run("pytest tests --color=yes")
110
+
111
+
112
+ @task
113
+ def mypy(ctx: Context):
114
+ ctx.run("mypy src")
115
+
116
+
117
+ @task
118
+ def build_docs(ctx: Context):
119
+ print("Building docs")
120
+ ctx.run("sphinx-build -b html docs _site", hide=True)