def test_loaderException(self): """ Test that an exception raised from the loader does not break the L{CachedFile}. """ counter = count() def _loadMe(path, crashMe=False): if crashMe: raise Exception('It is an exception!') return next(counter) cf = CachedFile(self.testFile, _loadMe) # Can we still load after the first attempt raises an exception? self.assertRaises(Exception, cf.load, True) self.assertEqual(cf.load(), 0) # Cache should be valid now, so a broken loader shouldn't matter self.assertEqual(cf.load(True), 0) # A second broken load cf.invalidate() self.assertRaises(Exception, cf.load, True) self.assertEqual(cf.load(), 1)
class JSModule(object): _modules = {} lastModified = 0 deps = None packageDeps = [] def getOrCreate(cls, name, mapping): # XXX This implementation of getOrCreate precludes the # simultaneous co-existence of several different package # namespaces. if name in cls._modules: return cls._modules[name] mod = cls._modules[name] = cls(name, mapping) return mod getOrCreate = classmethod(getOrCreate) def __init__(self, name, mapping): self.name = name self.mapping = mapping if '.' in name: parent = '.'.join(name.split('.')[:-1]) self.packageDeps = [self.getOrCreate(parent, mapping)] self._cache = CachedFile(self.mapping[self.name], self._getDeps) def __repr__(self): return 'JSModule(%r)' % (self.name, ) _importExpression = re.compile('^// import (.+)$', re.MULTILINE) def _extractImports(self, fileObj): s = fileObj.read() for m in self._importExpression.finditer(s): yield self.getOrCreate(m.group(1).decode('ascii'), self.mapping) def _getDeps(self, jsFile): """ Calculate our dependencies given the path to our source. """ depgen = self._extractImports(file(jsFile, 'r')) return self.packageDeps + dict.fromkeys(depgen).keys() def dependencies(self): """ Return a list of names of other JavaScript modules we depend on. """ return self._cache.load() def allDependencies(self): if self.mapping[self.name] is None: return [] else: mods = [self] return dependencyOrdered(mods)
class htmlfile(object): """A document factory for an HTML disk template""" implements(inevow.IDocFactory) template = None pattern = None templateDir = '' beExtremelyLenient = True def __init__(self, template=None, pattern=None, templateDir=None, beExtremelyLenient=None): warnings.warn( "[v0.8] htmlfile is deprecated because it's buggy. Please start using xmlfile and/or xmlstr.", DeprecationWarning, stacklevel=2) if template is not None: self.template = template if pattern is not None: self.pattern = pattern if templateDir is not None: self.templateDir = templateDir if beExtremelyLenient is not None: self.beExtremelyLenient = beExtremelyLenient _filename = os.path.join(self.templateDir, self.template) self._cache = CachedFile(_filename, self._reallyLoad) def _reallyLoad(self, path, ctx): doc = microdom.parse(path, beExtremelyLenient=self.beExtremelyLenient) doc = flat.precompile(doc, ctx) if self.pattern is not None: doc = inevow.IQ(doc).onePattern(self.pattern) return doc def load(self, ctx=None, preprocessors=()): assert not preprocessors, "preprocessors not supported by htmlfile" return self._cache.load(ctx)
class htmlfile(object): """A document factory for an HTML disk template""" implements(inevow.IDocFactory) template = None pattern = None templateDir = "" beExtremelyLenient = True def __init__(self, template=None, pattern=None, templateDir=None, beExtremelyLenient=None): warnings.warn( "[v0.8] htmlfile is deprecated because it's buggy. Please start using xmlfile and/or xmlstr.", DeprecationWarning, stacklevel=2, ) if template is not None: self.template = template if pattern is not None: self.pattern = pattern if templateDir is not None: self.templateDir = templateDir if beExtremelyLenient is not None: self.beExtremelyLenient = beExtremelyLenient _filename = os.path.join(self.templateDir, self.template) self._cache = CachedFile(_filename, self._reallyLoad) def _reallyLoad(self, path, ctx): doc = microdom.parse(path, beExtremelyLenient=self.beExtremelyLenient) doc = flat.precompile(doc, ctx) if self.pattern is not None: doc = inevow.IQ(doc).onePattern(self.pattern) return doc def load(self, ctx=None, preprocessors=()): assert not preprocessors, "preprocessors not supported by htmlfile" return self._cache.load(ctx)
class CachedFileTests(TestCase): def setUp(self): self.testFile = self.mktemp() file(self.testFile, 'w').close() counter = count() self.cache = CachedFile(self.testFile, lambda path: next(counter)) def test_cache(self): """ Test that loading a file twice returns the cached version the second time. """ o1 = self.cache.load() o2 = self.cache.load() self.assertEqual(o1, o2) def test_cacheModifiedTime(self): """ Test that loading a cached file with a different mtime loads the file again. """ mtime = getmtime(self.testFile) o = self.cache.load() # sanity check self.assertEqual(o, 0) utime(self.testFile, (mtime + 100, mtime + 100)) o = self.cache.load() self.assertEqual(o, 1) utime(self.testFile, (mtime, mtime)) o = self.cache.load() self.assertEqual(o, 2) def test_cacheInvalidate(self): """ Test that calling invalidate really invalidates the cache. """ self.assertEqual(self.cache.load(), 0) self.cache.invalidate() self.assertEqual(self.cache.load(), 1) def test_loadArgs(self): """ Test that additional arguments are correctly passed through to the loader. """ marker = object() def _loadMe(path, otherArg, otherKwarg): self.assertIdentical(otherArg, marker) self.assertIdentical(otherKwarg, marker) CachedFile(self.testFile, _loadMe).load(marker, otherKwarg=marker) def test_loaderException(self): """ Test that an exception raised from the loader does not break the L{CachedFile}. """ counter = count() def _loadMe(path, crashMe=False): if crashMe: raise Exception('It is an exception!') return next(counter) cf = CachedFile(self.testFile, _loadMe) # Can we still load after the first attempt raises an exception? self.assertRaises(Exception, cf.load, True) self.assertEqual(cf.load(), 0) # Cache should be valid now, so a broken loader shouldn't matter self.assertEqual(cf.load(True), 0) # A second broken load cf.invalidate() self.assertRaises(Exception, cf.load, True) self.assertEqual(cf.load(), 1)