Browse Source

Fix lint issues (incl. some very old one missed because of missing pyi files).

looper
Ben Niemann 3 years ago
parent
commit
789e49f059
  1. 2
      noisicaa/audioproc/engine/spec.pyi
  2. 5
      noisicaa/audioproc/public/CMakeLists.txt
  3. 115
      noisicaa/audioproc/public/musical_time.pyi
  4. 41
      noisicaa/audioproc/public/time_mapper.pyi
  5. 2
      noisicaa/builtin_nodes/beat_track/track_ui.py
  6. 13
      noisicaa/builtin_nodes/midi_looper/node_ui.py
  7. 9
      noisicaa/builtin_nodes/midi_looper/node_ui_test.py
  8. 32
      noisicaa/builtin_nodes/midi_looper/processor_test.py
  9. 1
      noisicaa/music/__init__.py
  10. 3
      noisicaa/music/base_track.py
  11. 2
      noisicaa/music/project_client.py
  12. 6
      noisicaa/ui/pianoroll.py
  13. 13
      noisicaa/ui/pianoroll_test.py
  14. 4
      noisicaa/ui/slots.py
  15. 3
      noisicaa/ui/track_list/measured_track_editor.py
  16. 3
      noisicaa/value_types/midi_event.py

2
noisicaa/audioproc/engine/spec.pyi

@ -32,7 +32,7 @@ opname = ... # type: Dict[int, str]
class PySpec(object):
bpm = ... # type: int
duration = ... # type: audioproc.MusicalTime
duration = ... # type: audioproc.MusicalDuration
def __init__(self) -> None: ...
def dump(self) -> str: ...

5
noisicaa/audioproc/public/CMakeLists.txt

@ -18,7 +18,10 @@
#
# @end:license
add_python_package()
add_python_package(
time_mapper.pyi
musical_time.pyi
)
set(LIB_SRCS
backend_settings.pb.cc

115
noisicaa/audioproc/public/musical_time.pyi

@ -0,0 +1,115 @@
#!/usr/bin/python3
# @begin:license
#
# Copyright (c) 2015-2019, Benjamin Niemann <pink@odahoda.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# @end:license
import fractions
from typing import overload, Any, Union
from google.protobuf import message as protobuf
from noisicaa import value_types
from . import musical_time_pb2
class PyMusicalDuration(value_types.ProtoValue):
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, numerator: int, denominator: int) -> None: ...
@overload
def __init__(self, duration: PyMusicalDuration) -> None: ...
@overload
def __init__(self, duration: fractions.Fraction) -> None: ...
@overload
def __init__(self, duration: int) -> None: ...
def __hash__(self) -> int: ...
def __str__(self) -> str: ...
def __repr__(self) -> str: ...
def __getstate__(self) -> Any: ...
def __setstate__(self, state: Any) -> None: ...
@property
def numerator(self) -> int: ...
@property
def denominator(self) -> int: ...
@property
def fraction(self) -> fractions.Fraction: ...
def to_float(self) -> float: ...
def __bool__(self) -> bool: ...
def __eq__(self, other: Any) -> bool: ...
def __ne__(self, other: Any) -> bool: ...
def __gt__(self, other: PyMusicalDuration) -> bool: ...
def __ge__(self, other: PyMusicalDuration) -> bool: ...
def __le__(self, other: PyMusicalDuration) -> bool: ...
def __lt__(self, other: PyMusicalDuration) -> bool: ...
def __add__(self, other: PyMusicalDuration) -> PyMusicalDuration: ...
def __sub__(self, other: PyMusicalDuration) -> PyMusicalDuration: ...
def __mul__(self, other: Union[PyMusicalDuration, PyMusicalTime, fractions.Fraction, int]) -> PyMusicalDuration: ...
def __truediv__(self, other: Union[PyMusicalDuration, PyMusicalTime, fractions.Fraction, int]) -> PyMusicalDuration: ...
def __int__(self) -> int: ...
def __float__(self) -> float: ...
@classmethod
def from_proto(cls, pb: protobuf.Message) -> PyMusicalDuration: ...
def to_proto(self) -> musical_time_pb2.MusicalDuration: ...
class PyMusicalTime(value_types.ProtoValue):
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, numerator: int, denominator: int) -> None: ...
@overload
def __init__(self, duration: PyMusicalTime) -> None: ...
@overload
def __init__(self, duration: fractions.Fraction) -> None: ...
@overload
def __init__(self, duration: int) -> None: ...
def __hash__(self) -> int: ...
def __str__(self) -> str: ...
def __repr__(self) -> str: ...
def __getstate__(self) -> Any: ...
def __setstate__(self, state: Any) -> None: ...
@property
def numerator(self) -> int: ...
@property
def denominator(self) -> int: ...
@property
def fraction(self) -> fractions.Fraction: ...
def to_float(self) -> float: ...
def __bool__(self) -> bool: ...
def __eq__(self, other: Any) -> bool: ...
def __ne__(self, other: Any) -> bool: ...
def __gt__(self, other: PyMusicalTime) -> bool: ...
def __ge__(self, other: PyMusicalTime) -> bool: ...
def __lt__(self, other: PyMusicalTime) -> bool: ...
def __le__(self, other: PyMusicalTime) -> bool: ...
def __add__(self, other: PyMusicalDuration) -> PyMusicalTime: ...
@overload
def __sub__(self, other: PyMusicalDuration) -> PyMusicalTime: ...
@overload
def __sub__(self, other: PyMusicalTime) -> PyMusicalDuration: ...
def __mul__(self, other: Union[PyMusicalDuration, PyMusicalTime, fractions.Fraction, int]) -> PyMusicalTime: ...
def __truediv__(self, other: Union[PyMusicalDuration, PyMusicalTime, fractions.Fraction, int]) -> PyMusicalTime: ...
def __mod__(self, other: Union[PyMusicalDuration, PyMusicalTime, fractions.Fraction, int]) -> PyMusicalTime: ...
def __int__(self) -> int: ...
def __float__(self) -> float: ...
@classmethod
def from_proto(cls, pb: protobuf.Message) -> PyMusicalTime: ...
def to_proto(self) -> musical_time_pb2.MusicalTime: ...

41
noisicaa/audioproc/public/time_mapper.pyi

@ -0,0 +1,41 @@
# @begin:license
#
# Copyright (c) 2015-2019, Benjamin Niemann <pink@odahoda.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# @end:license
from typing import Iterator
from .musical_time import PyMusicalTime, PyMusicalDuration
from noisicaa import music
class PyTimeMapper(object):
bpm = ... # type: int
duration = ... # type: PyMusicalDuration
def __init__(self, sample_rate: int) -> None: ...
def setup(self, project: music.BaseProject = None) -> None: ...
def cleanup(self) -> None: ...
@property
def end_time(self) -> PyMusicalTime: ...
@property
def num_samples(self) -> int: ...
def sample_to_musical_time(self, sample_time: int) -> PyMusicalTime: ...
def musical_to_sample_time(self, musical_time: PyMusicalTime) -> int: ...
def __iter__(self) -> Iterator[PyMusicalTime]: ...
def find(self, t: PyMusicalTime) -> Iterator[PyMusicalTime]: ...

2
noisicaa/builtin_nodes/beat_track/track_ui.py

@ -128,7 +128,7 @@ class BeatMeasureEditor(measured_track_editor.MeasureEditor):
def measure(self) -> model.BeatMeasure:
return down_cast(model.BeatMeasure, super().measure)
def xToTime(self, x: int) -> audioproc.MusicalTime:
def xToTime(self, x: int) -> audioproc.MusicalDuration:
return audioproc.MusicalDuration(
int(8 * self.measure.time_signature.upper * x / self.width()),
8 * self.measure.time_signature.upper)

13
noisicaa/builtin_nodes/midi_looper/node_ui.py

@ -22,7 +22,7 @@
import enum
import logging
from typing import Any, Dict, List, Tuple
from typing import Any, Dict, List
from PyQt5.QtCore import Qt
from PyQt5 import QtCore
@ -173,7 +173,8 @@ class MidiLooperNodeWidget(ui_base.ProjectMixin, core.AutoCleanupMixin, QtWidget
else:
raise TypeError(type(change))
def __durationChanged(self, change: music.PropertyValueChange[audioproc.MusicalDuration]) -> None:
def __durationChanged(
self, change: music.PropertyValueChange[audioproc.MusicalDuration]) -> None:
num_beats = change.new_value / audioproc.MusicalDuration(1, 4)
assert num_beats.denominator == 1
self.__duration.setValue(num_beats.numerator)
@ -194,7 +195,8 @@ class MidiLooperNodeWidget(ui_base.ProjectMixin, core.AutoCleanupMixin, QtWidget
self.call_async(self.project_view.sendNodeMessage(msg))
def __nodeMessage(self, msg: Dict[str, Any]) -> None:
current_position_urid = 'http://noisicaa.odahoda.de/lv2/processor_midi_looper#current_position'
current_position_urid = (
'http://noisicaa.odahoda.de/lv2/processor_midi_looper#current_position')
if current_position_urid in msg:
numerator, denominator = msg[current_position_urid]
current_position = audioproc.MusicalTime(numerator, denominator)
@ -207,7 +209,8 @@ class MidiLooperNodeWidget(ui_base.ProjectMixin, core.AutoCleanupMixin, QtWidget
if record_state == RecordState.RECORDING:
self.__recorded_events.clear()
self.__pianoroll.clearEvents()
self.__pianoroll.setUnfinishedNoteMode(pianoroll.UnfinishedNoteMode.ToPlaybackPosition)
self.__pianoroll.setUnfinishedNoteMode(
pianoroll.UnfinishedNoteMode.ToPlaybackPosition)
else:
if record_state == RecordState.OFF:
del self.__listeners['events']
@ -248,7 +251,7 @@ class MidiLooperNode(base_node.Node):
def __init__(self, *, node: music.BaseNode, **kwargs: Any) -> None:
assert isinstance(node, model.MidiLooper), type(node).__name__
self.__widget = None # type: MidiLooperNodeWidget
self.__widget = None # type: QtWidgets.QWidget
self.__node = node # type: model.MidiLooper
super().__init__(node=node, **kwargs)

9
noisicaa/builtin_nodes/midi_looper/node_ui_test.py

@ -43,15 +43,18 @@ class MidiLooperNodeWidgetTest(uitest.ProjectMixin, uitest.UITestCase):
self.node = self.project.create_node('builtin://midi-looper')
async def test_init(self):
widget = node_ui.MidiLooperNodeWidget(node=self.node, context=self.context)
widget = node_ui.MidiLooperNodeWidget(
node=self.node, session_prefix='test', context=self.context)
widget.cleanup()
async def test_duration(self):
widget = node_ui.MidiLooperNodeWidget(node=self.node, context=self.context)
widget = node_ui.MidiLooperNodeWidget(
node=self.node, session_prefix='test', context=self.context)
try:
duration = widget.findChild(QtWidgets.QSpinBox, 'duration')
assert duration is not None
self.assertEqual(duration.value(), (self.node.duration / audioproc.MusicalDuration(1, 4)).numerator)
self.assertEqual(
duration.value(), (self.node.duration / audioproc.MusicalDuration(1, 4)).numerator)
with self.project.apply_mutations('test'):
self.node.set_duration(audioproc.MusicalDuration(5, 4))

32
noisicaa/builtin_nodes/midi_looper/processor_test.py

@ -24,6 +24,8 @@ from noisidev import unittest_engine_mixins
from noisidev import unittest_engine_utils
from noisicaa import lv2
from noisicaa.audioproc.public import node_parameters_pb2
from noisicaa.audioproc.public import time_mapper
from noisicaa.audioproc.public import musical_time
from noisicaa.audioproc.engine import block_context
from noisicaa.audioproc.engine import buffers
from noisicaa.audioproc.engine import processor
@ -35,6 +37,20 @@ class ProcessorMidiLooperTestMixin(
unittest_mixins.NodeDBMixin,
unittest.TestCase):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.time_mapper = None
def setup_testcase(self):
self.time_mapper = time_mapper.PyTimeMapper(self.host_system.sample_rate)
self.time_mapper.setup()
def cleanup_testcase(self):
if self.time_mapper is not None:
self.time_mapper.cleanup()
self.time_mapper = None
def test_value(self):
plugin_uri = 'builtin://midi-looper'
@ -45,15 +61,23 @@ class ProcessorMidiLooperTestMixin(
params = node_parameters_pb2.NodeParameters()
spec = params.Extensions[processor_pb2.midi_looper_spec]
spec.duration.numerator = 8
spec.duration.denominator = 4
proc.set_parameters(params)
buffer_mgr = unittest_engine_utils.BufferManager(self.host_system)
ev_in = buffer_mgr.allocate('in', buffers.PyAtomDataBuffer())
ev_out = buffer_mgr.allocate('out', buffers.PyAtomDataBuffer())
buffer_mgr.allocate('in', buffers.PyAtomDataBuffer())
buffer_mgr.allocate('out', buffers.PyAtomDataBuffer())
ctxt = block_context.PyBlockContext()
ctxt.sample_pos = 1024
ctxt.sample_pos = 0
ctxt.clear_time_map(self.host_system.block_size)
for s in range(self.host_system.block_size):
ctxt.set_sample_time(
s,
musical_time.PyMusicalTime(s, 44100),
musical_time.PyMusicalTime(s + 1, 44100))
proc.connect_port(ctxt, 0, buffer_mgr.data('in'))
proc.connect_port(ctxt, 1, buffer_mgr.data('out'))
@ -63,4 +87,4 @@ class ProcessorMidiLooperTestMixin(
with forge.sequence():
pass
proc.process_block(ctxt, None) # TODO: pass time_mapper
proc.process_block(ctxt, self.time_mapper)

1
noisicaa/music/__init__.py

@ -57,6 +57,7 @@ from .base_track import (
Measure,
)
from .project import (
BaseProject,
Project,
)
from .render_pb2 import (

3
noisicaa/music/base_track.py

@ -170,8 +170,7 @@ class MeasuredTrackConnector(node_connector.NodeConnector):
self.__add_event(event)
events.append(event)
def _update_measure_range(
self, begin: audioproc.MusicalTime, end: audioproc.MusicalTime) -> None:
def _update_measure_range(self, begin: int, end: int) -> None:
time = audioproc.MusicalTime()
for mref in self._node.measure_list:
if mref.index >= end:

2
noisicaa/music/project_client.py

@ -323,7 +323,7 @@ class ProjectClient(object):
elif value_type == 'musical_time_value':
return audioproc.MusicalTime.from_proto(session_value.musical_time_value)
elif value_type == 'musical_duration_value':
return audioproc.MusicalDuration.from_proto(session_value.musical_time_value)
return audioproc.MusicalDuration.from_proto(session_value.musical_duration_value)
else:
raise ValueError(session_value)

6
noisicaa/ui/pianoroll.py

@ -22,7 +22,7 @@
import enum
import logging
from typing import Any, Dict
from typing import Any, Dict, Set
from PyQt5.QtCore import Qt
from PyQt5 import QtCore
@ -59,7 +59,7 @@ class PianoKeys(slots.SlotContainer, QtWidgets.QWidget):
self.__active_key_edge1_color = QtGui.QColor(200, 200, 255)
self.__active_key_edge2_color = QtGui.QColor(100, 100, 160)
self.__active_keys = set()
self.__active_keys = set() # type: Set[int]
self.yOffsetChanged.connect(lambda _: self.update())
@ -184,7 +184,7 @@ class PianoRollGrid(slots.SlotContainer, QtWidgets.QWidget):
self.__playback_position_color = QtGui.QColor(0, 0, 0)
self.__next_event_id = 0
self.__events = {} # Dict[int, value_types.MidiEvent]
self.__events = {} # type: Dict[int, value_types.MidiEvent]
self.__sorted_events = sortedcontainers.SortedList()
self.setMinimumSize(100, 50)

13
noisicaa/ui/pianoroll_test.py

@ -24,6 +24,7 @@ from PyQt5 import QtGui
from noisidev import uitest
from noisicaa import audioproc
from noisicaa import value_types
from . import pianoroll
@ -41,13 +42,17 @@ class PianoRollTest(uitest.UITestCase):
self.assertTrue(self.roll.close())
def test_addEvent(self):
self.roll.addEvent(audioproc.MusicalTime(1, 8), bytes([0x90, 60, 100]))
self.roll.addEvent(value_types.MidiEvent(
audioproc.MusicalTime(1, 8), bytes([0x90, 60, 100])))
self.render()
self.roll.addEvent(audioproc.MusicalTime(2, 8), bytes([0x80, 60, 0]))
self.roll.addEvent(value_types.MidiEvent(
audioproc.MusicalTime(2, 8), bytes([0x80, 60, 0])))
self.render()
def test_clearEvents(self):
self.roll.addEvent(audioproc.MusicalTime(1, 8), bytes([0x90, 60, 100]))
self.roll.addEvent(audioproc.MusicalTime(2, 8), bytes([0x80, 60, 0]))
self.roll.addEvent(value_types.MidiEvent(
audioproc.MusicalTime(1, 8), bytes([0x90, 60, 100])))
self.roll.addEvent(value_types.MidiEvent(
audioproc.MusicalTime(2, 8), bytes([0x80, 60, 0])))
self.roll.clearEvents()
self.render()

4
noisicaa/ui/slots.py

@ -82,7 +82,7 @@ class SlotConnectionManager(ui_base.ProjectMixin, object):
super().__init__(**kwargs)
self.__session_prefix = session_prefix
self.__connections = {} # type: Dict[str, Tuple[QtCore.pyqtSignal, QtCore.pyqtConnection]]
self.__connections = {} # type: Dict[str, Tuple[QtCore.pyqtBoundSignal, QtCore.pyqtConnection]]
def cleanup(self) -> None:
while self.__connections:
@ -93,7 +93,7 @@ class SlotConnectionManager(ui_base.ProjectMixin, object):
self,
name: str,
setter: Callable[[T], None],
signal: QtCore.pyqtSignal,
signal: QtCore.pyqtBoundSignal,
default: T = None,
) -> None:
value = self.get_session_value(self.__session_prefix + ':' + name, default)

3
noisicaa/ui/track_list/measured_track_editor.py

@ -649,7 +649,8 @@ class MeasuredTrackEditor(base_track_editor.BaseTrackEditor):
measure_time = audioproc.MusicalTime()
for measure_editor in self.measure_editors():
if measure_time <= time < measure_time + measure_editor.duration:
measure_editor.setPlaybackPos(time - measure_time)
measure_editor.setPlaybackPos(
audioproc.MusicalTime() + (time - measure_time))
self.__measure_editor_at_playback_pos = measure_editor
break
measure_time += measure_editor.duration

3
noisicaa/value_types/midi_event.py

@ -34,7 +34,8 @@ class MidiEvent(proto_value.ProtoValue):
self.__sortkey = (self.__time, self.__midi[0] & 0xf0, self.__midi)
def __str__(self) -> str:
return '<MidiEvent %.3f [%s]>' % (self.__time.to_float(), ' '.join('%02x' % m for m in self.__midi))
return '<MidiEvent %.3f [%s]>' % (
self.__time.to_float(), ' '.join('%02x' % m for m in self.__midi))
__repr__ = __str__
def to_proto(self) -> 'audioproc.MidiEvent':

Loading…
Cancel
Save