From 6b62e037f2f828ec6bf9c7e0066db32cfb54abef Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 21 Dec 2012 18:48:12 +0000 Subject: Improved error handling in Python by loading error descriptions from data. Fix connecting and disconnecting with ingenish. Fix path problems. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4875 a436a847-0d15-0410-975c-d299462d15a1 --- ingen/Node.hpp | 2 +- scripts/ingen.py | 73 ++++++++++++++++++++++++++++++++++++++++++++---------- scripts/ingenish | 15 ++++++----- src/AtomReader.cpp | 3 ++- 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/ingen/Node.hpp b/ingen/Node.hpp index 9ec6abd1..275c82cc 100644 --- a/ingen/Node.hpp +++ b/ingen/Node.hpp @@ -75,7 +75,7 @@ public: static Raul::URI root_uri() { return Raul::URI("ingen:root"); } static bool uri_is_path(const Raul::URI& uri) { - return uri.substr(0, root_uri().length()) == root_uri(); + return uri.substr(0, root_uri().length() + 1) == root_uri() + "/"; } static Raul::Path uri_to_path(const Raul::URI& uri) { diff --git a/scripts/ingen.py b/scripts/ingen.py index 594e369d..dcfe7206 100644 --- a/scripts/ingen.py +++ b/scripts/ingen.py @@ -21,11 +21,12 @@ import socket import sys class NS: - ingen = rdflib.Namespace('http://drobilla.net/ns/ingen#') - lv2 = rdflib.Namespace('http://lv2plug.in/ns/lv2core#') - patch = rdflib.Namespace('http://lv2plug.in/ns/ext/patch#') - rdf = rdflib.Namespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#') - xsd = rdflib.Namespace('http://www.w3.org/2001/XMLSchema#') + ingen = rdflib.Namespace('http://drobilla.net/ns/ingen#') + ingerr = rdflib.Namespace('http://drobilla.net/ns/ingen/errors#') + lv2 = rdflib.Namespace('http://lv2plug.in/ns/lv2core#') + patch = rdflib.Namespace('http://lv2plug.in/ns/ext/patch#') + rdf = rdflib.Namespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#') + xsd = rdflib.Namespace('http://www.w3.org/2001/XMLSchema#') class Interface: 'The core Ingen interface' @@ -45,8 +46,37 @@ class Interface: pass class Error(Exception): - def __init__(self, code, cause): - Exception.__init__(self, 'error %d, cause: %s' % (code, cause)) + def __init__(self, msg, cause): + Exception.__init__(self, '%s; cause: %s' % (msg, cause)) + +def lv2_path(): + path = os.getenv('LV2_PATH') + if path: + return path + elif sys.platform == 'darwin': + return os.pathsep.join(['~/Library/Audio/Plug-Ins/LV2', + '~/.lv2', + '/usr/local/lib/lv2', + '/usr/lib/lv2', + '/Library/Audio/Plug-Ins/LV2']) + elif sys.platform == 'haiku': + return os.pathsep.join(['~/.lv2', + '/boot/common/add-ons/lv2']) + elif sys.platform == 'win32': + return os.pathsep.join([ + os.path.join(os.getenv('APPDATA'), 'LV2'), + os.path.join(os.getenv('COMMONPROGRAMFILES'), 'LV2')]) + else: + return os.pathsep.join(['~/.lv2', + '/usr/lib/lv2', + '/usr/local/lib/lv2']) + +def ingen_bundle_path(): + for d in lv2_path().split(os.pathsep): + bundle = os.path.abspath(os.path.join(d, 'ingen.lv2')) + if os.path.exists(bundle): + return bundle + return None class Remote(Interface): def __init__(self, uri='unix:///tmp/ingen.sock'): @@ -68,6 +98,11 @@ class Remote(Interface): else: raise Exception('Unsupported server URI `%s' % uri) + # Parse error description from Ingen bundle for pretty printing + bundle = ingen_bundle_path() + if bundle: + self.model.parse(os.path.join(bundle, 'errors.ttl'), format='n3') + def __del__(self): self.sock.close() @@ -88,8 +123,9 @@ class Remote(Interface): return update def uri_to_path(self, uri): + path = uri if uri.startswith(self.server_base): - return uri[len(self.server_base):] + return uri[len(self.server_base)-1:] return uri def recv(self): @@ -115,6 +151,17 @@ class Remote(Interface): closure += [b] return closure + + def raise_error(self, code, cause): + klass = self.model.value(None, NS.ingerr.errorCode, rdflib.Literal(code)) + if not klass: + raise Error('error %d' % code, cause) + + fmt = self.model.value(klass, NS.ingerr.formatString, None) + if not fmt: + raise Error('%s' % klass, cause) + + raise Error(fmt, cause) def send(self, msg): # Send message to server @@ -140,7 +187,7 @@ class Remote(Interface): response_desc += [i] blanks += [response] if body != 0: - raise Error(int(body), msg) # Raise exception on server error + self.raise_error(int(body), msg) # Raise exception on server error # Find the blank node closure of all responses blank_closure = [] @@ -193,8 +240,8 @@ class Remote(Interface): patch:subject ; patch:body [ a ingen:Edge ; - ingen:tail <%s> ; - ingen:head <%s> ; + ingen:tail ; + ingen:head ; ] . ''' % (os.path.commonprefix([tail, head]), tail, head)) @@ -204,8 +251,8 @@ class Remote(Interface): a patch:Delete ; patch:body [ a ingen:Edge ; - ingen:tail <%s> ; - ingen:head <%s> ; + ingen:tail ; + ingen:head ; ] . ''' % (tail, head)) diff --git a/scripts/ingenish b/scripts/ingenish index 3e572dbf..9e4b86ae 100755 --- a/scripts/ingenish +++ b/scripts/ingenish @@ -97,14 +97,13 @@ if len(sys.argv) - a == 0: try: run(shlex.split(raw_input('> '))) except (EOFError, KeyboardInterrupt, SystemExit): - print('error') break except: - print('error: %s' % sys.exc_info()[0]) + print('error: %s' % sys.exc_info()[1]) else: - update = run(sys.argv[1:]) - if update: - print update.serialize(format='n3') - else: - print_usage() - sys.exit(1) + try: + update = run(sys.argv[1:]) + if update: + print update.serialize(format='n3') + except: + print('error: %s' % sys.exc_info()[1]) diff --git a/src/AtomReader.cpp b/src/AtomReader.cpp index 8e0d296d..f7b95177 100644 --- a/src/AtomReader.cpp +++ b/src/AtomReader.cpp @@ -188,7 +188,8 @@ AtomReader::write(const LV2_Atom* msg) if (tail_path && head_path) { _iface.connect(*tail_path, *head_path); } else { - _log.warn("Edge has non-path tail or head\n"); + _log.warn(Raul::fmt("Edge %1% => %2% has non-path tail or head\n") + % atom_to_uri(tail) % atom_to_uri(head)); } } else { Ingen::Resource::Properties props; -- cgit v1.2.1