def _formatter_callback_factory(): # pragma: no cover """Returns a list of includes to be given to `cnxepub.collation.collate`. """ includes = [] settings = get_current_registry().settings exercise_url_template = settings.get( 'embeddables.exercise.url_template', None) exercise_match = settings.get('embeddables.exercise.match', None) exercise_token = settings.get('embeddables.exercise.token', None) mathml_url = settings.get('mathmlcloud.url', None) memcache_servers = settings.get('memcache_servers') if memcache_servers: memcache_servers = memcache_servers.split() else: memcache_servers = None if exercise_url_template and exercise_match: mc_client = None if memcache_servers: mc_client = memcache.Client(memcache_servers, debug=0) includes.append(exercise_callback_factory(exercise_match, exercise_url_template, mc_client, exercise_token, mathml_url)) return includes
def _formatter_callback_factory(): # pragma: no cover """Returns a list of includes to be given to `cnxepub.collation.collate`. """ includes = [] exercise_url_template = '{baseUrl}/api/exercises?q={field}:"{{itemCode}}"' settings = get_current_registry().settings exercise_base_url = settings.get('embeddables.exercise.base_url', None) exercise_matches = [match.split(',', 1) for match in aslist( settings.get('embeddables.exercise.match', ''), flatten=False)] exercise_token = settings.get('embeddables.exercise.token', None) mathml_url = settings.get('mathmlcloud.url', None) memcache_servers = settings.get('memcache_servers') if memcache_servers: memcache_servers = memcache_servers.split() else: memcache_servers = None if exercise_base_url and exercise_matches: mc_client = None if memcache_servers: mc_client = memcache.Client(memcache_servers, debug=0) for (exercise_match, exercise_field) in exercise_matches: template = exercise_url_template.format( baseUrl=exercise_base_url, field=exercise_field) includes.append(exercise_callback_factory(exercise_match, template, mc_client, exercise_token, mathml_url)) return includes
def assemble(ctx, input_dir, output_dir, exercise_token, exercise_host): """Assembles litezip structure data into a single-page-html file. This also stores the intermediary results alongside the resulting assembled single-page-html. """ input_dir = Path(input_dir) output_dir = Path(output_dir) collection_assembled_xhtml = (output_dir / ASSEMBLED_FILENAME) if collection_assembled_xhtml.exists(): confirm_msg = ( "File '{}' already exists. Would you like to replace it?".format( collection_assembled_xhtml)) click.confirm(confirm_msg, abort=True, err=True) collection_assembled_xhtml.unlink() if not output_dir.exists(): output_dir.mkdir() collection_xml = input_dir / 'collection.xml' binder = Binder.from_collection_xml(collection_xml) # Write the collection.xml symlink to the output directory output_collection_xml = (output_dir / 'collection.xml') if output_collection_xml.exists(): output_collection_xml.unlink() output_collection_xml.symlink_to(relative_path(collection_xml, output_dir)) # Fetch exercises as part of producing the collection xhtml exercise_match_urls = ( ('#ost/api/ex/', 'https://{}/api/exercises?q=tag:{{itemCode}}'.format(exercise_host)), ('#exercise/', 'https://{}/api/exercises?q=nickname:{{itemCode}}'.format( exercise_host)), ) includes = [ exercise_callback_factory(exercise_match, exercise_url, token=exercise_token) for exercise_match, exercise_url in exercise_match_urls ] # Write the binder out as a single-page-html collection_xhtml = produce_collection_xhtml(binder, output_dir, includes) logger.debug('Wrote: {}'.format(str(collection_xhtml.resolve()))) # Write the symbolic links for modules to the output directory provide_supporting_files(input_dir, output_dir, binder) return 0
def main(argv=sys.argv): if len(argv) < 2: usage(argv) config_uri = argv[1] bootstrap(config_uri) settings = get_current_registry().settings connection_string = settings[CONNECTION_STRING] exercise_url_template = settings.get('embeddables.exercise.url_template', None) exercise_match = settings.get('embeddables.exercise.match', None) exercise_token = settings.get('embeddables.exercise.token', None) mathml_url = settings.get('mathmlcloud.url', None) includes = None if exercise_url_template and exercise_match: includes = [ exercise_callback_factory(exercise_match, exercise_url_template, exercise_token, mathml_url) ] # Code adapted from # http://initd.org/psycopg/docs/advanced.html#asynchronous-notifications with psycopg2.connect(connection_string) as conn: conn.set_isolation_level( psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) with conn.cursor() as cursor: cursor.execute('LISTEN {}'.format(CHANNEL)) logger.debug( 'Waiting for notifications on channel "{}"'.format(CHANNEL)) rlist = [conn] # wait until ready for reading wlist = [] # wait until ready for writing xlist = [] # wait for an "exceptional condition" timeout = 5 while True: if select.select(rlist, wlist, xlist, timeout) != ([], [], []): conn.poll() while conn.notifies: notify = conn.notifies.pop(0) logger.debug( 'Got NOTIFY: pid={} channel={} payload={}'.format( notify.pid, notify.channel, notify.payload)) post_publication(conn, includes)
def main(argv=sys.argv): if len(argv) < 2: usage(argv) config_uri = argv[1] bootstrap(config_uri) settings = get_current_registry().settings connection_string = settings[CONNECTION_STRING] exercise_url_template = settings.get('embeddables.exercise.url_template', None) exercise_match = settings.get('embeddables.exercise.match', None) exercise_token = settings.get('embeddables.exercise.token', None) mathml_url = settings.get('mathmlcloud.url', None) includes = None if exercise_url_template and exercise_match: includes = [exercise_callback_factory(exercise_match, exercise_url_template, exercise_token, mathml_url)] # Code adapted from # http://initd.org/psycopg/docs/advanced.html#asynchronous-notifications with psycopg2.connect(connection_string) as conn: conn.set_isolation_level( psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) with conn.cursor() as cursor: cursor.execute('LISTEN {}'.format(CHANNEL)) logger.debug('Waiting for notifications on channel "{}"' .format(CHANNEL)) rlist = [conn] # wait until ready for reading wlist = [] # wait until ready for writing xlist = [] # wait for an "exceptional condition" timeout = 5 while True: if select.select(rlist, wlist, xlist, timeout) != ([], [], []): conn.poll() while conn.notifies: notify = conn.notifies.pop(0) logger.debug('Got NOTIFY: pid={} channel={} payload={}' .format(notify.pid, notify.channel, notify.payload)) post_publication(conn, includes)
def main(argv=None): parser = argparse.ArgumentParser(description="Assemble complete book " "as single HTML file") parser.add_argument('epub_file_path', help='Path to the epub file containing the book') parser.add_argument("html_out", nargs="?", type=argparse.FileType('w'), help="assembled HTML file output (default stdout)", default=sys.stdout) parser.add_argument('-m', "--mathjax_version", const=DEFAULT_MATHJAX_VER, metavar="mathjax_version", nargs="?", help="Add script tag to use MathJax of given version") parser.add_argument('-n', "--no-network", action='store_true', help="Do not use network access " "- no exercise or math conversion") parser.add_argument('-x', "--exercise_host", const=DEFAULT_EXERCISES_HOST, metavar="exercise_host", nargs="?", help="Download included exercises from this host") parser.add_argument('-t', "--exercise_token", metavar="exercise_token", nargs="?", help="Token for including answers in exercises") parser.add_argument('-M', "--mathmlcloud_url", metavar="mathmlcloud_url", nargs="?", help="Convert TeX equations using " "this mathmlcloud API url", const=DEFAULT_MATHMLCLOUD_URL) parser.add_argument('-v', '--verbose', action='store_true', help='Send debugging info to stderr') parser.add_argument('-s', '--subset-chapters', dest='numchapters', type=int, const=2, nargs='?', metavar='num_chapters', help="Create subset of complete book " "(default 2 chapters plus extras)") args = parser.parse_args(argv) handler = logging.StreamHandler(sys.stderr) if args.verbose: logger.setLevel(logging.DEBUG) logger.addHandler(handler) mathjax_version = args.mathjax_version if mathjax_version: if not mathjax_version.endswith('latest'): mathjax_version += '-latest' exercise_host = args.exercise_host or DEFAULT_EXERCISES_HOST exercise_token = args.exercise_token mml_url = args.mathmlcloud_url or DEFAULT_MATHMLCLOUD_URL if not args.no_network: exercise_url = \ 'https://%s/api/exercises?q=tag:{itemCode}' % (exercise_host) exercise_match = '#ost/api/ex/' includes = [exercise_callback_factory(exercise_match, exercise_url, exercise_token, mml_url)] else: includes = None single_html(args.epub_file_path, args.html_out, mathjax_version, args.numchapters, includes)