py2tosc 0.1.0__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.
- py2tosc-0.1.0/CHANGELOG.md +99 -0
- py2tosc-0.1.0/LICENSE +10 -0
- py2tosc-0.1.0/PKG-INFO +119 -0
- py2tosc-0.1.0/README.md +93 -0
- py2tosc-0.1.0/pyproject.toml +76 -0
- py2tosc-0.1.0/pyproject.toml.orig +72 -0
- py2tosc-0.1.0/src/py2tosc/__init__.py +110 -0
- py2tosc-0.1.0/src/py2tosc/codec.py +512 -0
- py2tosc-0.1.0/src/py2tosc/control.py +391 -0
- py2tosc-0.1.0/src/py2tosc/defaults.py +207 -0
- py2tosc-0.1.0/src/py2tosc/document.py +238 -0
- py2tosc-0.1.0/src/py2tosc/enums.py +103 -0
- py2tosc-0.1.0/src/py2tosc/layout.py +194 -0
- py2tosc-0.1.0/src/py2tosc/messages.py +267 -0
- py2tosc-0.1.0/src/py2tosc/properties.py +345 -0
- py2tosc-0.1.0/src/py2tosc/py.typed +2 -0
- py2tosc-0.1.0/src/py2tosc/validate.py +199 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to py2tosc. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project uses [semantic versioning](https://semver.org/spec/v2.0.0.html) -- while the version is below 1.0, a minor bump may break the API.
|
|
4
|
+
|
|
5
|
+
## [0.1.0]
|
|
6
|
+
|
|
7
|
+
First release: py2tosc is a rewrite of [tosclib](https://github.com/AlbertoV5/tosclib) 0.3.5 by Alberto Valdez; the entries below describe what changed relative to it. Scripts written against tosclib will not run against py2tosc, and there are no compatibility shims. See [Coming from tosclib](https://shakfu.github.io/py2tosc/migrating/) for a name by name mapping.
|
|
8
|
+
|
|
9
|
+
### Addeds
|
|
10
|
+
|
|
11
|
+
- `Document`, with `load`, `loads`, `save` and `dumps` named after the `json` module's. `load` accepts a `.tosc` or an `.xml` without being told which, and `save` picks the format from the file extension.
|
|
12
|
+
|
|
13
|
+
- `Control` as the node model. Traversal returns controls, not `ET.Element`, so children no longer have to be re-wrapped by hand.
|
|
14
|
+
|
|
15
|
+
- `find`, `find_all` and `walk`, searching by name, by control type or both.
|
|
16
|
+
|
|
17
|
+
- `Control.copy`, duplicating a subtree with fresh node ids.
|
|
18
|
+
|
|
19
|
+
- `save(validate=True)` and `dumps(validate=True)`, which refuse to write a layout that has errors and raise `ValidationError` instead. Off by default.
|
|
20
|
+
|
|
21
|
+
- `validate`, an opt-in check for things TouchOSC rejects or ignores -- children on a control that cannot hold them, duplicate node ids, a property stored under the wrong type, or a format property on a control type that has no use for it. Advisory and never raises; custom properties are left alone. Every rule is corroborated against layouts the editor wrote.
|
|
22
|
+
|
|
23
|
+
- `GamepadMessage`. tosclib 0.3.x had a `ControlElements.GAMEPAD` enum member with no implementation behind it, so a layout containing a gamepad binding could not be read at all.
|
|
24
|
+
|
|
25
|
+
- `Frame` and `Color` named tuples. Colours accept normalised floats, 0-255 integers or hex strings.
|
|
26
|
+
|
|
27
|
+
- `__version__`, and an `__all__` that governs the public namespace.
|
|
28
|
+
|
|
29
|
+
- Support for reading and writing lexml version 6, the format TouchOSC 1.5 writes: the `<includes>` element and the `<noDuplicates>` message flag. Both are omitted from documents that declare an older version.
|
|
30
|
+
|
|
31
|
+
- Frames keep sub-pixel positions. TouchOSC stores frames like `x=417.439`, which earlier releases -- and the first draft of this one -- rounded to integers, moving the control.
|
|
32
|
+
|
|
33
|
+
- A test corpus of 42 layout files, including the twenty examples bundled with TouchOSC 1.5.2, spanning both format versions, and demo scripts that the test suite executes -- including a numpad built from nested layouts, a Lua script and LOCAL message wiring.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- **The API is `snake_case`.** `setColor` is `control.color = ...`, `findChildByName` is `find`. Property keys stay camelCase in the file, because that is what the format stores; `control.corner_radius` addresses the `cornerRadius` key.
|
|
38
|
+
|
|
39
|
+
- **Property and value data are native Python types**, not strings. `Value.locked` is a `bool`; `Property("textSize", 14).value` is `14`.
|
|
40
|
+
|
|
41
|
+
- **Reading no longer mutates the tree.** tosclib inserted empty `<messages>` and `<children>` elements into any control it wrapped.
|
|
42
|
+
|
|
43
|
+
- **Missing properties raise `AttributeError`** rather than returning `None`. Use `control.get(key)` where absence is expected.
|
|
44
|
+
|
|
45
|
+
- **Layouts are functions, not decorators.** `layout.row`, `layout.column` and `layout.grid` take the parent as an argument and return the controls they made, so nesting is ordinary function composition.
|
|
46
|
+
|
|
47
|
+
- Serialization is written directly rather than through `ElementTree`, so CDATA sections, element order and the XML declaration are preserved. Loading a layout and saving it reproduces the TouchOSC editor's own bytes exactly, in both the compressed and exported forms.
|
|
48
|
+
|
|
49
|
+
- Documentation moved from Sphinx to MkDocs.
|
|
50
|
+
|
|
51
|
+
- Packaging moved to `pyproject.toml` with the `uv_build` backend; `setup.py`, `tox.ini` and the three `requirements*.txt` files are gone.
|
|
52
|
+
|
|
53
|
+
- Releasing and publishing the documentation are driven from the Makefile rather than from CI. `make release-check` gates the declared version, the changelog entry and the state of the working tree; `make dist-check` rebuilds `dist/` from empty and validates it with `twine check --strict`; `make publish` uploads, behind a `CONFIRM=1` guard because a filename PyPI has accepted can never be reused. `make docs-deploy` pushes the documentation to `gh-pages`. Nothing is published automatically.
|
|
54
|
+
|
|
55
|
+
- CI runs the suite on Ubuntu against Python 3.10 through 3.14, and checks types, lint, a strict documentation build, and the built wheel, on every push and pull request.
|
|
56
|
+
|
|
57
|
+
### Removed
|
|
58
|
+
|
|
59
|
+
- **numpy is no longer a dependency.** py2tosc has no runtime dependencies at all. The layout arithmetic is plain Python.
|
|
60
|
+
|
|
61
|
+
- `ElementTOSC` and the `elements`, `controls` and `tosc` modules.
|
|
62
|
+
|
|
63
|
+
- `asCtrl`, which was declared, exported, and had `pass` for a body.
|
|
64
|
+
|
|
65
|
+
### Fixed
|
|
66
|
+
|
|
67
|
+
- `import tosclib` failed without `pyparsing`, an undeclared dependency reached by a stray `from pyparsing import Optional` that was never used. In a clean environment, `pip install tosclib` produced an unimportable package.
|
|
68
|
+
|
|
69
|
+
- Building a control with more than one message nested the second message inside the first, because the XML builder rebound its parent element inside a nested loop. An OSC and a MIDI binding on the same control produced a file TouchOSC could not load.
|
|
70
|
+
|
|
71
|
+
- MIDI bindings were written with a trigger's fields in place of the status bytes, from a leaked loop variable, and their values used a `<midivalue>` tag the format does not define. No MIDI binding tosclib produced was valid.
|
|
72
|
+
|
|
73
|
+
- `<dstID>` was written without its CDATA wrapper, unlike every other string in the format.
|
|
74
|
+
|
|
75
|
+
- Generated layouts declared `lexml version=3` and omitted `<includes>`.
|
|
76
|
+
|
|
77
|
+
- Default `connections` was five slots wide; TouchOSC 1.5 uses ten.
|
|
78
|
+
|
|
79
|
+
- Element truth-value testing, deprecated since Python 3.12.
|
|
80
|
+
|
|
81
|
+
- The test suite only passed when run from the repository root.
|
|
82
|
+
|
|
83
|
+
- CI declared its matrix key as `python-versions` but read `matrix.python-version`, so every leg silently tested the same interpreter, and the matrix targeted Python versions the package rejected.
|
|
84
|
+
|
|
85
|
+
- `numpy>=2` broke every layout: numpy 2 changed scalar `repr`, and the frames were stringified through it.
|
|
86
|
+
|
|
87
|
+
- `gridColor` was missing from XY and RADAR defaults, `textClip` and `textWrap` from TEXT, and `lines`/`linesDisplay` from XY.
|
|
88
|
+
|
|
89
|
+
- `GamepadMessage.connections` defaulted to ten characters. The gamepad field counts controllers, not network connections, and is four wide.
|
|
90
|
+
|
|
91
|
+
- `MidiType.NOTE_ON` was spelled `NOTEON`; the format uses `NOTE_ON`.
|
|
92
|
+
|
|
93
|
+
- `PAGER` carried an `x` value instead of `page`, and `ENCODER` was missing its `y`.
|
|
94
|
+
|
|
95
|
+
## Prior history
|
|
96
|
+
|
|
97
|
+
py2tosc began as a fork of [tosclib](https://github.com/AlbertoV5/tosclib), which had twelve releases between 2022-05-20 and 2022-06-09, ending at 0.3.5. That history belongs to a different distribution and is not restated here; see [the tosclib releases](https://pypi.org/project/tosclib/#history).
|
|
98
|
+
|
|
99
|
+
[0.1.0]: https://github.com/shakfu/py2tosc/releases/tag/v0.1.0
|
py2tosc-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Alberto Valdez (AlbertoV5) -- original tosclib
|
|
4
|
+
Copyright (c) 2026 Shakeeb Alireza -- py2tosc
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
7
|
+
|
|
8
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
9
|
+
|
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
py2tosc-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: py2tosc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Generate and edit TouchOSC layouts from Python.
|
|
5
|
+
Keywords: touchosc,osc,midi,tosc,hexler
|
|
6
|
+
Author: Shakeeb Alireza
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Project-URL: Homepage, https://github.com/shakfu/py2tosc
|
|
22
|
+
Project-URL: Documentation, https://shakfu.github.io/py2tosc
|
|
23
|
+
Project-URL: Repository, https://github.com/shakfu/py2tosc
|
|
24
|
+
Project-URL: Issues, https://github.com/shakfu/py2tosc/issues
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# py2tosc
|
|
28
|
+
|
|
29
|
+
Generate and edit TouchOSC layouts from Python.
|
|
30
|
+
|
|
31
|
+
  
|
|
32
|
+
|
|
33
|
+
py2tosc is a rewrite of [tosclib](https://github.com/AlbertoV5/tosclib) by [Alberto Valdez](https://github.com/AlbertoV5), whose work established the original mapping between the `.tosc` format and Python that this library is built on. The API is new and incompatible, but the knowledge of the format -- the control types, the property tables, the message layouts, and some of the tests and examples -- came from there, and is carried over with thanks. Original copyright is retained in [LICENSE](LICENSE).
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
**Disclaimer**: This project has no relation to Hexler, the developer of TouchOSC. Back up your layouts before editing them with third party tools.
|
|
37
|
+
|
|
38
|
+
## [Documentation](https://shakfu.github.io/py2tosc)
|
|
39
|
+
|
|
40
|
+
```console
|
|
41
|
+
$ pip install py2tosc
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
No dependencies. Python 3.10 or newer.
|
|
45
|
+
|
|
46
|
+
## What it does
|
|
47
|
+
|
|
48
|
+
A `.tosc` file is a zlib-compressed XML tree. py2tosc reads that tree into plain Python objects, lets you edit them, and writes it back out -- accurately enough that loading a layout and saving it again reproduces the editor's own bytes exactly, in both the compressed and exported forms.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
import py2tosc
|
|
52
|
+
|
|
53
|
+
doc = py2tosc.load("mixer.tosc")
|
|
54
|
+
|
|
55
|
+
for fader in doc.find_all(type="FADER"):
|
|
56
|
+
fader.color = "#e76f51"
|
|
57
|
+
fader.corner_radius = 2.0
|
|
58
|
+
|
|
59
|
+
doc.save("mixer-restyled.tosc")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Building one from scratch:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
import py2tosc
|
|
66
|
+
from py2tosc import layout
|
|
67
|
+
|
|
68
|
+
doc = py2tosc.Document.new(frame=(0, 0, 1024, 768))
|
|
69
|
+
|
|
70
|
+
strip = py2tosc.group(name="strip", frame=(0, 0, 1024, 768))
|
|
71
|
+
doc.add(strip)
|
|
72
|
+
|
|
73
|
+
for index, fader in enumerate(layout.row(strip, "FADER", sizes=8)):
|
|
74
|
+
fader.name = f"ch{index + 1}"
|
|
75
|
+
fader.messages.append(py2tosc.OscMessage())
|
|
76
|
+
|
|
77
|
+
doc.save("mixer.tosc")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Design
|
|
81
|
+
|
|
82
|
+
| Module | Holds |
|
|
83
|
+
|--------|-------|
|
|
84
|
+
| `enums` | TouchOSC's own vocabulary: control types, property types, conversions |
|
|
85
|
+
| `properties` | `Property`, `Frame`, `Color`, and the `snake_case` to camelCase mapping |
|
|
86
|
+
| `messages` | `Value`, `OscMessage`, `MidiMessage`, `LocalMessage`, `GamepadMessage` and their parts |
|
|
87
|
+
| `defaults` | The default property set for each control type |
|
|
88
|
+
| `control` | `Control`, the node model, plus a factory per control type |
|
|
89
|
+
| `codec` | Reading and writing the `.tosc` XML dialect, CDATA included |
|
|
90
|
+
| `document` | `Document`, `load`, `save`, `dumps` |
|
|
91
|
+
| `layout` | Row, column and grid arrangement, in plain arithmetic |
|
|
92
|
+
|
|
93
|
+
Property keys are camelCase in the file because that is what TouchOSC stores. The Python API is `snake_case` and translates at the boundary, so `control.corner_radius` addresses the `cornerRadius` key.
|
|
94
|
+
|
|
95
|
+
## Contributing
|
|
96
|
+
|
|
97
|
+
```console
|
|
98
|
+
$ make install # install the package and dev dependencies
|
|
99
|
+
$ make test # run the test suite
|
|
100
|
+
$ make docs-serve # serve the documentation with live reload
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`make help` lists the rest. The project uses [uv](https://docs.astral.sh/uv/) for environments, building and publishing.
|
|
104
|
+
|
|
105
|
+
### Releasing
|
|
106
|
+
|
|
107
|
+
1. Bump `version` in `pyproject.toml` and `__version__` in `src/py2tosc/__init__.py` -- a test fails if they disagree.
|
|
108
|
+
|
|
109
|
+
2. Date the release's section in `CHANGELOG.md`.
|
|
110
|
+
|
|
111
|
+
3. `make release-check`, then `make tag` and `git push origin vX.Y.Z`.
|
|
112
|
+
|
|
113
|
+
4. `make publish-test` to rehearse against TestPyPI, then `make publish CONFIRM=1`.
|
|
114
|
+
|
|
115
|
+
Publishing is manual and irreversible: a filename PyPI has accepted cannot be reused even after a delete, and no workflow re-checks the tag or the tree first. That makes `make release-check` in step 3 the only gate, so run it on a clean checkout. Both publish targets rebuild `dist/` from scratch and validate it with `twine check --strict` before uploading, and both need credentials in `~/.pypirc` or `TWINE_USERNAME`/`TWINE_PASSWORD`.
|
|
116
|
+
|
|
117
|
+
Documentation is published the same way, with `make docs-deploy`. Nothing deploys it automatically.
|
|
118
|
+
|
|
119
|
+
Bug reports and pull requests are welcome, including for the documentation.
|
py2tosc-0.1.0/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# py2tosc
|
|
2
|
+
|
|
3
|
+
Generate and edit TouchOSC layouts from Python.
|
|
4
|
+
|
|
5
|
+
  
|
|
6
|
+
|
|
7
|
+
py2tosc is a rewrite of [tosclib](https://github.com/AlbertoV5/tosclib) by [Alberto Valdez](https://github.com/AlbertoV5), whose work established the original mapping between the `.tosc` format and Python that this library is built on. The API is new and incompatible, but the knowledge of the format -- the control types, the property tables, the message layouts, and some of the tests and examples -- came from there, and is carried over with thanks. Original copyright is retained in [LICENSE](LICENSE).
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
**Disclaimer**: This project has no relation to Hexler, the developer of TouchOSC. Back up your layouts before editing them with third party tools.
|
|
11
|
+
|
|
12
|
+
## [Documentation](https://shakfu.github.io/py2tosc)
|
|
13
|
+
|
|
14
|
+
```console
|
|
15
|
+
$ pip install py2tosc
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
No dependencies. Python 3.10 or newer.
|
|
19
|
+
|
|
20
|
+
## What it does
|
|
21
|
+
|
|
22
|
+
A `.tosc` file is a zlib-compressed XML tree. py2tosc reads that tree into plain Python objects, lets you edit them, and writes it back out -- accurately enough that loading a layout and saving it again reproduces the editor's own bytes exactly, in both the compressed and exported forms.
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
import py2tosc
|
|
26
|
+
|
|
27
|
+
doc = py2tosc.load("mixer.tosc")
|
|
28
|
+
|
|
29
|
+
for fader in doc.find_all(type="FADER"):
|
|
30
|
+
fader.color = "#e76f51"
|
|
31
|
+
fader.corner_radius = 2.0
|
|
32
|
+
|
|
33
|
+
doc.save("mixer-restyled.tosc")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Building one from scratch:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
import py2tosc
|
|
40
|
+
from py2tosc import layout
|
|
41
|
+
|
|
42
|
+
doc = py2tosc.Document.new(frame=(0, 0, 1024, 768))
|
|
43
|
+
|
|
44
|
+
strip = py2tosc.group(name="strip", frame=(0, 0, 1024, 768))
|
|
45
|
+
doc.add(strip)
|
|
46
|
+
|
|
47
|
+
for index, fader in enumerate(layout.row(strip, "FADER", sizes=8)):
|
|
48
|
+
fader.name = f"ch{index + 1}"
|
|
49
|
+
fader.messages.append(py2tosc.OscMessage())
|
|
50
|
+
|
|
51
|
+
doc.save("mixer.tosc")
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Design
|
|
55
|
+
|
|
56
|
+
| Module | Holds |
|
|
57
|
+
|--------|-------|
|
|
58
|
+
| `enums` | TouchOSC's own vocabulary: control types, property types, conversions |
|
|
59
|
+
| `properties` | `Property`, `Frame`, `Color`, and the `snake_case` to camelCase mapping |
|
|
60
|
+
| `messages` | `Value`, `OscMessage`, `MidiMessage`, `LocalMessage`, `GamepadMessage` and their parts |
|
|
61
|
+
| `defaults` | The default property set for each control type |
|
|
62
|
+
| `control` | `Control`, the node model, plus a factory per control type |
|
|
63
|
+
| `codec` | Reading and writing the `.tosc` XML dialect, CDATA included |
|
|
64
|
+
| `document` | `Document`, `load`, `save`, `dumps` |
|
|
65
|
+
| `layout` | Row, column and grid arrangement, in plain arithmetic |
|
|
66
|
+
|
|
67
|
+
Property keys are camelCase in the file because that is what TouchOSC stores. The Python API is `snake_case` and translates at the boundary, so `control.corner_radius` addresses the `cornerRadius` key.
|
|
68
|
+
|
|
69
|
+
## Contributing
|
|
70
|
+
|
|
71
|
+
```console
|
|
72
|
+
$ make install # install the package and dev dependencies
|
|
73
|
+
$ make test # run the test suite
|
|
74
|
+
$ make docs-serve # serve the documentation with live reload
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`make help` lists the rest. The project uses [uv](https://docs.astral.sh/uv/) for environments, building and publishing.
|
|
78
|
+
|
|
79
|
+
### Releasing
|
|
80
|
+
|
|
81
|
+
1. Bump `version` in `pyproject.toml` and `__version__` in `src/py2tosc/__init__.py` -- a test fails if they disagree.
|
|
82
|
+
|
|
83
|
+
2. Date the release's section in `CHANGELOG.md`.
|
|
84
|
+
|
|
85
|
+
3. `make release-check`, then `make tag` and `git push origin vX.Y.Z`.
|
|
86
|
+
|
|
87
|
+
4. `make publish-test` to rehearse against TestPyPI, then `make publish CONFIRM=1`.
|
|
88
|
+
|
|
89
|
+
Publishing is manual and irreversible: a filename PyPI has accepted cannot be reused even after a delete, and no workflow re-checks the tag or the tree first. That makes `make release-check` in step 3 the only gate, so run it on a clean checkout. Both publish targets rebuild `dist/` from scratch and validate it with `twine check --strict` before uploading, and both need credentials in `~/.pypirc` or `TWINE_USERNAME`/`TWINE_PASSWORD`.
|
|
90
|
+
|
|
91
|
+
Documentation is published the same way, with `make docs-deploy`. Nothing deploys it automatically.
|
|
92
|
+
|
|
93
|
+
Bug reports and pull requests are welcome, including for the documentation.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "py2tosc"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Generate and edit TouchOSC layouts from Python."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
keywords = [
|
|
10
|
+
"touchosc",
|
|
11
|
+
"osc",
|
|
12
|
+
"midi",
|
|
13
|
+
"tosc",
|
|
14
|
+
"hexler",
|
|
15
|
+
]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Programming Language :: Python :: 3.14",
|
|
26
|
+
"Topic :: Multimedia :: Sound/Audio",
|
|
27
|
+
"Typing :: Typed",
|
|
28
|
+
]
|
|
29
|
+
dependencies = []
|
|
30
|
+
|
|
31
|
+
[[project.authors]]
|
|
32
|
+
name = "Shakeeb Alireza"
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/shakfu/py2tosc"
|
|
36
|
+
Documentation = "https://shakfu.github.io/py2tosc"
|
|
37
|
+
Repository = "https://github.com/shakfu/py2tosc"
|
|
38
|
+
Issues = "https://github.com/shakfu/py2tosc/issues"
|
|
39
|
+
|
|
40
|
+
[build-system]
|
|
41
|
+
requires = ["uv_build>=0.12.1,<0.13"]
|
|
42
|
+
build-backend = "uv_build"
|
|
43
|
+
|
|
44
|
+
[dependency-groups]
|
|
45
|
+
dev = [
|
|
46
|
+
"pytest>=8.0",
|
|
47
|
+
"pytest-cov>=5.0",
|
|
48
|
+
"mypy>=1.11",
|
|
49
|
+
"pillow>=10.0",
|
|
50
|
+
"ruff>=0.16.1",
|
|
51
|
+
"twine>=7.0.0",
|
|
52
|
+
]
|
|
53
|
+
docs = [
|
|
54
|
+
"mkdocs>=1.6",
|
|
55
|
+
"mkdocs-material>=9.5",
|
|
56
|
+
"mkdocstrings[python]>=0.26",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[tool.uv]
|
|
60
|
+
default-groups = [
|
|
61
|
+
"dev",
|
|
62
|
+
"docs",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[tool.uv.build-backend]
|
|
66
|
+
source-include = ["CHANGELOG.md"]
|
|
67
|
+
|
|
68
|
+
[tool.pytest.ini_options]
|
|
69
|
+
testpaths = ["tests"]
|
|
70
|
+
addopts = "-W error::DeprecationWarning"
|
|
71
|
+
|
|
72
|
+
[tool.mypy]
|
|
73
|
+
python_version = "3.10"
|
|
74
|
+
packages = ["py2tosc"]
|
|
75
|
+
strict_optional = true
|
|
76
|
+
warn_unused_ignores = true
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "py2tosc"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Generate and edit TouchOSC layouts from Python."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
authors = [{ name = "Shakeeb Alireza" }]
|
|
10
|
+
keywords = ["touchosc", "osc", "midi", "tosc", "hexler"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 4 - Beta",
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"Operating System :: OS Independent",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Programming Language :: Python :: 3.14",
|
|
21
|
+
"Topic :: Multimedia :: Sound/Audio",
|
|
22
|
+
"Typing :: Typed",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
# py2tosc has no runtime dependencies. It needs nothing beyond the standard
|
|
26
|
+
# library, which is the point of dropping numpy in 1.0.
|
|
27
|
+
dependencies = []
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://github.com/shakfu/py2tosc"
|
|
31
|
+
Documentation = "https://shakfu.github.io/py2tosc"
|
|
32
|
+
Repository = "https://github.com/shakfu/py2tosc"
|
|
33
|
+
Issues = "https://github.com/shakfu/py2tosc/issues"
|
|
34
|
+
|
|
35
|
+
[build-system]
|
|
36
|
+
requires = ["uv_build>=0.12.1,<0.13"]
|
|
37
|
+
build-backend = "uv_build"
|
|
38
|
+
|
|
39
|
+
[dependency-groups]
|
|
40
|
+
dev = [
|
|
41
|
+
"pytest>=8.0",
|
|
42
|
+
"pytest-cov>=5.0",
|
|
43
|
+
"mypy>=1.11",
|
|
44
|
+
# Only the image converter demo needs this, but the demo is tested.
|
|
45
|
+
"pillow>=10.0",
|
|
46
|
+
"ruff>=0.16.1",
|
|
47
|
+
"twine>=7.0.0",
|
|
48
|
+
]
|
|
49
|
+
docs = [
|
|
50
|
+
"mkdocs>=1.6",
|
|
51
|
+
"mkdocs-material>=9.5",
|
|
52
|
+
"mkdocstrings[python]>=0.26",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[tool.uv.build-backend]
|
|
56
|
+
# Ship the changelog in the sdist alongside README and LICENSE.
|
|
57
|
+
source-include = ["CHANGELOG.md"]
|
|
58
|
+
|
|
59
|
+
[tool.uv]
|
|
60
|
+
# Both groups are installed by a bare `uv sync`, so `make docs` and `make test`
|
|
61
|
+
# work without having to name a group.
|
|
62
|
+
default-groups = ["dev", "docs"]
|
|
63
|
+
|
|
64
|
+
[tool.pytest.ini_options]
|
|
65
|
+
testpaths = ["tests"]
|
|
66
|
+
addopts = "-W error::DeprecationWarning"
|
|
67
|
+
|
|
68
|
+
[tool.mypy]
|
|
69
|
+
python_version = "3.10"
|
|
70
|
+
packages = ["py2tosc"]
|
|
71
|
+
strict_optional = true
|
|
72
|
+
warn_unused_ignores = true
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Generate and edit TouchOSC layouts from Python.
|
|
2
|
+
|
|
3
|
+
```python
|
|
4
|
+
import py2tosc
|
|
5
|
+
|
|
6
|
+
doc = py2tosc.load("layout.tosc")
|
|
7
|
+
for fader in doc.find_all(type="FADER"):
|
|
8
|
+
fader.color = "#e76f51"
|
|
9
|
+
doc.save("out.tosc")
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
This project has no relation to Hexler, the developer of TouchOSC. Back up your
|
|
13
|
+
layouts before editing them with third party tools.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from . import layout
|
|
17
|
+
from .control import (
|
|
18
|
+
Control,
|
|
19
|
+
box,
|
|
20
|
+
button,
|
|
21
|
+
encoder,
|
|
22
|
+
fader,
|
|
23
|
+
grid,
|
|
24
|
+
group,
|
|
25
|
+
label,
|
|
26
|
+
pager,
|
|
27
|
+
radar,
|
|
28
|
+
radial,
|
|
29
|
+
radio,
|
|
30
|
+
text,
|
|
31
|
+
xy,
|
|
32
|
+
)
|
|
33
|
+
from .document import Document, dumps, load, loads, save
|
|
34
|
+
from .enums import (
|
|
35
|
+
ControlType,
|
|
36
|
+
Conversion,
|
|
37
|
+
MidiType,
|
|
38
|
+
PartialType,
|
|
39
|
+
PropertyType,
|
|
40
|
+
TriggerCondition,
|
|
41
|
+
)
|
|
42
|
+
from .messages import (
|
|
43
|
+
GamepadMessage,
|
|
44
|
+
LocalMessage,
|
|
45
|
+
Message,
|
|
46
|
+
MidiCommand,
|
|
47
|
+
MidiMessage,
|
|
48
|
+
MidiValue,
|
|
49
|
+
OscMessage,
|
|
50
|
+
Partial,
|
|
51
|
+
Trigger,
|
|
52
|
+
Value,
|
|
53
|
+
)
|
|
54
|
+
from .properties import Color, Frame, Property, to_color, to_frame
|
|
55
|
+
from .validate import Issue, ValidationError, validate
|
|
56
|
+
|
|
57
|
+
#: Keep in step with `version` in pyproject.toml, which the build backend reads
|
|
58
|
+
#: and which `uv_build` requires to be static. `test_version_is_declared_once`
|
|
59
|
+
#: fails if the two drift apart.
|
|
60
|
+
__version__ = "0.1.0"
|
|
61
|
+
|
|
62
|
+
# Sorted rather than grouped by topic, because RUF022 asks for it and the
|
|
63
|
+
# grouping lives in the API reference instead. See docs/api/.
|
|
64
|
+
__all__ = [
|
|
65
|
+
"Color",
|
|
66
|
+
"Control",
|
|
67
|
+
"ControlType",
|
|
68
|
+
"Conversion",
|
|
69
|
+
"Document",
|
|
70
|
+
"Frame",
|
|
71
|
+
"GamepadMessage",
|
|
72
|
+
"Issue",
|
|
73
|
+
"LocalMessage",
|
|
74
|
+
"Message",
|
|
75
|
+
"MidiCommand",
|
|
76
|
+
"MidiMessage",
|
|
77
|
+
"MidiType",
|
|
78
|
+
"MidiValue",
|
|
79
|
+
"OscMessage",
|
|
80
|
+
"Partial",
|
|
81
|
+
"PartialType",
|
|
82
|
+
"Property",
|
|
83
|
+
"PropertyType",
|
|
84
|
+
"Trigger",
|
|
85
|
+
"TriggerCondition",
|
|
86
|
+
"ValidationError",
|
|
87
|
+
"Value",
|
|
88
|
+
"__version__",
|
|
89
|
+
"box",
|
|
90
|
+
"button",
|
|
91
|
+
"dumps",
|
|
92
|
+
"encoder",
|
|
93
|
+
"fader",
|
|
94
|
+
"grid",
|
|
95
|
+
"group",
|
|
96
|
+
"label",
|
|
97
|
+
"layout",
|
|
98
|
+
"load",
|
|
99
|
+
"loads",
|
|
100
|
+
"pager",
|
|
101
|
+
"radar",
|
|
102
|
+
"radial",
|
|
103
|
+
"radio",
|
|
104
|
+
"save",
|
|
105
|
+
"text",
|
|
106
|
+
"to_color",
|
|
107
|
+
"to_frame",
|
|
108
|
+
"validate",
|
|
109
|
+
"xy",
|
|
110
|
+
]
|