def create_epub(ident_hash, file, format='raw'): """Creates an epub from an ``ident_hash``, which is output to the given ``file`` (a file-like object). Returns None, writes to the given ``file``. """ model = factory(ident_hash, baked=(format != 'raw')) if isinstance(model, cnxepub.Document): model = cnxepub.TranslucentBinder(nodes=[model]) cnxepub.make_epub(model, file)
def tree_to_nodes(tree, context=None, metadata=None): """Assembles ``tree`` nodes into object models. If ``context`` is supplied, it will be used to contextualize the contents of the nodes. Metadata will pass non-node identifying values down to child nodes, if not overridden (license, timestamps, etc) """ nodes = [] for item in tree['contents']: if 'contents' in item: sub_nodes = tree_to_nodes(item, context=context, metadata=metadata) if metadata is None: metadata = {} else: metadata = metadata.copy() for key in ('title', 'id', 'shortid', 'cnx-archive-uri', 'cnx-archive-shortid'): if key in metadata: metadata.pop(key) for key in ('title', 'id', 'shortId'): if item.get(key): metadata[key] = item[key] if item[key] != 'subcol': if key == 'id': metadata['cnx-archive-uri'] = item[key] elif key == 'shortId': metadata['cnx-archive-shortid'] = item[key] titles = _title_overrides_from_tree(item) if item.get('id') is not None: tbinder = cnxepub.Binder(item.get('id'), sub_nodes, metadata=metadata, title_overrides=titles) else: tbinder = cnxepub.TranslucentBinder(sub_nodes, metadata=metadata, title_overrides=titles) nodes.append(tbinder) else: doc = document_factory(item['id'], context=context) for key in ('title', 'id', 'shortId'): if item.get(key): doc.metadata[key] = item[key] if key == 'id': doc.metadata['cnx-archive-uri'] = item[key] elif key == 'shortId': doc.metadata['cnx-archive-shortid'] = item[key] nodes.append(doc) return nodes
def setUp(self, cursor): super(RemoveBakedTestCase, self).setUp() binder = use_cases.setup_COMPLEX_BOOK_ONE_in_archive(self, cursor) cursor.connection.commit() publisher = 'ream' msg = 'part of collated publish' # Build some new metadata for the composite document. metadata = [ x.metadata.copy() for x in cnxepub.flatten_to_documents(binder) ][0] del metadata['cnx-archive-uri'] del metadata['version'] metadata['created'] = None metadata['revised'] = None metadata['title'] = "Made up of other things" # Add some fake collation objects to the book. content = '<p>composite</p>' composite_doc = cnxepub.CompositeDocument(None, content, metadata) composite_section = cnxepub.TranslucentBinder( nodes=[composite_doc], metadata={'title': "Other things"}) baked_doc_content = '<p>collated</p>' def cnxepub_collate(binder_model, ruleset=None, includes=None): binder_model[0][0].content = baked_doc_content binder_model.append(composite_section) return binder_model with mock.patch('cnxpublishing.bake.collate_models') as mock_collate: mock_collate.side_effect = cnxepub_collate from cnxpublishing.bake import bake fake_recipe_id = 1 errors = bake(binder, fake_recipe_id, publisher, msg, cursor=cursor) self.ident_hash = binder.ident_hash self.composite_ident_hash = composite_doc.ident_hash self.baked_doc_sha1 = self._get_file_sha1(cursor, binder[0][0], binder) self.composite_doc_sha1 = self._get_file_sha1(cursor, composite_doc, binder)
def tree_to_nodes(tree, context=None): """Assembles ``tree`` nodes into object models. If ``context`` is supplied, it will be used to contextualize the contents of the nodes. """ nodes = [] for item in tree['contents']: if 'contents' in item: sub_nodes = tree_to_nodes(item, context=context) titles = _title_overrides_from_tree(item) metadata = {} for key in ('title', 'id', 'shortId'): if item.get(key): metadata[key] = item[key] if item[key] != 'subcol': if key == 'id': metadata['cnx-archive-uri'] = item[key] elif key == 'shortId': metadata['cnx-archive-shortid'] = item[key] if item.get('id') is not None: tbinder = cnxepub.Binder(item.get('id'), sub_nodes, metadata=metadata, title_overrides=titles) else: tbinder = cnxepub.TranslucentBinder(sub_nodes, metadata=metadata, title_overrides=titles) nodes.append(tbinder) else: doc = document_factory(item['id'], context=context) for key in ('title', 'id', 'shortId'): if item.get(key): doc.metadata[key] = item[key] if key == 'id': doc.metadata['cnx-archive-uri'] = item[key] elif key == 'shortId': doc.metadata['cnx-archive-shortid'] = item[key] nodes.append(doc) return nodes
cnxepub.TranslucentBinder( metadata={u'title': u'Part One'}, nodes=[ cnxepub.TranslucentBinder( metadata={u'title': u'Chapter One'}, title_overrides=['Document One'], nodes=[ cnxepub.Document( id=u'2cf4d7d3@draft', data= u'<p class="para">If you finish the book, there will be cake.</p><img src="../resources/{}">' .format(RESOURCE_ONE_FILENAME), resources=[ cnxepub.Resource( RESOURCE_ONE_FILENAME, _read_file(RESOURCE_ONE_FILEPATH, 'rb'), 'image/png', filename=RESOURCE_ONE_FILENAME) ], metadata={ u'title': u'Document One of Infinity', u'created': u'2013/03/19 15:01:16 -0500', u'revised': u'2013/03/19 15:01:16 -0500', u'keywords': [u'South Africa'], u'subjects': [ u'Mathematics and Statistics', ], u'summary': u"<span xmlns='http://www.w3.org/1999/xhtml'>descriptive text</span>", u'language': u'en', u'license_text': u'CC-By 4.0', u'license_url': u'http://creativecommons.org/licenses/by/4.0/', u'authors': [{ u'id': u'marknewlyn', u'name': u'Mark Horner', u'type': u'cnx-id' }, { u'id': u'charrose', u'name': u'Charmaine St. Rose', u'type': u'cnx-id' }, { u'id': u'sarblyth', u'name': u'Sarah Blyth', u'type': u'cnx-id' }], u'copyright_holders': [{ u'id': u'ream', u'name': u'Ream', u'type': u'cnx-id' }], u'editors': [{ u'id': u'impicky', u'name': u'I. M. Picky', u'type': u'cnx-id' }], u'illustrators': [{ u'id': u'frahablar', u'name': u'Francis Hablar', u'type': u'cnx-id' }], u'publishers': [{ u'id': u'ream', u'name': u'Ream', u'type': u'cnx-id' }, { u'id': u'rings', u'name': u'Rings', u'type': u'cnx-id' }], u'translators': [{ u'id': u'frahablar', u'name': u'Francis Hablar', u'type': u'cnx-id' }], u'print_style': u'*print style*', }), ]), ]),
def test(self, cursor): binder = use_cases.setup_COMPLEX_BOOK_ONE_in_archive(self, cursor) cursor.connection.commit() publisher = 'ream' msg = 'part of collated publish' # Build some new metadata for the composite document. metadata = [ x.metadata.copy() for x in cnxepub.flatten_to_documents(binder) ][0] del metadata['cnx-archive-uri'] del metadata['version'] metadata['created'] = None metadata['revised'] = None metadata['title'] = "Made up of other things" # Add some fake collation objects to the book. content = '<p>composite</p>' composite_doc = cnxepub.CompositeDocument(None, content, metadata) composite_section = cnxepub.TranslucentBinder( nodes=[composite_doc], metadata={'title': "Other things"}) baked_doc_content = '<p>collated</p>' def cnxepub_collate(binder_model, ruleset=None, includes=None): binder_model[0][0].content = baked_doc_content binder_model.append(composite_section) return binder_model fake_recipe_id = 1 with mock.patch('cnxpublishing.bake.collate_models') as mock_collate: mock_collate.side_effect = cnxepub_collate errors = self.target(binder, fake_recipe_id, publisher, msg) # Ensure the output of the errors. self.assertEqual(errors, []) # Ensure the original tree is intact. cursor.execute("SELECT tree_to_json(%s, %s, FALSE)::json;", ( binder.id, binder.metadata['version'], )) tree = cursor.fetchone()[0] self.assertNotIn(composite_doc.ident_hash, cnxepub.flatten_tree_to_ident_hashes(tree)) # Ensure the tree as been stamped. cursor.execute("SELECT tree_to_json(%s, %s, TRUE)::json;", ( binder.id, binder.metadata['version'], )) baked_tree = cursor.fetchone()[0] self.assertIn(composite_doc.ident_hash, cnxepub.flatten_tree_to_ident_hashes(baked_tree)) # Ensure the changes to a document content were persisted. content_to_check = [ ( binder[0][0], baked_doc_content, ), ( composite_doc, content, ), ] for doc, content in content_to_check: self.assertIn(content, self._get_baked_file(cursor, doc, binder))