From 4755ddff4c490c22ada880a26225e8bd72805ffb Mon Sep 17 00:00:00 2001 From: Vincent Vinet Date: Mon, 26 Oct 2009 20:24:02 +0000 Subject: new UAM, archive it and forget it --- (limited to 'tutorius/uam') diff --git a/tutorius/uam/__init__.py b/tutorius/uam/__init__.py index bcd67e1..babb1d8 100644 --- a/tutorius/uam/__init__.py +++ b/tutorius/uam/__init__.py @@ -18,22 +18,52 @@ Universal Addressing Mechanism module Allows addressing Events, signals, widgets, etc for supported platforms + +Different subschemes must implement a parser in the form + + from . import UAMParser + + class MyParser(UAMParser): + @classmethod + def getAddon(self, uri): + ... + + where getAddon accepts a single parameter which is a URI as defined here + +A base parser, UAMParser, should be sufficient for most uses +The base parser will attempt to create any addon according to this uri format: + +:///?# + +where: + + is the base scheme + + is the activity's dns identifier, such as battleship.tutorius.org + + is a list of key=value attributes to pass to the constructor. If + multiple values are passed for the same key, the last one will prevail + + is the addon to use, and passed directly to addon.create() """ from urllib2 import urlparse +from .. import addon -import gtkparser -import gobjectparser +SCHEME="tap" #Tutorius Adressing Protocol +_parsers = {} -SCHEME="tap" #Tutorius Adressing Protocol +def addParser(name, cls): + """ Reconfigure urlparse to accept an additional scheme + @param name schema to add + """ + #Check if abstract. If so, ignore + if getattr(cls, "__abstract__", False): + return -__parsers = { - gtkparser.SCHEME:gtkparser.parse_gtk, - gobjectparser.SCHEME:gobjectparser.parse_gobject, -} + _parsers[name] = cls -def __add_to_urlparse(name): #Add to uses_netloc if not name in urlparse.uses_netloc: urlparse.uses_netloc.append(name) @@ -42,9 +72,9 @@ def __add_to_urlparse(name): if not name in urlparse.uses_relative: urlparse.uses_relative.append(name) -# #Add to uses_params -# if not name in urlparse.uses_params: -# urlparse.uses_params.append(name) + ##Add to uses_params + #if not name in urlparse.uses_params: + # urlparse.uses_params.append(name) #Add to uses_query if not name in urlparse.uses_query: @@ -53,14 +83,59 @@ def __add_to_urlparse(name): #Add to uses_frament if not name in urlparse.uses_fragment: urlparse.uses_fragment.append(name) - - -#Add schemes to urlparse -__add_to_urlparse(SCHEME) - -for subscheme in [".".join([SCHEME,s]) for s in __parsers]: - __add_to_urlparse(subscheme) +class UAMParserMeta(type): + """ + UAM Parsers should have this as a Metaclass in order to + automatically register with urlparse. + """ + def __new__(cls, name, bases, attrs): + """ Type pre-constructor + @param cls This metaclass + @param name name of the new class + @param bases list of bases for the new class + @param attrs dictionary of attributes + """ + # Generate the scheme and subscheme if possible + #FIXME Keep the parent scheme if we don't have one? + if "__scheme__" in attrs: + scheme = attrs["__scheme__"] + for base in bases: + if hasattr(base, "__scheme__"): + scheme = getattr(base, "__scheme__") + "." + scheme + attrs["__scheme__"] = scheme + return type.__new__(cls, name, bases, attrs) + + def __init__(cls, name, bases, attrs): + """ Type constructor + @param cls constructed class + @param name name of the new class + @param bases list of bases for the new class + @param attrs dictionary of attributes + """ + if "__scheme__" in attrs: + #Register the parser in the module and urlparse + addParser(attrs["__scheme__"], cls) + +class UAMParser(object): + __metaclass__ = UAMParserMeta + __scheme__ = SCHEME + __abstract__ = False #Only there to show it exists + + @classmethod + def getAddon(cls, uri): + """Parse an uri + @param uri URI object + """ + params = UAMParser.stripQueryLists(uri.query) + return addon.create(uri.addon, **params) + + @staticmethod + def stripQueryLists(querydict): + newdict = {} + for key, value in querydict.items(): + newdict[key] = urlparse.unquote(value[-1]) + return newdict class SchemeError(Exception): def __init__(self, message): @@ -68,22 +143,45 @@ class SchemeError(Exception): ## Commenting this line as it is causing an error in the tests ##self.message = message - -def parse_uri(uri): - res = urlparse.urlparse(uri) - - scheme = res.scheme.split(".")[0] - subscheme = ".".join(res.scheme.split(".")[1:]) - if not scheme == SCHEME: - raise SchemeError("Scheme %s not supported" % scheme) - - if subscheme != "" and not subscheme in __parsers: - raise SchemeError("SubScheme %s not supported" % subscheme) - - if subscheme: - return __parsers[subscheme](res) - - return res - - +class ParserError(Exception): + pass + +class URI(object): + def __init__(self, uri): + self._uri = None + self._set_uri(uri) + + def _get_uri(self): + return self._uri.geturl() + def _set_uri(self, uri): + if isinstance(uri, urlparse.ParseResult): + self._uri = uri + else: + self._uri = urlparse.urlparse(uri) + #Ensure we only use valid schemes + if self.scheme not in _parsers: + raise SchemeError("Scheme not supported: %s" % self.scheme) + + uri = property(fset=_set_uri, fget=_get_uri) + activity = property(lambda self: self._uri.hostname) + scheme = property(lambda self: self._uri.scheme) + addon = property(lambda self: self._uri.fragment) + path = property(lambda self: self._uri.path) + #params = property(lambda self: urlparse.parse_qs(self._uri.params)) + def _get_querydict(self): + return urlparse.parse_qs(self._uri.query) + query = property(_get_querydict) + + #Serialization functions + def __getstate__(self): + return dict(uri=self.uri) + def __setstate__(self, state): + self.uri = state["uri"] + + def getAddon(self): + return _parsers[self.scheme].getAddon(self) + +#Import the different parsers that we know about +import gtkparser +import gobjectparser diff --git a/tutorius/uam/gobjectparser.py b/tutorius/uam/gobjectparser.py index c1fba3d..767b5ea 100644 --- a/tutorius/uam/gobjectparser.py +++ b/tutorius/uam/gobjectparser.py @@ -19,9 +19,8 @@ UAM Parser for gobject subscheme To be completed """ +from . import UAMParser -SCHEME="gobject" +class GObjectParser(UAMParser): + __scheme__ = "gobject" -def parse_gobject(parsed_uri): - """Do nothing for now""" - return parsed_uri diff --git a/tutorius/uam/gtkparser.py b/tutorius/uam/gtkparser.py index ede2f03..3da852a 100644 --- a/tutorius/uam/gtkparser.py +++ b/tutorius/uam/gtkparser.py @@ -25,8 +25,6 @@ The gtk subscheme for tutorius is where: - is the uam.SCHEME + "." + SCHEME - is the activity's dns identifier, such as battleship.tutorius.org is the Hierarchical path to the widget, where 0 is the activity, such as /0/0/1/0/1/0 @@ -36,9 +34,17 @@ where: must be used with params to specify which action or eventfilter to use, such as "DialogMessage" """ +from . import UAMParser, addon + -SCHEME="gtk" +class GtkParser(UAMParser): + __scheme__ = "gtk" -def parse_gtk(parsed_uri): - """Do nothing for now""" - return parsed_uri + @classmethod + def getAddon(cls, uri): + """Parse an uri + @param uri URI object + """ + params = UAMParser.stripQueryLists(uri.query) + path = uri.path.replace("/",".") + return addon.create(uri.addon, object_id=uri.path, **params) -- cgit v0.9.1