def test_get_cached_file(self, cache_env): # we can get a file cached before. cm = CacheManager(str(cache_env / "cache")) cache_key = cm.register_doc(str(cache_env / "src1.txt"), str(cache_env / "result1.txt")) path = cm.get_cached_file(cache_key) assert path is not None assert open(path, 'r').read() == (cache_env / "result1.txt").read()
def test_get_cached_file_w_key_from_file(self, cache_env): # we can get a cached file, stored under a key, which is a file cm = CacheManager(str(cache_env / "cache")) cache_key = cm.register_doc(str(cache_env / "src1.txt"), str(cache_env / "result1.txt"), repr_key=StringIO('foo')) path = cm.get_cached_file(cache_key) assert path is not None assert open(path, 'r').read() == (cache_env / "result1.txt").read()
def test_get_cached_file(self, cache_env): # we can get a file cached before. cm = CacheManager(str(cache_env / "cache")) cache_key = cm.register_doc( str(cache_env / "src1.txt"), str(cache_env / "result1.txt")) path = cm.get_cached_file(cache_key) assert path is not None assert open(path, 'r').read() == ( cache_env / "result1.txt").read()
def test_get_cached_file_w_key_from_file(self, cache_env): # we can get a cached file, stored under a key, which is a file cm = CacheManager(str(cache_env / "cache")) cache_key = cm.register_doc( str(cache_env / "src1.txt"), str(cache_env / "result1.txt"), repr_key=StringIO('foo')) path = cm.get_cached_file(cache_key) assert path is not None assert open(path, 'r').read() == ( cache_env / "result1.txt").read()
def test_get_cached_file(self): cm = CacheManager(self.workdir) path = cm.get_cached_file(self.src_path1) self.assertTrue(path is None) self.assertEqual(os.listdir(self.workdir), []) my_id1 = cm.register_doc(self.src_path1, self.result_path1) path1 = cm.get_cached_file(my_id1) self.assertTrue(path1 is not None) my_id2 = cm.register_doc( self.src_path2, self.result_path1, repr_key='foo') path1 = cm.get_cached_file(my_id2) self.assertTrue(path1 is not None) my_id3 = cm.register_doc( self.src_path2, self.result_path1, repr_key=StringIO('foo')) path1 = cm.get_cached_file(my_id3) self.assertTrue(path1 is not None) self.assertEqual(my_id2, my_id3) self.assertEqual(cm.get_cached_file('nonsense_really'), None) return
def test_convert_to_pdf_cached_wo_cache_key(self): # We can get a cached doc also without a cache key (but # it is extensive) self.doc = Document('mytestdoc.doc', self.doc_simple1, self.workdir) pdf1, cache_key1 = self.doc.convertToPDF() # store doc in cache # modfiy result to distuingish it from freshly converted doc from ulif.openoffice.cachemanager import CacheManager cm = CacheManager(self.workdir) cached_path = cm.get_cached_file(cache_key1) open(cached_path, 'wb').write('My Fake Result') # now re-get the document. We should get the cached copy self.doc = Document('mytestdoc.doc', self.doc_simple1, self.workdir) pdf2, cache_key2 = self.doc.convertToPDF() self.assertEqual(pdf2, 'My Fake Result') self.assertEqual(cache_key2, cache_key1)
def test_get_cached_file_invalid_cache_key(self, tmpdir): # invalid/unused cache keys return `None` as cached file. cm = CacheManager(str(tmpdir)) assert cm.get_cached_file("not-existing") is None
def test_get_cached_file_empty(self, cache_env): # while cache is empty we get `None` when asking for cached files. cm = CacheManager(str(cache_env / "cache")) path = cm.get_cached_file(str(cache_env / "src1.txt")) assert path is None
class RESTfulDocConverter(object): """A WSGI app that caches and converts office documents via LibreOffice. It acts as a RESTful document store that supports HTTP actions to add/modify/retrieve converted documents. Accepted arguments: - `cache_dir`: Path to a directory, where cached files can be stored. The directory is created if it does not exist. """ # cf: https://routes.readthedocs.io/en/latest/restful.html # http://www.ianbicking.org/blog/2010/03/12/a-webob-app-example/ map = Mapper() map.resource('doc', 'docs') #: A cache manager instance. cache_manager = None template_dir = os.path.join(os.path.dirname(__file__), 'templates') def __init__(self, cache_dir=None): self.cache_dir = cache_dir self.cache_manager = None if self.cache_dir is not None: self.cache_manager = CacheManager(self.cache_dir) def _url(self, req, *args, **kw): """Generate an URL pointing to some REST service. `req` is the current request. Arguments and keywords are passed on to the generated :class:`routes.util.URLGenerator` instance. So you can use it like the `url` method described in the `routes` docs, except that you have to pass in the `req` parameter first. """ url = URLGenerator(self.map, req.environ) return url(*args, **kw) @wsgify def __call__(self, req): results = self.map.routematch(environ=req.environ) if not results: return exc.HTTPNotFound() match, route = results return getattr(self, match['action'])(req) def index(self, req): # get index of all docs return Response(str(mydocs.keys())) def create(self, req): # post a new doc options = dict([(name, val) for name, val in req.params.items() if name not in ('CREATE', 'doc', 'docid')]) if 'out_fmt' in req.params.keys(): options['oocp-out-fmt'] = options['out_fmt'] del options['out_fmt'] if 'CREATE' in req.params.keys(): if options.get('oocp-out-fmt', 'html') == 'pdf': options['meta-procord'] = 'unzip,oocp,zip' doc = req.POST['doc'] # write doc to filesystem tmp_dir = tempfile.mkdtemp() src_path = os.path.join(tmp_dir, doc.filename) with open(src_path, 'wb') as f: for chunk in iter(lambda: doc.file.read(8 * 1024), b''): f.write(chunk) # do the conversion result_path, id_tag, metadata = convert_doc(src_path, options, self.cache_dir) # deliver the created file resp = make_response(result_path) if id_tag is not None: # we can only signal new resources if cache is enabled resp.status = '201 Created' resp.location = self._url(req, 'doc', id=id_tag, qualified=True) return resp def new(self, req): # get a form to create a new doc template = open(os.path.join(self.template_dir, 'form_new.tpl')).read() template = template.format(target_url=self._url(req, 'docs')) return Response(template) def update(self, req): # put/update an existing doc pass # pragma: no cover def delete(self, req): # delete a doc pass # pragma: no cover def edit(self, req): # edit a doc pass # pragma: no cover def show(self, req): # show a doc doc_id = req.path.split('/')[-1] result_path = self.cache_manager.get_cached_file(doc_id) if result_path is None: return exc.HTTPNotFound() return make_response(result_path)
class Client(object): """A client to trigger document conversions. """ def __init__(self, cache_dir=None): self.cache_dir = cache_dir self.cache_manager = None if self.cache_dir is not None: self.cache_manager = CacheManager(self.cache_dir) def convert(self, src_doc_path, options={}): """Convert `src_doc_path` according to `options`. Calls :func:`convert_doc` internally and returns the result given by this function. """ return convert_doc(src_doc_path, options, self.cache_dir) def get_cached(self, cache_key): """Get the document from cache stored under `cache_key`. Returns ``None`` if no such file can be found or no cache dir was set at all. .. warning:: The returned path (if any) is part of cache! Do not remove or change the file. Copy it to another location instead. .. versionadded:: 1.1 """ if self.cache_manager is not None: return self.cache_manager.get_cached_file(cache_key) return None def get_cached_by_source(self, src_doc_path, options={}): """Get the document from cache by source doc and options. Find a cached document, which was created from the given `src_doc_path` and `options`. Returns the path to the document and a cache key you are encouraged to use for future access. Please note that this method is much more expensive than :meth:`get_cached`. Use it only if the `cache_key` returned upon registering a doc is absolutely not available any more. Returns ``(None, None)`` if no such file can be found or no cache dir was set at all. .. warning:: The returned path (if any) is part of cache! Do not remove or change the file. Copy it to another location instead. .. versionadded:: 1.1 """ repr_key = get_marker(options) if self.cache_manager is not None: return self.cache_manager.get_cached_file_by_source( src_doc_path, repr_key) return None, None
class RESTfulDocConverter(object): """A WSGI app that caches and converts office documents via LibreOffice. It acts as a RESTful document store that supports HTTP actions to add/modify/retrieve converted documents. Accepted arguments: - `cache_dir`: Path to a directory, where cached files can be stored. The directory is created if it does not exist. """ # cf: https://routes.readthedocs.io/en/latest/restful.html # http://www.ianbicking.org/blog/2010/03/12/a-webob-app-example/ map = Mapper() map.resource('doc', 'docs') #: A cache manager instance. cache_manager = None template_dir = os.path.join(os.path.dirname(__file__), 'templates') def __init__(self, cache_dir=None): self.cache_dir = cache_dir self.cache_manager = None if self.cache_dir is not None: self.cache_manager = CacheManager(self.cache_dir) def _url(self, req, *args, **kw): """Generate an URL pointing to some REST service. `req` is the current request. Arguments and keywords are passed on to the generated :class:`routes.util.URLGenerator` instance. So you can use it like the `url` method described in the `routes` docs, except that you have to pass in the `req` parameter first. """ url = URLGenerator(self.map, req.environ) return url(*args, **kw) @wsgify def __call__(self, req): results = self.map.routematch(environ=req.environ) if not results: return exc.HTTPNotFound() match, route = results return getattr(self, match['action'])(req) def index(self, req): # get index of all docs return Response(str(list(mydocs.keys()))) def create(self, req): # post a new doc options = dict([(name, val) for name, val in list(req.params.items()) if name not in ('CREATE', 'doc', 'docid')]) if 'out_fmt' in list(req.params.keys()): options['oocp-out-fmt'] = options['out_fmt'] del options['out_fmt'] if 'CREATE' in list(req.params.keys()): if options.get('oocp-out-fmt', 'html') == 'pdf': options['meta-procord'] = 'unzip,oocp,zip' doc = req.POST['doc'] # write doc to filesystem tmp_dir = tempfile.mkdtemp() src_path = os.path.join(tmp_dir, doc.filename) with open(src_path, 'wb') as f: for chunk in iter(lambda: doc.file.read(8 * 1024), b''): f.write(chunk) # do the conversion result_path, id_tag, metadata = convert_doc( src_path, options, self.cache_dir) # deliver the created file resp = make_response(result_path) if id_tag is not None: # we can only signal new resources if cache is enabled resp.status = '201 Created' resp.location = self._url(req, 'doc', id=id_tag, qualified=True) return resp def new(self, req): # get a form to create a new doc template = open( os.path.join(self.template_dir, 'form_new.tpl')).read() template = template.format(target_url=self._url(req, 'docs')) return Response(template) def update(self, req): # put/update an existing doc pass # pragma: no cover def delete(self, req): # delete a doc pass # pragma: no cover def edit(self, req): # edit a doc pass # pragma: no cover def show(self, req): # show a doc doc_id = req.path.split('/')[-1] result_path = self.cache_manager.get_cached_file(doc_id) if result_path is None: return exc.HTTPNotFound() return make_response(result_path)
def test_get_cached_file_invalid_cache_key(self, tmpdir): # invalid/unused cache keys return `None` as cached file. cm = CacheManager(str(tmpdir)) assert cm.get_cached_file("not-existing") is None
def test_get_cached_file_empty(self, cache_env): # while cache is empty we get `None` when asking for cached files. cm = CacheManager(str(cache_env / "cache")) path = cm.get_cached_file(str(cache_env / "src1.txt")) assert path is None
class Client(object): """A client to trigger document conversions. """ def __init__(self, cache_dir=None): self.cache_dir = cache_dir self.cache_manager = None if self.cache_dir is not None: self.cache_manager = CacheManager(self.cache_dir) def convert(self, src_doc_path, options={}): """Convert `src_doc_path` according to `options`. Calls :func:`convert_doc` internally and returns the result given by this function. """ return convert_doc(src_doc_path, options, self.cache_dir) def get_cached(self, cache_key): """Get the document from cache stored under `cache_key`. Returns ``None`` if no such file can be found or no cache dir was set at all. .. warning:: The returned path (if any) is part of cache! Do not remove or change the file. Copy it to another location instead. .. versionadded:: 1.1 """ if self.cache_manager is not None: return self.cache_manager.get_cached_file(cache_key) return None def get_cached_by_source(self, src_doc_path, options={}): """Get the document from cache by source doc and options. Find a cached document, which was created from the given `src_doc_path` and `options`. Returns the path to the document and a cache key you are encouraged to use for future access. Please note that this method is much more expensive than :meth:`get_cached`. Use it only if the `cache_key` returned upon registering a doc is absolutely not available any more. Returns ``(None, None)`` if no such file can be found or no cache dir was set at all. .. warning:: The returned path (if any) is part of cache! Do not remove or change the file. Copy it to another location instead. .. versionadded:: 1.1 """ repr_key = get_marker(options) if self.cache_manager is not None: return self.cache_manager.get_cached_file_by_source( src_doc_path, repr_key) return None, None