diff options
-rw-r--r-- | suds/cache.py | 50 | ||||
-rw-r--r-- | suds/options.py | 8 | ||||
-rw-r--r-- | suds/reader.py | 74 |
3 files changed, 94 insertions, 38 deletions
diff --git a/suds/cache.py b/suds/cache.py index 0e2b314..c2bd624 100644 --- a/suds/cache.py +++ b/suds/cache.py @@ -21,6 +21,8 @@ Contains basic caching classes. import os from tempfile import gettempdir as tmp from suds.transport import * +from suds.sax.parser import Parser +from suds.sax.element import Element from datetime import datetime as dt from datetime import timedelta from cStringIO import StringIO @@ -115,8 +117,6 @@ class FileCache(Cache): """ A file-based URL cache. @cvar fnprefix: The file name prefix. - @type fnprefix: str - @ivar fnsuffix: The file name suffix. @type fnsuffix: str @ivar duration: The cached file duration which defines how long the file will be cached. @@ -125,7 +125,6 @@ class FileCache(Cache): @type location: str """ fnprefix = 'suds' - fnsuffix = 'gcf' units = ('months', 'weeks', 'days', 'hours', 'minutes', 'seconds') def __init__(self, location=None, **duration): @@ -143,6 +142,14 @@ class FileCache(Cache): self.duration = (None, 0) self.setduration(**duration) + def fnsuffix(self): + """ + Get the file name suffix + @return: The suffix + @rtype: str + """ + return 'gcf' + def setduration(self, **duration): """ Set the caching duration which defines how long the @@ -255,14 +262,34 @@ class FileCache(Cache): return open(fn, *args) def __fn(self, id): - if hasattr(id, 'name') and hasattr(id, 'suffix'): - name = id.name - suffix = id.suffix - else: - name = id - suffix = self.fnsuffix - fn = '%s-%s.%s' % (self.fnprefix, abs(hash(name)), suffix) + name = id + suffix = self.fnsuffix() + fn = '%s-%s.%s' % (self.fnprefix, name, suffix) return os.path.join(self.location, fn) + + +class DocumentCache(FileCache): + """ + Provides xml document caching. + """ + + def fnsuffix(self): + return 'xml' + + def get(self, id): + try: + fp = FileCache.getf(self, id) + if fp is None: + return None + p = Parser() + return p.parse(fp) + except: + FileCache.purge(self, id) + + def put(self, id, object): + if isinstance(object, Element): + FileCache.put(self, id, str(object)) + return object class ObjectCache(FileCache): @@ -273,6 +300,9 @@ class ObjectCache(FileCache): """ protocol = 2 + def fnsuffix(self): + return 'px' + def get(self, id): try: fp = FileCache.getf(self, id) diff --git a/suds/options.py b/suds/options.py index 7e5c069..4cf3660 100644 --- a/suds/options.py +++ b/suds/options.py @@ -85,9 +85,14 @@ class Options(Skin): - type: I{bool} - default: False - B{autoblend} - Flag that ensures that the schema(s) defined within the - WSDL import each other. B{**Experimental**}. + WSDL import each other. - type: I{bool} - default: False + - B{cachingpolicy} - The caching policy. + - type: I{int} + - 0 = Cache XML documents. + - 1 = Cache WSDL (pickled) object. + - default: 0 """ def __init__(self, **kwargs): domain = __name__ @@ -105,5 +110,6 @@ class Options(Skin): Definition('prefixes', bool, True), Definition('retxml', bool, False), Definition('autoblend', bool, False), + Definition('cachingpolicy', int, 0), ] Skin.__init__(self, domain, definitions, kwargs) diff --git a/suds/reader.py b/suds/reader.py index 84e6822..0bac400 100644 --- a/suds/reader.py +++ b/suds/reader.py @@ -21,6 +21,7 @@ Contains xml document reader classes. from suds.sax.parser import Parser from suds.transport import Request +from suds.cache import Cache, NoCache from suds.store import DocumentStore from logging import getLogger @@ -28,31 +29,34 @@ from logging import getLogger log = getLogger(__name__) -class ObjectId(object): - - def __init__(self, name, suffix): - self.name = name - self.suffix = suffix - - -class DocumentReader: +class Reader: """ - The XML document reader provides an integration - between the SAX L{Parser} and the document cache. - @cvar suffix: The cache file suffix. - @type suffix: str + The reader provides integration with cache. @ivar options: An options object. @type options: I{Options} """ - - suffix = 'pxd' - + def __init__(self, options): """ @param options: An options object. @type options: I{Options} """ self.options = options + + def mangle(self, name, x): + """ + Mangle the name by hashing the I{name} and appending I{x}. + @return: the mangled name. + """ + h = abs(hash(name)) + return '%s-%s' % (h, x) + + +class DocumentReader(Reader): + """ + The XML document reader provides an integration + between the SAX L{Parser} and the document cache. + """ def open(self, url): """ @@ -66,8 +70,8 @@ class DocumentReader: @return: The specified XML document. @rtype: I{Document} """ - id = ObjectId(url, self.suffix) - cache = self.options.cache + cache = self.cache() + id = self.mangle(url, 'document') d = cache.get(id) if d is None: d = self.download(url) @@ -88,23 +92,28 @@ class DocumentReader: fp = self.options.transport.open(Request(url)) sax = Parser() return sax.parse(file=fp) + + def cache(self): + """ + Get the cache. + @return: The I{options} when I{cachingpolicy} = B{0}. + @rtype: L{Cache} + """ + if self.options.cachingpolicy == 0: + return self.options.cache + else: + return NoCache() -class DefinitionsReader: +class DefinitionsReader(Reader): """ The WSDL definitions reader provides an integration between the Definitions and the object cache. - @cvar suffix: The cache file suffix. - @type suffix: str - @ivar options: An options object. - @type options: I{Options} @ivar fn: A factory function (constructor) used to create the object not found in the cache. @type fn: I{Constructor} """ - suffix = 'pw' - def __init__(self, options, fn): """ @param options: An options object. @@ -113,7 +122,7 @@ class DefinitionsReader: create the object not found in the cache. @type fn: I{Constructor} """ - self.options = options + Reader.__init__(self, options) self.fn = fn def open(self, url): @@ -129,8 +138,8 @@ class DefinitionsReader: @return: The WSDL object. @rtype: I{Definitions} """ - id = ObjectId(url, self.suffix) - cache = self.options.cache + cache = self.cache() + id = self.mangle(url, 'wsdl') d = cache.get(id) if d is None: d = self.fn(url, self.options) @@ -140,3 +149,14 @@ class DefinitionsReader: for imp in d.imports: imp.imported.options = self.options return d + + def cache(self): + """ + Get the cache. + @return: The I{options} when I{cachingpolicy} = B{1}. + @rtype: L{Cache} + """ + if self.options.cachingpolicy == 1: + return self.options.cache + else: + return NoCache()
\ No newline at end of file |