xair-api 2.4.1__py3-none-any.whl → 2.4.2__py3-none-any.whl

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.
xair_api/xair.py CHANGED
@@ -1,193 +1,193 @@
1
- import abc
2
- import logging
3
- import threading
4
- import time
5
- from pathlib import Path
6
- from typing import Optional, Union
7
-
8
- try:
9
- import tomllib
10
- except ModuleNotFoundError:
11
- import tomli as tomllib
12
-
13
- from pythonosc.dispatcher import Dispatcher
14
- from pythonosc.osc_message_builder import OscMessageBuilder
15
- from pythonosc.osc_server import BlockingOSCUDPServer
16
-
17
- from . import adapter, kinds, util
18
- from .bus import Bus
19
- from .config import Config
20
- from .dca import DCA
21
- from .errors import XAirRemoteConnectionTimeoutError, XAirRemoteError
22
- from .fx import FX, FXSend
23
- from .headamp import HeadAmp
24
- from .kinds import KindMap
25
- from .lr import LR
26
- from .rtn import AuxRtn, FxRtn
27
- from .strip import Strip
28
-
29
- logger = logging.getLogger(__name__)
30
-
31
-
32
- class OSCClientServer(BlockingOSCUDPServer):
33
- def __init__(self, address: str, dispatcher: Dispatcher):
34
- super().__init__(('', 0), dispatcher)
35
- self.xr_address = address
36
-
37
- def send_message(self, address: str, vals: Optional[Union[str, list]]):
38
- builder = OscMessageBuilder(address=address)
39
- vals = vals if vals is not None else []
40
- if not isinstance(vals, list):
41
- vals = [vals]
42
- for val in vals:
43
- builder.add_arg(val)
44
- msg = builder.build()
45
- self.socket.sendto(msg.dgram, self.xr_address)
46
-
47
-
48
- class XAirRemote(abc.ABC):
49
- """Handles the communication with the mixer via the OSC protocol"""
50
-
51
- _info_response = []
52
-
53
- def __init__(self, **kwargs):
54
- dispatcher = Dispatcher()
55
- dispatcher.set_default_handler(self.msg_handler)
56
- self.xair_ip = kwargs['ip'] or self._ip_from_toml()
57
- self.xair_port = kwargs['port']
58
- self._delay = kwargs['delay']
59
- self.connect_timeout = kwargs['connect_timeout']
60
- self.logger = logger.getChild(self.__class__.__name__)
61
- if not self.xair_ip:
62
- raise XAirRemoteError('No valid ip detected')
63
- self.server = OSCClientServer((self.xair_ip, self.xair_port), dispatcher)
64
-
65
- def __enter__(self):
66
- self.worker = threading.Thread(target=self.run_server, daemon=True)
67
- self.worker.start()
68
- self.validate_connection()
69
- return self
70
-
71
- def _ip_from_toml(self) -> str:
72
- filepath = Path.cwd() / 'config.toml'
73
- with open(filepath, 'rb') as f:
74
- conn = tomllib.load(f)
75
- return conn['connection'].get('ip')
76
-
77
- @util.timeout
78
- def validate_connection(self):
79
- if not self.query('/xinfo'):
80
- raise XAirRemoteConnectionTimeoutError(self.xair_ip, self.xair_port)
81
- self.logger.info(
82
- f'Successfully connected to {self.info_response[2]} at {self.info_response[0]}.'
83
- )
84
-
85
- @property
86
- def info_response(self):
87
- return self._info_response
88
-
89
- def run_server(self):
90
- self.server.serve_forever()
91
-
92
- def msg_handler(self, addr, *data):
93
- self.logger.debug(f"received: {addr} {data if data else ''}")
94
- self._info_response = data[:]
95
-
96
- def send(self, addr: str, param: Optional[str] = None):
97
- self.logger.debug(f"sending: {addr} {param if param is not None else ''}")
98
- self.server.send_message(addr, param)
99
-
100
- def query(self, address):
101
- self.send(address)
102
- time.sleep(self._delay)
103
- return self.info_response
104
-
105
- def __exit__(self, exc_type, exc_value, exc_tr):
106
- self.server.shutdown()
107
-
108
-
109
- def _make_remote(kind: KindMap) -> XAirRemote:
110
- """
111
- Creates a new XAIR remote class.
112
-
113
- The returned class will subclass XAirRemote.
114
- """
115
-
116
- def init_x32(self, *args, **kwargs):
117
- defaultkwargs = {
118
- 'ip': None,
119
- 'port': 10023,
120
- 'delay': 0.02,
121
- 'connect_timeout': 2,
122
- }
123
- kwargs = defaultkwargs | kwargs
124
- XAirRemote.__init__(self, *args, **kwargs)
125
- self.kind = kind
126
- self.mainst = adapter.MainStereo.make(self)
127
- self.mainmono = adapter.MainMono.make(self)
128
- self.matrix = tuple(
129
- adapter.Matrix.make(self, i) for i in range(kind.num_matrix)
130
- )
131
- self.strip = tuple(Strip.make(self, i) for i in range(kind.num_strip))
132
- self.bus = tuple(adapter.Bus.make(self, i) for i in range(kind.num_bus))
133
- self.dca = tuple(DCA(self, i) for i in range(kind.num_dca))
134
- self.fx = tuple(FX(self, i) for i in range(kind.num_fx))
135
- self.fxreturn = tuple(adapter.FxRtn.make(self, i) for i in range(kind.num_fx))
136
- self.auxin = tuple(adapter.AuxRtn.make(self, i) for i in range(kind.num_auxrtn))
137
- self.config = Config.make(self)
138
- self.headamp = tuple(adapter.HeadAmp(self, i) for i in range(kind.num_headamp))
139
-
140
- def init_xair(self, *args, **kwargs):
141
- defaultkwargs = {
142
- 'ip': None,
143
- 'port': 10024,
144
- 'delay': 0.02,
145
- 'connect_timeout': 2,
146
- }
147
- kwargs = defaultkwargs | kwargs
148
- XAirRemote.__init__(self, *args, **kwargs)
149
- self.kind = kind
150
- self.lr = LR.make(self)
151
- self.strip = tuple(Strip.make(self, i) for i in range(kind.num_strip))
152
- self.bus = tuple(Bus.make(self, i) for i in range(kind.num_bus))
153
- self.dca = tuple(DCA(self, i) for i in range(kind.num_dca))
154
- self.fx = tuple(FX(self, i) for i in range(kind.num_fx))
155
- self.fxsend = tuple(FXSend.make(self, i) for i in range(kind.num_fx))
156
- self.fxreturn = tuple(FxRtn.make(self, i) for i in range(kind.num_fx))
157
- self.auxreturn = AuxRtn.make(self)
158
- self.config = Config.make(self)
159
- self.headamp = tuple(HeadAmp(self, i) for i in range(kind.num_strip))
160
-
161
- if kind.id_ == 'X32':
162
- return type(
163
- f'XAirRemote{kind}',
164
- (XAirRemote,),
165
- {
166
- '__init__': init_x32,
167
- },
168
- )
169
- return type(
170
- f'XAirRemote{kind}',
171
- (XAirRemote,),
172
- {
173
- '__init__': init_xair,
174
- },
175
- )
176
-
177
-
178
- _remotes = {kind.id_: _make_remote(kind) for kind in kinds.all}
179
-
180
-
181
- def request_remote_obj(kind_id: str, *args, **kwargs) -> XAirRemote:
182
- """
183
- Interface entry point. Wraps factory expression and handles errors
184
-
185
- Returns a reference to an XAirRemote class of a kind
186
- """
187
-
188
- XAIRREMOTE_cls = None
189
- try:
190
- XAIRREMOTE_cls = _remotes[kind_id]
191
- except KeyError as e:
192
- raise XAirRemoteError(f"Unknown mixer kind '{kind_id}'") from e
193
- return XAIRREMOTE_cls(*args, **kwargs)
1
+ import abc
2
+ import logging
3
+ import threading
4
+ import time
5
+ from pathlib import Path
6
+ from typing import Optional, Union
7
+
8
+ try:
9
+ import tomllib
10
+ except ModuleNotFoundError:
11
+ import tomli as tomllib
12
+
13
+ from pythonosc.dispatcher import Dispatcher
14
+ from pythonosc.osc_message_builder import OscMessageBuilder
15
+ from pythonosc.osc_server import BlockingOSCUDPServer
16
+
17
+ from . import adapter, kinds, util
18
+ from .bus import Bus
19
+ from .config import Config
20
+ from .dca import DCA
21
+ from .errors import XAirRemoteConnectionTimeoutError, XAirRemoteError
22
+ from .fx import FX, FXSend
23
+ from .headamp import HeadAmp
24
+ from .kinds import KindMap
25
+ from .lr import LR
26
+ from .rtn import AuxRtn, FxRtn
27
+ from .strip import Strip
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ class OSCClientServer(BlockingOSCUDPServer):
33
+ def __init__(self, address: str, dispatcher: Dispatcher):
34
+ super().__init__(('', 0), dispatcher)
35
+ self.xr_address = address
36
+
37
+ def send_message(self, address: str, vals: Optional[Union[str, list]]):
38
+ builder = OscMessageBuilder(address=address)
39
+ vals = vals if vals is not None else []
40
+ if not isinstance(vals, list):
41
+ vals = [vals]
42
+ for val in vals:
43
+ builder.add_arg(val)
44
+ msg = builder.build()
45
+ self.socket.sendto(msg.dgram, self.xr_address)
46
+
47
+
48
+ class XAirRemote(abc.ABC):
49
+ """Handles the communication with the mixer via the OSC protocol"""
50
+
51
+ _info_response = []
52
+
53
+ def __init__(self, **kwargs):
54
+ dispatcher = Dispatcher()
55
+ dispatcher.set_default_handler(self.msg_handler)
56
+ self.xair_ip = kwargs['ip'] or self._ip_from_toml()
57
+ self.xair_port = kwargs['port']
58
+ self._delay = kwargs['delay']
59
+ self.connect_timeout = kwargs['connect_timeout']
60
+ self.logger = logger.getChild(self.__class__.__name__)
61
+ if not self.xair_ip:
62
+ raise XAirRemoteError('No valid ip detected')
63
+ self.server = OSCClientServer((self.xair_ip, self.xair_port), dispatcher)
64
+
65
+ def __enter__(self):
66
+ self.worker = threading.Thread(target=self.run_server, daemon=True)
67
+ self.worker.start()
68
+ self.validate_connection()
69
+ return self
70
+
71
+ def _ip_from_toml(self) -> str:
72
+ filepath = Path.cwd() / 'config.toml'
73
+ with open(filepath, 'rb') as f:
74
+ conn = tomllib.load(f)
75
+ return conn['connection'].get('ip')
76
+
77
+ @util.timeout
78
+ def validate_connection(self):
79
+ if not self.query('/xinfo'):
80
+ raise XAirRemoteConnectionTimeoutError(self.xair_ip, self.xair_port)
81
+ self.logger.info(
82
+ f'Successfully connected to {self.info_response[2]} at {self.info_response[0]}.'
83
+ )
84
+
85
+ @property
86
+ def info_response(self):
87
+ return self._info_response
88
+
89
+ def run_server(self):
90
+ self.server.serve_forever()
91
+
92
+ def msg_handler(self, addr, *data):
93
+ self.logger.debug(f"received: {addr} {data if data else ''}")
94
+ self._info_response = data[:]
95
+
96
+ def send(self, addr: str, param: Optional[str] = None):
97
+ self.logger.debug(f"sending: {addr} {param if param is not None else ''}")
98
+ self.server.send_message(addr, param)
99
+
100
+ def query(self, address):
101
+ self.send(address)
102
+ time.sleep(self._delay)
103
+ return self.info_response
104
+
105
+ def __exit__(self, exc_type, exc_value, exc_tr):
106
+ self.server.shutdown()
107
+
108
+
109
+ def _make_remote(kind: KindMap) -> XAirRemote:
110
+ """
111
+ Creates a new XAIR remote class.
112
+
113
+ The returned class will subclass XAirRemote.
114
+ """
115
+
116
+ def init_x32(self, *args, **kwargs):
117
+ defaultkwargs = {
118
+ 'ip': None,
119
+ 'port': 10023,
120
+ 'delay': 0.02,
121
+ 'connect_timeout': 2,
122
+ }
123
+ kwargs = defaultkwargs | kwargs
124
+ XAirRemote.__init__(self, *args, **kwargs)
125
+ self.kind = kind
126
+ self.mainst = adapter.MainStereo.make(self)
127
+ self.mainmono = adapter.MainMono.make(self)
128
+ self.matrix = tuple(
129
+ adapter.Matrix.make(self, i) for i in range(kind.num_matrix)
130
+ )
131
+ self.strip = tuple(Strip.make(self, i) for i in range(kind.num_strip))
132
+ self.bus = tuple(adapter.Bus.make(self, i) for i in range(kind.num_bus))
133
+ self.dca = tuple(DCA(self, i) for i in range(kind.num_dca))
134
+ self.fx = tuple(FX(self, i) for i in range(kind.num_fx))
135
+ self.fxreturn = tuple(adapter.FxRtn.make(self, i) for i in range(kind.num_fx))
136
+ self.auxin = tuple(adapter.AuxRtn.make(self, i) for i in range(kind.num_auxrtn))
137
+ self.config = Config.make(self)
138
+ self.headamp = tuple(adapter.HeadAmp(self, i) for i in range(kind.num_headamp))
139
+
140
+ def init_xair(self, *args, **kwargs):
141
+ defaultkwargs = {
142
+ 'ip': None,
143
+ 'port': 10024,
144
+ 'delay': 0.02,
145
+ 'connect_timeout': 2,
146
+ }
147
+ kwargs = defaultkwargs | kwargs
148
+ XAirRemote.__init__(self, *args, **kwargs)
149
+ self.kind = kind
150
+ self.lr = LR.make(self)
151
+ self.strip = tuple(Strip.make(self, i) for i in range(kind.num_strip))
152
+ self.bus = tuple(Bus.make(self, i) for i in range(kind.num_bus))
153
+ self.dca = tuple(DCA(self, i) for i in range(kind.num_dca))
154
+ self.fx = tuple(FX(self, i) for i in range(kind.num_fx))
155
+ self.fxsend = tuple(FXSend.make(self, i) for i in range(kind.num_fx))
156
+ self.fxreturn = tuple(FxRtn.make(self, i) for i in range(kind.num_fx))
157
+ self.auxreturn = AuxRtn.make(self)
158
+ self.config = Config.make(self)
159
+ self.headamp = tuple(HeadAmp(self, i) for i in range(kind.num_strip))
160
+
161
+ if kind.id_ == 'X32':
162
+ return type(
163
+ f'XAirRemote{kind}',
164
+ (XAirRemote,),
165
+ {
166
+ '__init__': init_x32,
167
+ },
168
+ )
169
+ return type(
170
+ f'XAirRemote{kind}',
171
+ (XAirRemote,),
172
+ {
173
+ '__init__': init_xair,
174
+ },
175
+ )
176
+
177
+
178
+ _remotes = {kind.id_: _make_remote(kind) for kind in kinds.all}
179
+
180
+
181
+ def request_remote_obj(kind_id: str, *args, **kwargs) -> XAirRemote:
182
+ """
183
+ Interface entry point. Wraps factory expression and handles errors
184
+
185
+ Returns a reference to an XAirRemote class of a kind
186
+ """
187
+
188
+ XAIRREMOTE_cls = None
189
+ try:
190
+ XAIRREMOTE_cls = _remotes[kind_id]
191
+ except KeyError as e:
192
+ raise XAirRemoteError(f"Unknown mixer kind '{kind_id}'") from e
193
+ return XAIRREMOTE_cls(*args, **kwargs)
@@ -1,23 +1,26 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: xair-api
3
- Version: 2.4.1
3
+ Version: 2.4.2
4
4
  Summary: Remote control Behringer X-Air | Midas MR mixers through OSC
5
5
  License: MIT
6
+ License-File: LICENSE
6
7
  Author: Onyx and Iris
7
8
  Author-email: code@onyxandiris.online
8
- Requires-Python: <4.0,>=3.10
9
+ Requires-Python: >=3.10
9
10
  Classifier: License :: OSI Approved :: MIT License
10
11
  Classifier: Programming Language :: Python :: 3
11
12
  Classifier: Programming Language :: Python :: 3.10
12
13
  Classifier: Programming Language :: Python :: 3.11
13
14
  Classifier: Programming Language :: Python :: 3.12
14
15
  Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
15
17
  Requires-Dist: python-osc (>=1.9.3,<2.0.0)
16
18
  Requires-Dist: tomli (>=2.0.1,<3.0) ; python_version < "3.11"
17
19
  Description-Content-Type: text/markdown
18
20
 
19
21
  [![PyPI version](https://badge.fury.io/py/xair-api.svg)](https://badge.fury.io/py/xair-api)
20
22
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/onyx-and-iris/xair-api-python/blob/dev/LICENSE)
23
+ [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
21
24
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
22
25
  ![Tests Status](./tests/xair/MR18.svg?dummy=8484744)
23
26
 
@@ -356,14 +359,14 @@ print(mixer.query('/ch/01/mix/on'))
356
359
 
357
360
  ### `Tests`
358
361
 
359
- Unplug any expensive equipment before running tests.
360
- Save your current settings to a snapshot first.
362
+ Install [poetry](https://python-poetry.org/docs/#installation) and then:
361
363
 
362
- First make sure you installed the [development dependencies](https://github.com/onyx-and-iris/xair-api-python#installation)
363
-
364
- To run all tests:
364
+ ```powershell
365
+ poetry poe test-xair
366
+ poetry poe test-x32
367
+ ```
365
368
 
366
- `pytest -v`.
369
+ Unplug any expensive equipment and save your current settings to a snapshot first.
367
370
 
368
371
  ## License
369
372
 
@@ -0,0 +1,20 @@
1
+ xair_api/__init__.py,sha256=YM1f4GULAc-zea8hoUNRkLf8EVxEik_HY6F836-WxgM,70
2
+ xair_api/adapter.py,sha256=2OHM0ZzTYJTYjr0C4k5PNo24kkMy_w_zee_xLU7R0J8,916
3
+ xair_api/bus.py,sha256=4yjuk6ozwYqZRiuH8TS-TiV0-DwRiH7kQQXrjKZ7_Q0,1705
4
+ xair_api/config.py,sha256=fkVuOAVO69E1mtKnhKoiDaokEyWTAXk6qroOQ9yLWaA,5646
5
+ xair_api/dca.py,sha256=53CdLoYkJPlPQdIPzdJyN_MmFjNBSnjgRgMQCZcKcNs,1380
6
+ xair_api/errors.py,sha256=ljh0S9TiZFONQYXva_gMr3oxSKdlwIKV2NvU8nHQ79U,397
7
+ xair_api/fx.py,sha256=XbYud6WIYwDFq53lN2-Xfw0z7aY_z3PmGfqnAL4diPc,1737
8
+ xair_api/headamp.py,sha256=VJtkviBBIEg9gZWAFd3IkNwgqpz8jbS1UcUxMc06v24,1126
9
+ xair_api/kinds.py,sha256=w2NRvXySdPbdrMnVCW4lVluwvUibnNRcHOOKbP9bT0M,1094
10
+ xair_api/lr.py,sha256=nzcyKUKgBNGxs4XSoqAxlfNIY00mWdGBEfZEths5s8E,1721
11
+ xair_api/meta.py,sha256=rORjsY0GcZKqzr33kwhf6e5UM9_a1dS45J4T0sZLGX8,1489
12
+ xair_api/rtn.py,sha256=DIL6u0oYC5upVc13xdyqyN1Dn2bIRagg7D6DrnAJcPw,3065
13
+ xair_api/shared.py,sha256=LHJQeElMFfdHJLHZ6GVnFVCRuK69MRZpGtTKiPJN8eo,18544
14
+ xair_api/strip.py,sha256=O52_trXhZ6iOX3sRklkej-_AL-gAyYze08WL7ob3g20,2009
15
+ xair_api/util.py,sha256=_HyqmSiJ_kdBgHyBrdZI-3SmcQZMvX1GAUGwRavotA8,2169
16
+ xair_api/xair.py,sha256=Es_jg1bgW732S4fMGsMmuLVVNcg0DKFQRHoSQgooYC0,6389
17
+ xair_api-2.4.2.dist-info/METADATA,sha256=OQRmO0TcuuBMqf5e-wlbeV2K83HTDZah529-tkoTUqo,9075
18
+ xair_api-2.4.2.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
19
+ xair_api-2.4.2.dist-info/licenses/LICENSE,sha256=yqfnWf9m9ArjIqh56opp7LBgEjzkLeFK4xLfkPWrnus,1102
20
+ xair_api-2.4.2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.0.1
2
+ Generator: poetry-core 2.3.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,22 +1,22 @@
1
- MIT License
2
-
3
- Copyright (c) 2018 Peter Dikant
4
- Copyright (c) 2022 Onyx and Iris
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in all
14
- copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Peter Dikant
4
+ Copyright (c) 2022 Onyx and Iris
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -1,20 +0,0 @@
1
- xair_api/__init__.py,sha256=O6VVgrgm1hq2iwgl6XNAWu54uxlpr7aB28s_a6fCm10,73
2
- xair_api/adapter.py,sha256=wD2oIFoHG-smgCC9z6fC_Ly0yIwjvZW5HPdjCT9KfLs,963
3
- xair_api/bus.py,sha256=a44uaQ-OVxekKottir86aNzuP1Srw2s97Afshqq5m5o,1771
4
- xair_api/config.py,sha256=vZ7R3eNu-it39icn1AlixAAFlp08ay3PXuNVQ725lzg,5853
5
- xair_api/dca.py,sha256=sn_X9dK4i-DEPr8E8Ot9seYrIiL1bJiKSjiPmZ4FjBo,1443
6
- xair_api/errors.py,sha256=Bm0ezXP8pgeiiz76UbVkaVpvJLw03qq71LOpCclaDEY,411
7
- xair_api/fx.py,sha256=PxAX_XZE67XtnsPyp3xLH79-DeG6dVJZpjECDSB2Ltg,1811
8
- xair_api/headamp.py,sha256=L6N5FrifYChUckuvOfp8fOrwczW9i1V51mXFowKaONk,1175
9
- xair_api/kinds.py,sha256=WS3pZBgpGAG-HPIPkgOxnGqqTnqQAjOEAO6f5SD7FUY,1155
10
- xair_api/lr.py,sha256=xqlsr2D_jvzDWsHDzbOf1EKW699UHd19vGmCFG6UQkk,1788
11
- xair_api/meta.py,sha256=rU61YNScmiPcvlNU7WcAhRP9AQXS0XoOkZ9ntm1iW6k,1564
12
- xair_api/rtn.py,sha256=f35eMrGw4YBfv1JK6vsKbaVXJfACotz8EycMxBiz2y4,3177
13
- xair_api/shared.py,sha256=k1RuE2N_RR9nKQQa6AyeIqtZ4i6IfrKzSl4YM7eAC_4,19171
14
- xair_api/strip.py,sha256=_ge_GfBeYiEBbRzMWBh67kaoZ907iwvnd6Bte_n_x9Y,2082
15
- xair_api/util.py,sha256=OxgWTWRqZLUz4AGTRT-hETjM4EUO4e8tXppRSOFY01M,2263
16
- xair_api/xair.py,sha256=Qhy7Ey6Gk092ADZNfn9sQ2sClRJHBZtehDBUNrUkRXQ,6582
17
- xair_api-2.4.1.dist-info/LICENSE,sha256=m2fbtv9II-iQqimTd4zjgynL5vuEqGXauLSDJZycYIo,1124
18
- xair_api-2.4.1.dist-info/METADATA,sha256=kc-8xB3c0997vgOl2YCEs33-je04tOmksS6uP6Uvx9s,8932
19
- xair_api-2.4.1.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
20
- xair_api-2.4.1.dist-info/RECORD,,