예제 #1
0
 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()
예제 #2
0
 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()
예제 #3
0
 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()
예제 #4
0
 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()
예제 #5
0
    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
예제 #6
0
 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)
예제 #7
0
 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
예제 #8
0
 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
예제 #9
0
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)
예제 #10
0
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
예제 #11
0
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)
예제 #12
0
 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
예제 #13
0
 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
예제 #14
0
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