]> git.parisson.com Git - timeside.git/commitdiff
- move generic component/interface architecture from core to component.py
authorOlivier Guilyardi <olivier@samalyse.com>
Fri, 27 Nov 2009 16:26:11 +0000 (16:26 +0000)
committerOlivier Guilyardi <olivier@samalyse.com>
Fri, 27 Nov 2009 16:26:11 +0000 (16:26 +0000)
- add Processor, MetaProcessor and processors() to core
- add IProcessor base interface for all processor interfaces
- let IAnalyzer, IGrapher, IEncoder and IDecoder subclass IProcessor
- let all actual processor classes descend from Processor
- use processors() instead of implementations() in test.py
- add listprocessors.py test script

13 files changed:
__init__.py
analyze/api.py
analyze/core.py
api.py [new file with mode: 0644]
core.py
decode/api.py
encode/api.py
encode/core.py
graph/api.py
graph/spectrogram_audiolab.py
graph/waveform_audiolab.py
tests/listprocessors.py [new file with mode: 0644]
tests/test.py

index 5a4f3457080bb60e284f65cd4a8711a03708e132..67efe02ac4e08b49f2682adf8fbeee1e5086eea8 100644 (file)
@@ -1,5 +1,5 @@
 
-import core
+from core import *
 import decode
 import encode
 import analyze
index 8091c613c6e2552abddbb44839894b6d4635987b..46d4ab9353f12383ba66e775709f5c252fcd885e 100644 (file)
@@ -19,9 +19,9 @@
 
 # Author: Guillaume Pellerin <yomguy@parisson.com>
 
-from timeside.core import *
+from timeside.api import IProcessor
 
-class IAnalyzer(Interface):
+class IAnalyzer(IProcessor):
     """Media item analyzer driver interface"""
 
     @staticmethod
index fdbcb416372176da662be6565847329469ca6d2f..c2371d2fb1a60c4ab2f04fafa32b1c26fc3660ff 100644 (file)
@@ -26,7 +26,8 @@ import optparse, math, sys
 import numpy
 import scikits.audiolab as audiolab
 
-class AudioProcessor(Component):
+# FIXME: AudioProcessor: wrong name, should be Analyzer or AnalyzerCore
+class AudioProcessor(Processor):
 
     def __init__(self):
         self.fft_size = 2048
diff --git a/api.py b/api.py
new file mode 100644 (file)
index 0000000..e2f62b9
--- /dev/null
+++ b/api.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2009 Olivier Guilyardi <olivier@samalyse.com>
+#
+# This file is part of TimeSide.
+
+# TimeSide 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.
+
+# TimeSide 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 TimeSide.  If not, see <http://www.gnu.org/licenses/>.
+
+from timeside.component import Interface
+
+class IProcessor(Interface):
+    pass
+
diff --git a/core.py b/core.py
index 817a9311aee91d2730f3ada2147b4d062292f113..94e636c6ac7011a4526592b5035f506a09327943 100644 (file)
--- a/core.py
+++ b/core.py
 # You should have received a copy of the GNU General Public License
 # along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
 
+from timeside.component import *
+from timeside.api import IProcessor
 
-
-# This file defines an object interface mechanism and a way to determine
-# which components implements a given interface
-#
-# For example, the following defines the Music class as implementing the
-# listenable interface.
-#
-# class Listenable(Interface):
-#     pass
-#
-# class Music(Component):
-#    implements(Listenable)
-#
-# Several class can implements a such interface, and it is possible to 
-# discover which class implements it with implementations():
-#
-# list_of_classes = implementations(Listenable)
-#
-# This mechanism support inheritance of interfaces: a class implementing a given 
-# interface is also considered to implement all the ascendants of this interface.
-#
-# However, inheritance is not supported for components. The descendants of a class 
-# implementing a given interface are not automatically considered to implement this 
-# interface too. 
-
-__all__ = ['Component', 'implements', 'Interface', 'implementations', 'TimeSideError']
+__all__ = ['Processor', 'Component', 'implements', 'processors', 'TimeSideError']
 
 class TimeSideError(Exception):
     """Exception base class for errors in TimeSide."""
     # FIXME: is this redundant with Django's error handling ?
-    # FIXME: this class doesn't belong to the core
-
-class Interface(object):
-    """Marker base class for interfaces."""
-
-def implements(*interfaces):
-    _implements.extend(interfaces)
-
-def implementations(interface):
-    result = []
-    find_implementations(interface, result)
-    return result
 
-_implementations = []
-_implements = []
-
-class ComponentMeta(type):
+_processors = []
 
+class MetaProcessor(MetaComponent):
+    """Metaclass of the Processor class, used mainly for ensuring uniqueness of 
+    processor id's"""
     def __new__(cls, name, bases, d):
-        new_class = type.__new__(cls, name, bases, d)
-        if _implements:
-            for i in _implements:
-                _implementations.append((i, new_class))
-        del _implements[:]
+        new_class = MetaComponent.__new__(cls, name, bases, d)
+        id = "fixme"
+        _processors.append((id, new_class))
         return new_class
 
-class Component(object):
-    __metaclass__ = ComponentMeta 
-
-def extend_unique(list1, list2):
-    for item in list2:
-        if item not in list1:
-            list1.append(item)
-
-def find_implementations(interface, result):
-    for i, cls in _implementations:
-        if (i == interface):
-            extend_unique(result, [cls])
-
-    subinterfaces = interface.__subclasses__()
-    if subinterfaces:
-        for i in subinterfaces:
-            find_implementations(i, result)
+class Processor(Component):
+    """Base component class of all processors"""
+    __metaclass__ = MetaProcessor
 
+def processors(interface=IProcessor, recurse=True):
+    """Returns the processors implementing a given interface and, if recurse,
+    any of the descendants of this interface."""
+    return implementations(interface, recurse)
+    
index c25d15fdaf3a5e87cab3f97d2d10e9b166a3814b..e3e6744656aa62898d864d847e45f594297d52a8 100644 (file)
 # You should have received a copy of the GNU General Public License
 # along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
 
-from timeside.core import Interface, TimeSideError
+from timeside.api import IProcessor
+from timeside.core import TimeSideError
 
-class IDecoder(Interface):
+class IDecoder(IProcessor):
     """Decoder driver interface"""
 
     @staticmethod
index ee9134efe944b68873d03679a4a2a719ce18e979..9314c82e35e45c991b60a3aad570a8efd9e683ab 100644 (file)
 # You should have received a copy of the GNU General Public License
 # along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
 
-from timeside.core import Interface, TimeSideError
+from timeside.core import TimeSideError
+from timeside.api import IProcessor
 
-class IEncoder(Interface):
+class IEncoder(IProcessor):
     """Encoder driver interface"""
 
     def __init__(self, output, nchannels, samplerate):
index 8ba366fdbf23dab553f6b8d88787bef41d32436e..73b88183bdbc07101e9dcbd5c1f0897e239b6c84 100644 (file)
@@ -52,8 +52,7 @@ class SubProcessPipe:
         self.input = self.proc.stdin
         self.output = self.proc.stdout
 
-
-class EncoderCore(Component):
+class EncoderCore(Processor):
     """Defines the main parts of the encoding tools :
     paths, metadata parsing, data streaming thru system command"""
 
index 1f9667a12d65ebc762de7803db511ce72956b50b..af1ed7a1c408cf858e491d8595c70e679b361f5f 100644 (file)
@@ -20,9 +20,9 @@
 # Author: Guillaume Pellerin <yomguy@parisson.com>
 # Author: Olivier Guilyardi <olivier@samalyse.com>
 
-from timeside.core import *
+from timeside.api import IProcessor
 
-class IGrapher(Interface):
+class IGrapher(IProcessor):
     """Media item visualizer driver interface"""
 
     @staticmethod
index 9687a25d06f1e48f225b7a1b8ce166bc4693d8fb..dc14fe1f23a1325700a7e9d0889ae9973b676686 100644 (file)
@@ -24,7 +24,7 @@ from timeside.graph.api import IGrapher
 from tempfile import NamedTemporaryFile
 from timeside.graph.wav2png import *
 
-class SpectrogramGrapherAudiolab(Component):
+class SpectrogramGrapherAudiolab(Processor):
     """Spectrogram graph driver (python style thanks to wav2png.py and scikits.audiolab)"""
 
     implements(IGrapher)
index 8a7dd0ebc413ea857a1765c6104e4e8c57f6c24b..4aeefc39934731a0dc95c60517b28e042fb1b1c5 100644 (file)
@@ -24,7 +24,7 @@ from timeside.graph.api import IGrapher
 from tempfile import NamedTemporaryFile
 from timeside.graph.wav2png import *
 
-class WaveFormGrapherAudiolab(Component):
+class WaveFormGrapherAudiolab(Processor):
     """WaveForm graph driver (python style thanks to wav2png.py and scikits.audiolab)"""
 
     implements(IGrapher)
diff --git a/tests/listprocessors.py b/tests/listprocessors.py
new file mode 100644 (file)
index 0000000..bf12c42
--- /dev/null
@@ -0,0 +1,12 @@
+import timeside
+
+def list_processors(interface, prefix=""):
+    print prefix + interface.__name__
+    subinterfaces = interface.__subclasses__()
+    for i in subinterfaces:
+        list_processors(i, prefix + "  ")
+    processors = timeside.processors(interface, False)
+    for p in processors:
+        print prefix + "  " + p.__name__
+
+list_processors(timeside.api.IProcessor)        
index c282f944f30198ad24bbf7305b4421f709617eff..38cd4c92e2f68b6e6e4a732c7a0b3d3cf7cfdaf4 100755 (executable)
@@ -8,7 +8,7 @@ from timeside.core import *
 
 
 class TestAnalyzers(Component):
-    analyzers = implementations(timeside.analyze.IAnalyzer)
+    analyzers = processors(timeside.analyze.IAnalyzer)
 
     def list(self):
         analyzers = []
@@ -35,7 +35,7 @@ class TestAnalyzers(Component):
 
 
 class TestDecoders(Component):
-    decoders = implementations(timeside.decode.IDecoder)
+    decoders = processors(timeside.decode.IDecoder)
 
     def list(self):
         decoders_list = []
@@ -72,7 +72,7 @@ class TestDecoders(Component):
                 f.close()
 
 class TestEncoders(Component):
-    encoders = implementations(timeside.encode.IEncoder)
+    encoders = processors(timeside.encode.IEncoder)
 
     def list(self):
         encoders = []
@@ -109,7 +109,7 @@ class TestEncoders(Component):
 
 
 class TestGraphers(Component):
-    graphers = implementations(timeside.graph.IGrapher)
+    graphers = processors(timeside.graph.IGrapher)
 
     def list(self):
         graphers = []