예제 #1
0
def publish_composite_model(cursor, model, parent_model, publisher, message):
    """Publishes the ``model`` and return its ident_hash."""
    if not isinstance(model, CompositeDocument):
        raise ValueError("This function only publishes CompositeDocument "
                         "objects. '{}' was given.".format(type(model)))
    if issequence(publisher) and len(publisher) > 1:
        raise ValueError("Only one publisher is allowed. '{}' "
                         "were given: {}".format(len(publisher), publisher))
    module_ident, ident_hash = _insert_metadata(cursor, model, publisher,
                                                message)
    for resource in model.resources:
        _insert_resource_file(cursor, module_ident, resource)
    html = str(cnxepub.DocumentContentFormatter(model))
    fileid, _ = _insert_file(cursor, io.BytesIO(html.encode('utf-8')),
                             'text/html')
    file_arg = {
        'module_ident': module_ident,
        'parent_ident_hash': parent_model.ident_hash,
        'fileid': fileid,
    }
    cursor.execute(
        """\
INSERT INTO collated_file_associations
  (context, item, fileid)
VALUES
  ((SELECT module_ident FROM modules
    WHERE ident_hash(uuid, major_version, minor_version)
   = %(parent_ident_hash)s),
    %(module_ident)s, %(fileid)s)""", file_arg)

    model.id, model.metadata['version'] = split_ident_hash(ident_hash)
    model.set_uri('cnx-archive', ident_hash)
    return ident_hash
예제 #2
0
def publish_model(cursor, model, publisher, message):
    """Publishes the ``model`` and return its ident_hash."""
    publishers = publisher
    if isinstance(publishers, list) and len(publishers) > 1:
        raise ValueError("Only one publisher is allowed. '{}' "
                         "were given: {}".format(len(publishers), publishers))
    module_ident, ident_hash = _insert_metadata(cursor, model, publisher,
                                                message)

    for resource in getattr(model, 'resources', []):
        _insert_resource_file(cursor, module_ident, resource)

    if isinstance(model, Document):
        html = str(cnxepub.DocumentContentFormatter(model)).encode('utf-8')
        sha1 = hashlib.new('sha1', html).hexdigest()
        cursor.execute("SELECT fileid FROM files WHERE sha1 = %s", (sha1, ))
        try:
            fileid = cursor.fetchone()[0]
        except TypeError:
            file_args = {
                'media_type': 'text/html',
                'data': psycopg2.Binary(html),
            }
            cursor.execute(
                """\
            insert into files (file, media_type)
            VALUES (%(data)s, %(media_type)s)
            returning fileid""", file_args)
            fileid = cursor.fetchone()[0]
        args = {
            'module_ident': module_ident,
            'filename': 'index.cnxml.html',
            'fileid': fileid,
        }
        cursor.execute(
            """\
        INSERT INTO module_files
          (module_ident, fileid, filename)
        VALUES
          (%(module_ident)s, %(fileid)s, %(filename)s)""", args)

    elif isinstance(model, Binder):
        tree = cnxepub.model_to_tree(model)
        tree = _insert_tree(cursor, tree)
    return ident_hash
예제 #3
0
def publish_collated_document(cursor, model, parent_model):
    """Publish a given `module`'s collated content in the context of
    the `parent_model`. Note, the model's content is expected to already
    have the collated content. This will just persist that content to
    the archive.

    """
    html = str(cnxepub.DocumentContentFormatter(model)).encode('utf-8')
    sha1 = hashlib.new('sha1', html).hexdigest()
    cursor.execute("SELECT fileid FROM files WHERE sha1 = %s", (sha1, ))
    try:
        fileid = cursor.fetchone()[0]
    except TypeError:
        file_args = {
            'media_type': 'text/html',
            'data': psycopg2.Binary(html),
        }
        cursor.execute(
            """\
        INSERT INTO files (file, media_type)
        VALUES (%(data)s, %(media_type)s)
        RETURNING fileid""", file_args)
        fileid = cursor.fetchone()[0]
    args = {
        'module_ident_hash': model.ident_hash,
        'parent_ident_hash': parent_model.ident_hash,
        'fileid': fileid,
    }
    stmt = """\
INSERT INTO collated_file_associations (context, item, fileid)
VALUES
  ((SELECT module_ident FROM modules
    WHERE ident_hash(uuid, major_version, minor_version)
   = %(parent_ident_hash)s),
   (SELECT module_ident FROM modules
    WHERE ident_hash(uuid, major_version, minor_version)
   = %(module_ident_hash)s),
   %(fileid)s)"""
    cursor.execute(stmt, args)
예제 #4
0
def derive_resources(request, document):
    from .models import ArchiveConnectionError, Resource

    settings = request.registry.settings
    archive_url = settings['archive.url']
    path = urlparse.unquote(request.route_path('get-resource', hash='{}'))
    resources = {}
    for r in document.references:
        if r.uri.startswith('/resources'):
            if not resources.get(r.uri):
                url = urlparse.urljoin(archive_url, r.uri)
                try:
                    response = requests.get(url)
                except requests.exceptions.ConnectionError as exc:
                    raise ArchiveConnectionError(exc.message)
                if response.status_code >= 400:
                    continue
                content_type = response.headers['content-type']
                resources[r.uri] = Resource(content_type,
                                            io.BytesIO(response.content))
                yield resources[r.uri]
            r.bind(resources[r.uri], path)
    html = cnxepub.DocumentContentFormatter(document)
    document.metadata['content'] = str(html)