#! /usr/bin/python """ $Id: term.py,v 1.37 2005/07/21 15:22:59 syosi Exp $ term This module defines objects correspodning to the basic terms in the RDF and N3 langauges: Symbols, Literals and Lists. (The N3 language goes on to include formuale, which are defined elsewhere) The code in this module deals with the represnetation of these terms and in debug form (__repr__) Interning of URIs and strings for storage in SWAP store. It also defines th utility Namespace module which makes using terms in practice both more convenient maybe even more efficient than carrying full URIs around. Includes: - template classes for builtins """ from __future__ import generators # for yield import string, sys, types from set_importer import Set, ImmutableSet import uripath # DanC's tested and correct one import md5, binascii # for building md5 URIs from uripath import refTo from RDFSink import runNamespace from local_decimal import Decimal # for xsd:decimal LITERAL_URI_prefix = "data:application/rdf+n3-literal;" import diag from diag import progress import sys if sys.hexversion < 0x02030000: raise RuntimeError("Sorry, this software requires python2.3 or newer.") import weakref class FakeError(RuntimeError): pass def interner(sub, cls, args, keywords={}, **keys): keys.update(keywords) ########################## ### What follows is interning code hashable = (args, ImmutableSet(keywords.iteritems())) try: m = sub.__interned__[hashable] if not isinstance(m, cls): if issubclass(cls, m.__class__): m.__class__ = cls else: raise ValueError return m except AttributeError: sub.__interned__ = weakref.WeakValueDictionary() except KeyError: pass except FakeError: pass ### End interning stuff ############################# self = super(sub, cls).__new__(cls, *args) for k, v in keywords.iteritems(): setattr(self, k, v) return self class Term(object): store = None # I need a replacement for the store class Symbol(Term): __slots__ = ['__weakref__', '_uri'] def __new__(cls, uri, store=None, **keywords): self = interner(cls, Symbol, [], _uri=uri, **keywords) return self def uri(self): return self._uri uri = property(uri) def uriref(self): return self.uri def __hash__(self): return hash(self.uri) def __repr__(self): return '<%s>' % self.uri def __getitem__(self, other): return Symbol(self.uri+other) class BuiltIn(Symbol): pass class Literal(Term): __slots__ = ['__weakref__', '_str', '_datatype', '_lang'] def __new__(cls, string, dt=None, lang=None): assert not dt or not lang dt = dt or None lang = lang or None self = interner(cls, Literal, [], _str=string, _datatype=dt, _lang=lang}) return self def string(self): return self._str string = property(str) def datatype(self): return self._datatype datatype = property(datatype) def lang(self): return self._lang lang = property(lang) def __str__(self): return self.string class CompoundTerm(Term): pass class List(tuple, CompoundTerm): def __new__(cls, iter): self = interner(cls, tuple, [iter]) return self def __getslice__(self, start, end): return List(tuple.__getslice__(start, end)) def __getitem__(self, k): if isinstance(k, slice): return List(tuple.__getitem__(k)) return tuple.__getitem__(k)