def write_rst(self): document_path = normalize_document_path([self.output_dir] + ['images'], extension='.rst') print(document_path) d = RstCloth() d.title('Docker Images') d.newline() d.content('DockHub URL:') d.newline() d.codeblock('https://hub.docker.com/u/pangeo', language='html') d.newline() for image in self.images: d.h3(image) d.newline() conda_list = self.conda_list(image) metadata = {'URL': f'https://hub.docker.com/r/{image}'} metadata.update(self.docker_inspect(image)) id = image.split('/')[1] html = template.render(id=id, conda_list=conda_list, metadata=metadata) d.directive('raw', arg='html', content=html) d.newline() d.write(document_path)
def render_step_file(input_fn, output_fn, conf): input_fn_base = os.path.basename(input_fn) logger.debug('generating step file for {0}'.format(input_fn_base)) steps = Steps(input_fn) logger.debug('resolved step file input for {0}'.format(input_fn_base)) r = RstCloth() web_output = WebStepsOutput(steps, conf=conf) web_output.render() r.content(web_output.rst.data, indent=0, wrap=False) logger.debug('generated web output for {0}'.format(input_fn_base)) r.directive('only', 'latex') r.newline() print_output = PrintStepsOutput(steps, conf=conf) print_output.render() r.content(print_output.rst.data, indent=3, wrap=False) logger.debug('generated print output for {0}'.format(input_fn_base)) if output_fn is None: output_fn = os.path.splitext(input_fn)[0] + '.rst' r.write(output_fn) logger.debug('wrote step include at {0}'.format(output_fn))
def generate_hash_file(fn, conf): r = RstCloth() if os.path.exists(fn): with open(fn, 'r') as f: existing = f.read() else: existing = [] commit = conf.git.commit r.directive('|commit| replace', '``{0}``'.format(commit)) try: if r.data == existing[:-1]: logger.info('no new commit(s), not updating {0} ({1})'.format( fn, commit[:10])) return True except TypeError: logger.warning('problem generating {0}, continuing'.format(fn)) if os.path.exists(fn): os.utime(fn, None) else: with open(fn, 'a'): os.utime(fn, None) else: r.write(fn) logger.info('regenerated {0} with new commit hash: {1}'.format( fn, commit[:10]))
def render_dfn_list(toc_items): r = RstCloth() r.directive('class', 'toc') r.newline() for entry in toc_items: entry.render() idnt = 3 * entry.level if entry.text_only is True: if 'name' in entry: r.definition(entry.name, entry.description, indent=idnt) else: r.content(entry.description, indent=idnt) r.newline() else: if 'name' in entry: dfn_heading = r.role('doc', "{0} <{1}>".format(entry.name, entry.file)) else: dfn_heading = r.role('doc', entry.file) if 'description' in entry: description = entry.description else: description = '' r.definition(dfn_heading, description, indent=idnt) r.newline() return r
def render_dfn_list(toc_items): r = RstCloth() r.directive('class', 'toc') r.newline() for entry in toc_items: entry.render() idnt = 3 * entry.level if entry.text_only is True: if 'name' in entry: r.definition(entry.name, entry.description, indent=idnt) else: r.content(entry.description, indent=idnt) r.newline() else: if 'name' in entry: dfn_heading = r.role( 'doc', "{0} <{1}>".format(entry.name, entry.file)) else: dfn_heading = r.role('doc', entry.file) if 'description' in entry: description = entry.description else: description = '' r.definition(dfn_heading, description, indent=idnt) r.newline() return r
def generate_hash_file(fn, conf): r = RstCloth() if os.path.exists(fn): with open(fn, 'r') as f: existing = f.read() else: existing = [] commit = conf.git.commit r.directive('|commit| replace', '``{0}``'.format(commit)) try: if r.data == existing[:-1]: logger.debug('no new commit(s), not updating {0} ({1})'.format(fn, commit[:10])) return True except TypeError: logger.warning('problem generating {0}, continuing'.format(fn)) if os.path.exists(fn): os.utime(fn, None) else: with open(fn, 'a'): os.utime(fn, None) else: r.write(fn) logger.debug('regenerated {0} with new commit hash: {1}'.format(fn, commit[:10]))
def get_include_statement(include_file): r = RstCloth() r.newline() r.directive('include', include_file) r.newline() return '\n'.join(r.data)
def render_options(option, conf): r = RstCloth() if 'program' not in option.replacement: option.replacement['program'] = RstCloth.role('program', option.program) if option.has_field('command'): option.replacement['command'] = RstCloth.role('toolcommand', option.command) if option.directive in ['option']: if len(option.name) > 1 and option.name[0] in ('<', '-'): prefix = '' else: prefix = '--' directive_str = '{prefix}{name}' if option.has_field('args'): directive_str += ' {args}' if option.has_field('aliases'): directive_str += ', {0}'.format(option.aliases) if option.has_field('args'): directive_str += ' {args}' if option.has_field('args'): directive_str = directive_str.format(prefix=prefix, name=option.name, args=option.args) else: directive_str = directive_str.format(prefix=prefix, name=option.name) else: prefix = '' directive_str = option.name if 'role' not in option.replacement: option.replacement['role'] = ':{0}:`{1}{2}`'.format(option.directive, prefix, option.name) option.render() # jinja template render r.directive(option.directive, directive_str) r.newline() indent = 3 if option.has_field('type'): r.content('*Type*: {0}'.format(option.type), indent=indent) r.newline() if option.has_field('default'): r.content('*Default*: {0}'.format(option.default), indent=indent) r.newline() for field in ('pre', 'description', 'content', 'post'): if option.has_field(field) is False: continue else: r.content(getattr(option, field).split('\n'), indent=indent, wrap=False) r.newline() return r
def generate_release_untar(builder, release): r = RstCloth() r.directive('code-block', 'sh', block='header') r.newline(block='header') r.content('tar -zxvf mongodb-{0}-{1}.tgz'.format(builder, release), 3, wrap=False, block='cmd') return r
def generate_release_copy(builder, release): r = RstCloth() r.directive('code-block', 'sh', block='header') r.newline(block='header') r.content('mkdir -p mongodb', 3, wrap=False, block='cmd') r.content('cp -R -n mongodb-{0}-{1}/ mongodb'.format(builder, release), 3, wrap=False, block='cmd') return r
def render_apiargs(apiargs, conf): r = RstCloth() r.directive('only', '(html or singlehtml or dirhtml)') render_apiarg_table(r, apiargs) r.directive('only', '(texinfo or latex or epub)') render_apiarg_fields(r, apiargs) return r
def render_glossary(terms): r = RstCloth() r.directive(name="glossary", fields=[("sorted", "")]) r.newline() for term in terms.ordered_content(): r.definition(term.term, term.definition, wrap=False, indent=3) return r
def pytest_sessionfinish(session): """ Write out results for each doc collector. """ if session.config.getoption("rst_dir"): if session.config.getoption("rst_write_index"): index = RstCloth() index.title(session.config.getoption("rst_title", "Test Results")) index.newline() index.content(session.config.getoption("rst_desc", "")) index.newline() index.directive(name="toctree", fields=[("includehidden", ""), ("glob", "")]) index.newline() index.content(["*"], 3) index.newline(2) index.write( os.path.join(session.config.getoption("rst_dir"), "index.rst")) results = [] for doc_collector in getattr(session, "doc_collectors", []): results.extend(doc_collector.get_all_results()) doc_collector.write( os.path.join(session.config.getoption("rst_dir"), doc_collector.node_name + ".rst")) # Writes the Overview.rst file. overview_path = os.path.join(session.config.getoption("rst_dir"), "overview.rst") if os.path.exists(overview_path): # Append to existing overview. with open(overview_path, "r") as existing_overview: overview_data = [ x.rstrip() for x in existing_overview.readlines() ] result_rst = RstCloth() result_rst._data = overview_data else: result_rst = RstCloth() result_rst.title("Test Result Table(s)") result_rst.newline() result_rst._add( tabulate( [(x["name"], x["setup"], x.get( "call", "NOTRUN"), x.get("teardown", "NOTRUN")) for x in results], headers=RESULTS_HEADER, tablefmt="rst", )) result_rst.newline(2) result_rst.write( os.path.join(session.config.getoption("rst_dir"), "overview.rst"))
def render_options(option, conf): r = RstCloth() if "program" not in option.replacement: option.replacement["program"] = ":program:`{0}`".format(option.program) if option.directive == "option": if option.name.startswith("<"): prefix = "" else: prefix = "--" directive_str = "{prefix}{name}" if option.has_field("args"): directive_str += " {args}" if option.has_field("aliases"): directive_str += ", {0}".format(option.aliases) if option.has_field("args"): directive_str += " {args}" if option.has_field("args"): directive_str = directive_str.format(prefix=prefix, name=option.name, args=option.args) else: directive_str = directive_str.format(prefix=prefix, name=option.name) else: prefix = "" directive_str = option.name if "role" not in option.replacement: option.replacement["role"] = ":{0}:`{1}{2}`".format(option.directive, prefix, option.name) option.render() # jinja template render r.directive(option.directive, directive_str) r.newline() indent = 3 if option.has_field("type"): r.content("*Type*: {0}".format(option.type), indent=indent) r.newline() if option.has_field("default"): r.content("*Default*: {0}".format(option.default), indent=indent) r.newline() for field in ("pre", "description", "content", "post"): if option.has_field(field) is False: continue else: r.content(getattr(option, field).split("\n"), indent=indent, wrap=False) r.newline() return r
def render_extracts(extract): r = RstCloth() extract.render() if 'style' in extract: r.directive('rst-class', extract.style) r.newline() render_action(extract, indent=0, level=extract.level, r=r) return r
def render_toctree(toc_items, is_ref=False): r = RstCloth() r.directive('toctree', fields=[('titlesonly', ''), ('hidden', '')]) r.newline() for entry in toc_items: if is_ref is False and 'name' in entry: r.content('{0} <{1}>'.format(entry.name, entry.file), indent=3, wrap=False) else: r.content(entry.file, indent=3, wrap=False) return r
def render_apiargs(apiargs): r = RstCloth() r.directive('only', '(html or singlehtml or dirhtml)') r.newline() render_apiarg_table(r, apiargs) r.newline() r.directive('only', '(texinfo or latex or epub)') r.newline() render_apiarg_fields(r, apiargs) return r
def render_steps(steps, conf): r = RstCloth() header_html = ('<div class="sequence-block">' '<div class="bullet-block">' '<div class="sequence-step">' '{0}' '</div>' '</div>') for idx, step in enumerate(steps.steps): step.render() # run replacements if 'number' not in step: step.number = idx r.directive('only', 'html or dirhtml or singlehtml') r.newline() r.directive(name='raw', arg='html', content=header_html.format(step.number), indent=3) r.newline() if 'heading' in step: r.heading(text=step.heading, char=character_levels[step.level], indent=3) r.newline() render_step_content(step, 3, r) r.directive(name='raw', arg='html', content="</div>", indent=3) r.newline() r.directive('only', 'latex or epub') r.newline() if 'heading' in step: r.heading(text="Step {0}: {1}".format(step.number, step.heading), char=character_levels[step.level], indent=3) r.newline() else: r.heading(text="Step {0}".format(step.number), char=character_levels[step.level], indent=3) r.newline() render_step_content(step, 3, r) return r
def render_extracts(extract): r = RstCloth() extract.render() indent = 0 if 'only' in extract: r.directive('only', extract.only, indent=indent) r.newline() indent += 3 if 'style' in extract: r.directive('rst-class', extract.style, indent=indent) r.newline() render_action(extract, indent=indent, level=extract.level, r=r) return r
def render_steps(steps, conf): r = RstCloth() header_html = ('<div class="sequence-block">' '<div class="bullet-block">' '<div class="sequence-step">' '{0}' '</div>' '</div>') for idx, step in enumerate(steps.ordered_content()): step.render() # run replacements if 'number' not in step: step.number = idx r.directive('only', 'html or dirhtml or singlehtml') r.newline() r.directive(name='raw', arg='html', content=header_html.format(step.number), indent=3) r.newline() if 'heading' in step: r.heading(text=step.heading, char=character_levels[step.level], indent=3) r.newline() render_step_content(step, 3, r) r.directive(name='raw', arg='html', content="</div>", indent=3) r.newline() r.directive('only', 'not(html or dirhtml or singlehtml)') r.newline() if 'heading' in step: r.heading(text="Step {0}: {1}".format(step.number, step.heading), char=character_levels[step.level], indent=3) r.newline() else: r.heading(text="Step {0}".format(step.number), char=character_levels[step.level], indent=3) r.newline() render_step_content(step, 3, r) return r
def render_toctree(toc_items): r = RstCloth() r.directive('class', 'hidden') r.newline() r.directive('toctree', fields=[('titlesonly', '')], indent=3) r.newline() for entry in toc_items: if 'name' in entry: r.content('{0} <{1}>'.format(entry.name, entry.file), indent=6, wrap=False) else: r.content(entry.file, indent=6, wrap=False) return r
def render_apiargs(apiargs): for content in apiargs.ordered_content(): setup_replacements(content) content.render() # run_replacements r = RstCloth() r.directive('only', '(html or singlehtml or dirhtml)') r.newline() render_apiarg_table(r, apiargs) r.newline() r.directive('only', '(texinfo or latex or epub)') r.newline() render_apiarg_fields(r, apiargs) return r
def generate_output(builder, platform, version, release): """ This is the legacy version of the function used by the makefile and CLI infrastructure""" r = RstCloth() r.directive('code-block', 'sh', block='header') r.newline(block='header') if release == 'core': r.content('curl -O http://downloads.mongodb.org/{0}/mongodb-{1}-{2}.tgz'.format(platform, builder, version), 3, wrap=False, block='cmd') else: r.content('curl -O http://downloads.10gen.com/linux/mongodb-{0}-subscription-{1}-{2}.tgz'.format(builder, release, version), 3, wrap=False, block='cmd') r.content('tar -zxvf mongodb-{0}-subscription-{1}-{2}.tgz'.format(builder, release, version), 3, wrap=False, block='cmd') r.content('cp -R -n mongodb-{0}-subscription-{1}-{2}/ mongodb'.format(builder, release, version), 3, wrap=False, block='cmd') r.newline(block='footer') return r
def render_apiargs(apiargs): for content in apiargs.ordered_content(): setup_replacements(content) content.render() # run_replacements r = RstCloth() r.directive('only', '(html or singlehtml or dirhtml)') r.newline() render_apiarg_table(r, apiargs) r.newline() r.directive('only', 'not(html or singlehtml or dirhtml)') r.newline() render_apiarg_fields(r, apiargs) return r
def generate_release_output(builder, platform, architecture, release): """ This is the contemporary version of the function used by the generate.py script""" r = RstCloth() r.directive('code-block', 'sh', block='header') r.newline(block='header') if architecture == 'core': r.content('curl -O http://downloads.mongodb.org/{0}/mongodb-{1}-{2}.tgz'.format(platform, builder, release), 3, wrap=False, block='cmd') else: r.content('curl -O http://downloads.10gen.com/linux/mongodb-{0}-subscription-{1}-{2}.tgz'.format(builder, architecture, release), 3, wrap=False, block='cmd') r.content('tar -zxvf mongodb-{0}-subscription-{1}-{2}.tgz'.format(builder, architecture, release), 3, wrap=False, block='cmd') r.content('cp -R -n mongodb-{0}-subscription-{1}-{2}/ mongodb'.format(builder, architecture, release), 3, wrap=False, block='cmd') r.newline(block='footer') return r
def generate_params(params, fn, conf): r = RstCloth() basename = os.path.basename(fn) params.sort(key=lambda p: p['position']) # Begin by generating the table for web output r.directive('only', '(html or singlehtml or dirhtml)', block='htm') r.newline(block='htm') # { filename: { $name: <param> } } ext_params = {} processed_params = [] for param in params: if 'file' in param: pos = param['position'] if param['file'] not in ext_params: fn, ext = populate_external_param(param['file'], basename, conf.paths.projectroot, conf.paths.source) ext_params[fn] = ext param = ext_params[conf.paths.source + param['file']][param['name']] param['position'] = pos processed_params.append(param) r.content(generate_param_table(processed_params), indent=3, block='html') r.newline(block='htm') # Then generate old-style param fields for non-web output r.directive('only', '(texinfo or latex or epub)', block='tex') r.newline(block='tex') for param in processed_params: key, val = generate_param_fields(param) r.field(name=key, value=val, indent=3, wrap=False, block='tex') r.newline(block='tex') return r
def generate_release_output(builder, platform, architecture, release): """ This is the contemporary version of the function used by the generate.py script""" r = RstCloth() r.directive('code-block', 'sh', block='header') r.newline(block='header') if architecture == 'core': r.content( 'curl -O http://downloads.mongodb.org/{0}/mongodb-{1}-{2}.tgz'. format(platform, builder, release), 3, wrap=False, block='cmd') else: r.content( 'curl -O http://downloads.10gen.com/linux/mongodb-{0}-subscription-{1}-{2}.tgz' .format(builder, architecture, release), 3, wrap=False, block='cmd') r.content('tar -zxvf mongodb-{0}-subscription-{1}-{2}.tgz'.format( builder, architecture, release), 3, wrap=False, block='cmd') r.content('cp -R -n mongodb-{0}-subscription-{1}-{2}/ mongodb'.format( builder, architecture, release), 3, wrap=False, block='cmd') r.newline(block='footer') return r
def generate_output(builder, platform, version, release): """ This is the legacy version of the function used by the makefile and CLI infrastructure""" r = RstCloth() r.directive('code-block', 'sh', block='header') r.newline(block='header') if release == 'core': r.content( 'curl -O http://downloads.mongodb.org/{0}/mongodb-{1}-{2}.tgz'. format(platform, builder, version), 3, wrap=False, block='cmd') else: r.content( 'curl -O http://downloads.10gen.com/linux/mongodb-{0}-subscription-{1}-{2}.tgz' .format(builder, release, version), 3, wrap=False, block='cmd') r.content('tar -zxvf mongodb-{0}-subscription-{1}-{2}.tgz'.format( builder, release, version), 3, wrap=False, block='cmd') r.content('cp -R -n mongodb-{0}-subscription-{1}-{2}/ mongodb'.format( builder, release, version), 3, wrap=False, block='cmd') r.newline(block='footer') return r
class CustomTocTree(object): def __init__(self, filename, conf, sort=False): if "ref-toc" in filename: self._is_ref = True sort = True else: self._is_ref = False self.spec = self._process_spec(filename, sort) self.conf = conf self.table = None self.contents = None self.dfn = None self.final = False def build_table(self): self.table = TableData() self.table.add_header(['Name', 'Description']) def build_dfn(self): self.dfn = RstCloth() self.dfn.directive('class', 'toc') self.dfn.newline() def build_contents(self): self.contents = RstCloth() self.contents.directive('class', 'hidden') self.contents.newline() self.contents.directive('toctree', fields=[('titlesonly', '')], indent=3) self.contents.newline() def _process_spec(self, spec, sort=False): o = [] with open(spec, 'r') as f: data = yaml.safe_load_all(f) for datum in data: if 'description' not in datum or datum['description'] is None: datum['description'] = '' if sort is False: pass elif 'name' not in datum: sort = False o.append(datum) if sort is True: o.sort(key=lambda o: o['name']) return o def finalize(self): if not self.final: for ref in self.spec: if giza.content.helper.edition_check(ref, self.conf) is False: continue if self.table is not None: if 'text' in ref: if ref['name'] is None: self.table.add_row(['', ref['text']]) else: self.table.add_row([ref['name'], ref['text']]) if 'name' in ref: self.table.add_row([ref['name'], ref['description']]) else: self.table = None if self.contents is not None and 'file' in ref: if 'name' in ref and self._is_ref is False: self.contents.content("{0} <{1}>".format( ref['name'], ref['file']), 6, wrap=False, block='toc') else: self.contents.content(ref['file'], 6, wrap=False, block='toc') if self.dfn is not None: if 'name' in ref: text = ref['name'] else: text = None if 'level' in ref: idnt = 3 * ref['level'] else: idnt = 3 if 'class' in ref: self.dfn.directive(name='class', arg=ref['class'], indent=idnt) idnt += 3 if 'text' in ref: if ref['name'] is None: self.dfn.content(ref['text'], idnt) else: self.dfn.definition(ref['name'], ref['text'], indent=idnt, bold=False, wrap=False) else: link = self.dfn.role('doc', ref['file'], text) self.dfn.definition(link, ref['description'], indent=idnt, bold=False, wrap=False) self.dfn.newline()
def full_example(collection, examples): """ :pram collection: An object with collection information and description. :pram examples: An object with examples, procedures and results. See :mod:`giza.content.examples.modules` for full documentation of the example data format. :returns: A populated ``RstCloth()`` object with the content of one example. """ r = RstCloth() if collection is not None: collection.render() if collection.options.show_title is True: if len(examples) == 1: ex_str = 'Example' else: ex_str = 'Examples' r.h2(ex_str) r.newline() if 'pre' in collection: r.content(collection.pre) r.newline() if 'content' in collection and collection.options.show_collection is True: r.content(collection.content) r.newline() if 'documents' in collection: r.codeblock(content=collection.documents, language='javascript') r.newline() if 'post' in collection: r.content(collection.post) r.newline() if 'final' in collection: r.content(collection.final) r.newline() for idx, example in enumerate(examples): example.render() if idx != 0: r.newline(2) if len(examples) > 1 and 'title' in example: getattr(r, 'h' + str(example.title.level))(example.title.text) r.newline() if 'pre' in example: r.content(example.pre) r.newline() lang = set() for op in example.operation: if 'pre' in op: r.content(op.pre) r.newline() # if content in op (e.g. for literalincludes) then # no need for code or language if 'content' in op: r.content(op.content) r.newline() elif 'literalinclude' in op: # Temporary and klugey include_options = [] if 'language' in op: include_options.append(('language', op.language)) r.directive('literalinclude', op.literalinclude, include_options) r.newline() elif 'code' in op: lang.add(op.language) r.codeblock(content=op.code, language=op.language) r.newline() if 'post' in op: r.content(op.post) r.newline() if 'post' in example: r.content(example.post) r.newline() if 'results' in example and example.results is not None: num_langs = len(lang) lang = list(lang)[0] if num_langs > 1: msg = 'specified more than one language for examples {0}, using {1} for results' logger.warning(msg.foramt(example.ref, lang)) r.codeblock(content=example.results, language=lang) if 'final' in example: r.newline() r.content(example.final) return r
def build_page(data, conf): if 'includes' not in conf.system.files.data: return else: iconf = conf.system.files.data.includes r = RstCloth() r.title(iconf['title']) r.newline() r.directive('default-domain', iconf['domain']) r.newline() try: r.content(iconf['introduction']) r.newline() except KeyError: logger.debug('include meta file lacks an introduction.') r.directive(name='contents', arg='Included Files', fields=[ ('backlinks', 'none'), ('class', 'long-toc'), ('depth', 1), ('local', ''), ]) r.newline() data = data.items() data.sort() for _, record in data: page_name = r.pre(record['name']) r.heading(text=page_name, char='-', indent=0) r.newline() r.heading('Meta', char='~', indent=0) r.newline() if record['num_clients'] == 0: r.content('{0} is not included in any files.'.format(page_name)) r.newline() add_content(r, record) elif record['num_clients'] == 1: if record['yaml_only']: r.content('{0} is only included in yaml files.'.format(page_name)) r.newline() else: link = r.role('doc', record['clients'][0]) r.content('{0} is only included in {1}.'.format(page_name, link)) r.newline() add_meta(r, page_name, record) add_content(r, record) else: r.content('{0} is included in **{1}** files.'.format(page_name, record['num_clients']), wrap=False) r.newline() add_meta(r, page_name, record) if record['yaml_only'] is False: clients = [ p for p in record['clients'] if not p.startswith('/includes') ] if len(clients) == 1: client_link = r.role('doc', clients[0]) inc_str = '{0} is the only file that includes {1} that is not also an include.' r.content(inc_str.format(client_link, page_name)) r.newline() else: r.heading('Client Pages', char='~', indent=0) r.newline() for pg in clients: client_link = r.role('doc', pg) r.li(client_link, wrap=False) r.newline() add_include_example(r, page_name, record['path']) add_content(r, record) return r
class OptionRendered(object): def __init__(self, option): if not isinstance(option, Option): raise TypeError else: self.option = option self.rst = RstCloth() def resolve_option_name(self): if self.option.directive == 'option': if self.option.name.startswith('<'): prefix = '' else: prefix = '--' if hasattr(self.option, 'aliases'): if hasattr(self.option, 'arguments'): return '{0}{1} {2}, {3}'.format(prefix, self.option.name, self.option.arguments, '{0}, '.format(self.option.arguments).join(self.option.aliases)) else: return '{0}{1}, {2}'.format(prefix, self.option.name, ', '.join(self.option.aliases)) else: if hasattr(self.option, 'arguments'): return '{0}{1} {2}'.format(prefix, self.option.name, self.option.arguments) else: return '{0}{1}'.format(prefix, self.option.name) else: return self.option.name def render(self, path): self.option.replace() self.rst.directive(self.option.directive, self.resolve_option_name()) self.rst.newline() if self.option.type is not None: self.rst.content('*Type*: {0}'.format(self.option.type), indent=3) self.rst.newline() if self.option.default is not None: self.rst.content('*Default*: {0}'.format(self.option.default), indent=3) self.rst.newline() if self.option.pre is not None: self.rst.content(self.option.pre.split('\n'), indent=3, wrap=False) self.rst.newline() if self.option.description is not None: self.rst.content(self.option.description.split('\n'), indent=3, wrap=False) self.rst.newline() if self.option.post is not None: self.rst.content(self.option.post.split('\n'), indent=3, wrap=False) self.rst.newline() output_file = self.option.resolve_output_path(path) self.rst.write(output_file) logger.debug('wrote option to file {0}'.format(output_file))
class CustomTocTree(object): def __init__(self, filename, conf, sort=False): if "ref-toc" in filename: self._is_ref = True sort = True else: self._is_ref = False self.spec = self._process_spec(filename, sort) self.conf = conf self.table = None self.contents = None self.dfn = None self.final = False def build_table(self): self.table = TableData() self.table.add_header(['Name', 'Description']) def build_dfn(self): self.dfn = RstCloth() self.dfn.directive('class', 'toc') self.dfn.newline() def build_contents(self): self.contents = RstCloth() self.contents.directive('class', 'hidden') self.contents.newline() self.contents.directive('toctree', fields=[('titlesonly', '')], indent=3) self.contents.newline() def _process_spec(self, spec, sort=False): o = [] with open(spec, 'r') as f: data = yaml.safe_load_all(f) for datum in data: if 'description' not in datum or datum['description'] is None: datum['description'] = '' if sort is False: pass elif 'name' not in datum: sort = False o.append(datum) if sort is True: o.sort(key=lambda o: o['name']) return o def finalize(self): if not self.final: for ref in self.spec: if giza.content.helper.edition_check(ref, self.conf) is False: continue if self.table is not None: if 'text' in ref: if ref['name'] is None: self.table.add_row( [ '', ref['text'] ] ) else: self.table.add_row( [ ref['name'], ref['text'] ]) if 'name' in ref: self.table.add_row([ ref['name'], ref['description'] ]) else: self.table = None if self.contents is not None and 'file' in ref: if 'name' in ref and self._is_ref is False: self.contents.content("{0} <{1}>".format(ref['name'], ref['file']), 6, wrap=False, block='toc') else: self.contents.content(ref['file'], 6, wrap=False, block='toc') if self.dfn is not None: if 'name' in ref: text = ref['name'] else: text = None if 'level' in ref: idnt = 3 * ref['level'] else: idnt = 3 if 'class' in ref: self.dfn.directive(name='class', arg=ref['class'], indent=idnt) idnt += 3 if 'text' in ref: if ref['name'] is None: self.dfn.content(ref['text'], idnt) else: self.dfn.definition(ref['name'], ref['text'], indent=idnt, bold=False, wrap=False) else: link = self.dfn.role('doc', ref['file'], text) self.dfn.definition(link, ref['description'], indent=idnt, bold=False, wrap=False) self.dfn.newline()
class TestRstCloth(TestCase): @classmethod def setUp(self): self.r = RstCloth() def test_adding_without_blocks(self): self.r._add('foo') self.assertEqual(self.r.data[0], 'foo') def test_newline(self): self.r.newline() self.assertEqual(len(self.r.data), 1) def test_multi_newline(self): self.r.newline(count=4) self.assertEqual(len(self.r.data[0]), 4 - 1) def test_directive_simple(self): self.r.directive('test', block='d0') self.assertEqual(self.r.data[0], '.. test::') def test_directive_arg_named(self): self.r.directive('test', arg='what', block='d3') self.assertEqual(self.r.data[0], '.. test:: what') def test_directive_arg_positional(self): self.r.directive('test', 'what', block='d1') self.assertEqual(self.r.data[0], '.. test:: what') def test_directive_fields(self): self.r.directive('test', fields=[('a', 'b')], block='d2') self.assertEqual(self.r.data[0], '.. test::') self.assertEqual(self.r.data[1], ' :a: b') def test_directive_fields_with_arg(self): self.r.directive('test', arg='what', fields=[('a', 'b')], block='d4') self.assertEqual(self.r.data[0], '.. test:: what') self.assertEqual(self.r.data[1], ' :a: b') def test_directive_fields_multiple(self): self.r.directive('test', fields=[('a', 'b'), ('c', 'd')], block='d5') self.assertEqual(self.r.data[0], '.. test::') self.assertEqual(self.r.data[1], ' :a: b') self.assertEqual(self.r.data[2], ' :c: d') def test_directive_fields_multiple_arg(self): self.r.directive('test', arg='new', fields=[('a', 'b'), ('c', 'd')], block='d6') self.assertEqual(self.r.data[0], '.. test:: new') self.assertEqual(self.r.data[1], ' :a: b') self.assertEqual(self.r.data[2], ' :c: d') def test_directive_content(self): self.r.directive('test', content='string', block='d7') self.assertEqual(self.r.data[0], '.. test::') self.assertEqual(self.r.data[1], '') self.assertEqual(self.r.data[2], ' string') def test_directive_with_multiline_content(self): self.r.directive('test', content=['string', 'second'], block='d8') self.assertEqual(self.r.data[0], '.. test::') self.assertEqual(self.r.data[1], '') self.assertEqual(self.r.data[2], ' string') self.assertEqual(self.r.data[3], ' second') def test_directive_simple_indent(self): self.r.directive('test', indent=3, block='di0') self.assertEqual(self.r.data, [' .. test::']) def test_directive_arg_named_indent(self): self.r.directive('test', arg='what', indent=3, block='di3') self.assertEqual(self.r.data, [' .. test:: what']) def test_directive_arg_positional_indent(self): self.r.directive('test', 'what', indent=3, block='di1') self.assertEqual(self.r.data, [' .. test:: what']) def test_directive_fields_indent(self): self.r.directive('test', fields=[('a', 'b')], indent=3, block='di2') self.assertEqual(self.r.data, [' .. test::', ' :a: b']) def test_directive_fields_with_arg_indent(self): self.r.directive('test', arg='what', fields=[('a', 'b')], indent=3, block='di4') self.assertEqual(self.r.data, [' .. test:: what', ' :a: b']) def test_directive_fields_multiple_indent(self): self.r.directive('test', indent=3, fields=[('a', 'b'), ('c', 'd')], block='di5') self.assertEqual(self.r.data, [' .. test::', ' :a: b', ' :c: d']) def test_directive_fields_multiple_arg_indent(self): self.r.directive('test', arg='new', indent=3, fields=[('a', 'b'), ('c', 'd')], block='di6') self.assertEqual(self.r.data, [' .. test:: new', ' :a: b', ' :c: d']) def test_directive_content_indent(self): self.r.directive('test', content='string', indent=3, block='di7') self.assertEqual(self.r.data, [' .. test::', ' ', ' string']) def test_directive_with_multiline_content_indent(self): self.r.directive('test', indent=3, content=['string', 'second'], block='di8') self.assertEqual(self.r.data, [' .. test::', ' ', ' string', ' second']) def test_single_role_no_text(self): ret = self.r.role('test', 'value') self.assertEqual(ret, ':test:`value`') def test_multi_role_no_text(self): ret = self.r.role(['test', 'role'], 'value') self.assertEqual(ret, ':test:role:`value`') def test_single_role_text(self): ret = self.r.role('test', 'value', 'link') self.assertEqual(ret, ':test:`link <value>`') def test_multi_role_text(self): ret = self.r.role(['test', 'role'], 'value', 'link') self.assertEqual(ret, ':test:role:`link <value>`') def test_single_role_no_text_args(self): ret = self.r.role(name='test', value='value') self.assertEqual(ret, ':test:`value`') def test_multi_role_no_text_args(self): ret = self.r.role(name=['test', 'role'], value='value') self.assertEqual(ret, ':test:role:`value`') def test_single_role_text_args(self): ret = self.r.role(name='test', value='value', text='link') self.assertEqual(ret, ':test:`link <value>`') def test_multi_role_text_args(self): ret = self.r.role(name=['test', 'role'], value='value', text='link') self.assertEqual(ret, ':test:role:`link <value>`') def test_bold(self): ret = self.r.bold('text') self.assertEqual(ret, '**text**') def test_emph(self): ret = self.r.emph('text') self.assertEqual(ret, '*text*') def test_pre(self): ret = self.r.pre('text') self.assertEqual(ret, '``text``') def test_inline_link(self): ret = self.r.inline_link('text', 'link') self.assertEqual(ret, '`text <link>`_') def test_footnote_ref(self): ret = self.r.footnote_ref('name') self.assertEqual(ret, '[#name]') def test_codeblock_simple(self): self.r.codeblock('ls -lha', block='cb0') self.assertEqual(self.r.data, ['::', ' ls -lha']) def test_codeblock_with_language(self): self.r.codeblock('ls -lha', language='shell',block='cb1') self.assertEqual(self.r.data, ['.. code-block:: shell', '', ' ls -lha']) def test_footnote(self): self.r.footnote('footsnotes', 'text of the note', block='fn0') self.assertEqual(self.r.data[0], '.. [#footsnotes] text of the note') def test_footnote_with_indent(self): self.r.footnote('footsnotes', 'text of the note', block='fn1', indent=3) self.assertEqual(self.r.data[0], ' .. [#footsnotes] text of the note') def test_footnote_with_wrap(self): self.r.footnote('footsnotes', 'the ' * 40, block='fn2', wrap=True) self.assertEqual(self.r.data[0], '.. [#footsnotes]' + ' the' * 14 + '\n ' + ' the' * 17 + '\n ' + ' the' * 9) def test_definition(self): self.r.definition('defitem', 'this is def text', block='dfn0') self.assertEqual(self.r.data, ['defitem', ' this is def text']) def test_definition_with_indent(self): self.r.definition('defitem', 'this is def text', indent=3, block='dfn1') self.assertEqual(self.r.data, [' defitem', ' this is def text']) def test_title_default(self): self.r.title('test text', block='hd0') self.assertEqual(self.r.data, ['=========', 'test text', '=========']) def test_title_alt(self): self.r.title('test text', char='-', block='hd1') self.assertEqual(self.r.data, ['---------', 'test text', '---------']) def test_heading_one(self): self.r.heading('test heading', char='-', indent=0, block='hd2') self.assertEqual(self.r.data, ['test heading', '------------']) def test_heading_two(self): self.r.heading('test heading', char='^', indent=0, block='hd3') self.assertEqual(self.r.data, ['test heading', '^^^^^^^^^^^^']) def test_h1(self): self.r.h1('test', block='hd4') self.assertEqual(self.r.data, ['test', '====']) def test_h2(self): self.r.h2('test', block='hd5') self.assertEqual(self.r.data, ['test', '----']) def test_h3(self): self.r.h3('test', block='hd6') self.assertEqual(self.r.data, ['test', '~~~~']) def test_h4(self): self.r.h4('test', block='hd7') self.assertEqual(self.r.data, ['test', '++++']) def test_h5(self): self.r.h5('test', block='hd8') self.assertEqual(self.r.data, ['test', '^^^^']) def test_h6(self): self.r.h6('test', block='hd9') self.assertEqual(self.r.data, ['test', ';;;;']) def test_replacement(self): self.r.replacement('foo', 'replace-with-bar', block='sub0') self.assertEqual(self.r.data, ['.. |foo| replace:: replace-with-bar']) def test_replacement_with_indent(self): self.r.replacement('foo', 'replace-with-bar', indent=3, block='sub1') self.assertEqual(self.r.data, [' .. |foo| replace:: replace-with-bar']) def test_li_simple(self): self.r.li('foo', block='li0') self.assertEqual(self.r.data, ['- foo']) def test_li_simple_indent(self): self.r.li('foo', indent=3, block='li1') self.assertEqual(self.r.data, [' - foo']) def test_li_simple_alt(self): self.r.li('foo', bullet='*', block='li2') self.assertEqual(self.r.data, ['* foo']) def test_li_simple_alt_indent(self): self.r.li('foo', bullet='*', indent=3, block='li3') self.assertEqual(self.r.data, [' * foo']) def test_li_complex(self): self.r.li(['foo', 'bar'], block='li0') self.assertEqual(self.r.data, ['- foo bar']) def test_li_complex_indent(self): self.r.li(['foo', 'bar'], indent=3, block='li1') self.assertEqual(self.r.data, [' - foo bar']) def test_li_complex_alt(self): self.r.li(['foo', 'bar'], bullet='*', block='li2') self.assertEqual(self.r.data, ['* foo bar']) def test_li_complex_alt_indent(self): self.r.li(['foo', 'bar'], bullet='*', indent=3, block='li3') self.assertEqual(self.r.data, [' * foo bar']) def test_field_simple(self): self.r.field('fname', 'fvalue', block='fld0') self.assertEqual(self.r.data, [':fname: fvalue']) def test_field_long_simple(self): self.r.field('fname is fname', 'fvalue', block='fld1') self.assertEqual(self.r.data, [':fname is fname: fvalue']) def test_field_simple_long(self): self.r.field('fname', 'v' * 54, block='fld2') self.assertEqual(self.r.data, [':fname: ' + 'v' * 54]) def test_field_simple_long_long(self): self.r.field('fname', 'v' * 55, block='fld3') self.assertEqual(self.r.data, [':fname:', '', ' ' + 'v' * 55]) def test_field_indent_simple(self): self.r.field('fname', 'fvalue', indent=3, block='fld4') self.assertEqual(self.r.data, [' :fname: fvalue']) def test_field_indent_long_simple(self): self.r.field('fname is fname', 'fvalue', indent=3, block='fld5') self.assertEqual(self.r.data, [' :fname is fname: fvalue']) def test_field_indent_simple_long(self): self.r.field('fname', 'v' * 54, indent=3, block='fld6') self.assertEqual(self.r.data, [' :fname: ' + 'v' * 54]) def test_field_indent_simple_long_long(self): self.r.field('fname', 'v' * 55, indent=3, block='fld7') self.assertEqual(self.r.data, [' :fname:', ' ', ' ' + 'v' * 55]) def test_field_wrap_simple(self): self.r.field('fname', 'the ' * 100, block='fld8') self.assertEqual(self.r.data, [':fname:', '', ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 10]) def test_field_wrap_indent_simple(self): self.r.field('fname', 'the ' * 100, indent=3, block='fld8') self.assertEqual(self.r.data, [' :fname:', ' ', ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 10]) def test_content_string(self): self.r.content('this is sparta', block='ct0') self.assertEqual(self.r.data, ['this is sparta']) def test_content_list(self): self.r.content(['this is sparta', 'this is spinal tap'], block='ct1') self.assertEqual(self.r.data, ['this is sparta', 'this is spinal tap']) def test_content_indent_string(self): self.r.content('this is sparta', indent=3, block='ct2') self.assertEqual(self.r.data, [' this is sparta']) def test_content_indent_list(self): self.r.content(['this is sparta', 'this is spinal tap'], indent=3, block='ct3') self.assertEqual(self.r.data, [' this is sparta', ' this is spinal tap']) def test_content_long(self): self.r.content('the ' * 100, block='ct4') self.assertEqual(self.r.data, [ 'the' + ' the' * 17, 'the ' * 17 + 'the', 'the ' * 17 + 'the', 'the ' * 17 + 'the', 'the ' * 17 + 'the', 'the ' * 9 + 'the' ]) def test_ontent_indent_long(self): self.r.content('the ' * 100, indent=3 ,block='ct5') self.assertEqual(self.r.data, [ ' the' + ' the' * 17, " " + 'the ' * 17 + 'the', ' ' + 'the ' * 17 + 'the', ' ' + 'the ' * 17 + 'the', ' ' + 'the ' * 17 + 'the', ' ' + 'the ' * 9 + 'the' ]) def test_ontent_indent_long_nowrap(self): self.r.content('the ' * 100, wrap=False, indent=3 ,block='ct5') self.assertEqual(self.r.data, [ ' ' + 'the ' * 99 + 'the']) def test_ref_target_named(self): self.r.ref_target(name="foo-are-magic-ref0", block='ref0') self.assertEqual(self.r.data, ['.. _foo-are-magic-ref0:']) def test_ref_target_unnamed(self): self.r.ref_target("foo-are-magic-ref1", block='ref1') self.assertEqual(self.r.data, ['.. _foo-are-magic-ref1:']) def test_ref_target_named_with_indent(self): self.r.ref_target(name="foo-are-magic-ref2", indent=3, block='ref2') self.assertEqual(self.r.data, [' .. _foo-are-magic-ref2:']) def test_ref_target_unnamed_wo_indent(self): self.r.ref_target("foo-are-magic-ref3", 3, block='ref3') self.assertEqual(self.r.data, [' .. _foo-are-magic-ref3:'])
def generate_image_pages(image, conf): r = RstCloth() dir = image.dir name = image.name alt = image.alt output = image.outputs image = os.path.sep.join([dir, name]) for img_output in output: width = str(img_output.width) + 'px' build_type = img_output.build_type r.newline() if 'tag' in img_output: tag = ''.join(['-', img_output.tag, '.', build_type]) else: tag = '.' + build_type options = [('alt', alt), ('align', 'center'), ('figwidth', width)] if 'scale' in img_output: options.append(('scale', img_output.scale)) if 'target' in img_output: options.append(('target', (img_output.target))) if img_output.type == 'target': continue elif img_output.type == 'print': r.directive('only', 'latex and not offset', wrap=False) r.newline() r.directive(name='figure', arg='/images/{0}{1}'.format(name, tag), fields=options, indent=3) elif img_output.type == 'offset': tex_figure = [ r'\begin{figure}[h!]', r'\centering', ''.join( [r'\includegraphics[width=', width, ']{', name, tag, '}']), r'\end{figure}' ] r.directive('only', 'latex and offset', wrap=False) r.newline() r.directive('raw', 'latex', content=tex_figure, indent=3) else: r.directive('only', 'website and slides', wrap=False) r.newline() r.directive(name='figure', arg='/images/{0}{1}'.format(name, tag), fields=options, indent=3) r.newline() r.directive('only', 'website and html', wrap=False) r.newline() r.directive(name='figure', arg='/images/{0}{1}'.format(name, tag), fields=options, indent=3) r.newline() if img_output.width > 740: options[2] = ('figwidth', '740px') r.directive('only', 'website and not (html or slides)', wrap=False) r.newline() img_str = ''.join([ '<div class="figure align-center" style="max-width:{5};">', '<img src="{0}/{1}/_images/{2}{3}" alt="{4}">', '</img>', '{6}</div>' ]) alt_html = docutils.core.publish_parts( alt, writer_name='html')['body'].strip() r.directive(name='raw', arg='html', content=img_str.format(conf.project.url, conf.git.branches.current, name, tag, alt, width, alt_html), indent=3) r.newline() image_rst_file_path = os.path.join(conf.paths.projectroot, image + '.rst') r.write(image_rst_file_path) logger.info('generated include file {0}.rst'.format(image))
def walk_and_write_rst(self, cat, prefix=None, depth=2): prefix = [] if prefix is None else prefix parent_dir = normalize_document_path([self.output_dir] + prefix) document_path = normalize_document_path([self.output_dir] + prefix + [cat.name], extension='.rst') print(document_path) d = RstCloth() assert cat.description, 'Catalog needs a description for title' #title = cat.description title = cat.name + ': ' + cat.description d.title(title) d.newline() d.content('Catalog URL:') d.newline() d.codeblock(self.remote_catalog_url(cat.path), language='html') d.newline() if len(prefix) > 0: d.h2('Parent Catalogs') d.newline() parent_links = [] for n in range(len(prefix)): levels_up = len(prefix) - n extra_prefixes = ['..'] * levels_up full_path = extra_prefixes + [to_valid_filename(prefix[n])] parent_cat_path = os.path.join(*full_path) parent_link = ':doc:' + d.inline_link(prefix[n], parent_cat_path)[:-1] parent_links.append(parent_link) d.content(' / '.join(parent_links)) d.newline() sub_catalogs = [] entries = [] for name, item in cat.items(): if item._container == 'catalog': if depth > 1: self.walk_and_write_rst(item(), prefix + [cat.name], depth - 1) sub_catalogs.append(name) else: entries.append(name) n = '.'.join(prefix + [name]) path_path = '/'.join(prefix) + '.rst' if len(sub_catalogs) > 0: d.h2('Child Catalogs') d.newline() sub_catalog_path = os.path.join(to_valid_filename(cat.name), '*') d.directive( 'toctree', fields=[ #('caption', 'Child Datasets'), ('glob', ''), ('maxdepth', '1') ], content=sub_catalog_path) if len(entries) > 0: d.h2('Datasets') d.newline() for name in entries: d.h3(name) d.newline() ds_item = cat[name] description = ds_item.description if description: d.content(description) d.newline() ds_repr = self.dataset_repr(ds_item) open_code = self.dataset_open_code(ds_item) name_jsfriendly = to_valid_filename(name).replace('.', '_') html = template.render(id=name_jsfriendly, open_code=open_code, repr=ds_repr, metadata=ds_item.metadata) d.directive('raw', arg='html', content=html) d.newline() ensure_dir_exists(parent_dir) d.write(document_path)
class StepsOutput(object): """ Base class for rendered step form. The render() method generates the rst in the internal RstCloth object. """ def __init__(self, steps, conf): if not isinstance(steps, Steps): raise TypeError else: self.steps = steps self.conf = conf self.current_step = 1 self.rst = RstCloth() self.hook() def hook(self): self.indent = 3 def edition_check(self, step): return giza.content.helper.edition_check(step, self.conf) @staticmethod def annotate_optional(step): if 'optional' in step and step['optional'] is True: if isinstance(step['title'], dict): step['title']['text'] = 'Optional. ' + step['title']['text'] else: if 'title' in step: step['title'] = 'Optional. ' + step['title'] elif 'heading' in step: step['heading'] = 'Optional. ' + step['heading'] del step['optional'] return step else: return step def render(self): for step in self.steps.source_list: if self.edition_check(step) is False: continue step = self.annotate_optional(step) self.heading(step) self.pre(step) self.current_step = step['stepnum'] if 'action' in step: if isinstance(step['action'], list): for block in step['action']: self.code_step(block) else: self.code_step(step['action']) self.content(step) self.post(step) def content(self, doc): if 'content' in doc and doc['content'] is not None: self.rst.content(doc['content'], wrap=False, indent=self.indent) self.rst.newline() def pre(self, doc): if 'pre' in doc and doc['pre'] is not None: self.rst.content(doc['pre'], wrap=False, indent=self.indent) self.rst.newline() def post(self, doc, code_step=False): if 'post' in doc and doc['post'] is not None: self.rst.content(doc['post'], wrap=False, indent=self.indent) self.rst.newline() if code_step is False: self.post_step_hook() def post_step_hook(self): pass def _heading(self, block, override_char=None, indent=0): if 'heading' in block: if isinstance(block['heading'], dict): if 'character' in block['heading']: pass else: block['heading']['character'] = override_char else: block['heading'] = { 'text': block['heading'], 'character': override_char } if block['heading']['text'] is None: logger.error('step in "{0}" is missing a heading'.format( os.path.basename(self.steps.source_fn))) return self.rst.heading(text=block['heading']['text'], char=block['heading']['character'], indent=indent) self.rst.newline() def code_step(self, block): if 'code' in block and 'content' in block: raise InvalidStep if 'heading' in block: self.block_heading(block) self.pre(block) if 'code' in block: if 'language' not in block: block['language'] = 'none' if not isinstance(block['code'], list): block['code'] = block['code'].split('\n') self.rst.directive(name='code-block', arg=block['language'], content=block['code'], indent=self.indent) self.rst.newline() if 'content' in block: self.content(block['content']) self.post(block, code_step=True) def key_name(self): key_name = os.path.splitext(os.path.basename(self.steps.source_fn))[0] if key_name.startswith('step-') or key_name.startswith('steps-'): key_name = key_name.split('-', 1)[1] return key_name
class StepsOutput(object): """ Base class for rendered step form. The render() method generates the rst in the internal RstCloth object. """ def __init__(self, steps, conf): if not isinstance(steps, Steps): raise TypeError else: self.steps = steps self.conf = conf self.current_step = 1 self.rst = RstCloth() self.hook() def hook(self): self.indent = 3 def edition_check(self, step): return giza.content.helper.edition_check(step, self.conf) @staticmethod def annotate_optional(step): if 'optional' in step and step['optional'] is True: if isinstance(step['title'], dict): step['title']['text'] = 'Optional. ' + step['title']['text'] else: if 'title' in step: step['title'] = 'Optional. ' + step['title'] elif 'heading' in step: step['heading'] = 'Optional. ' + step['heading'] del step['optional'] return step else: return step def render(self): for step in self.steps.source_list: if self.edition_check(step) is False: continue step = self.annotate_optional(step) self.heading(step) self.pre(step) self.current_step = step['stepnum'] if 'action' in step: if isinstance(step['action'], list): for block in step['action']: self.code_step(block) else: self.code_step(step['action']) self.content(step) self.post(step) def content(self, doc): if 'content' in doc and doc['content'] is not None: self.rst.content(doc['content'], wrap=False, indent=self.indent) self.rst.newline() def pre(self, doc): if 'pre' in doc and doc['pre'] is not None: self.rst.content(doc['pre'], wrap=False, indent=self.indent) self.rst.newline() def post(self, doc, code_step=False): if 'post' in doc and doc['post'] is not None: self.rst.content(doc['post'], wrap=False, indent=self.indent) self.rst.newline() if code_step is False: self.post_step_hook() def post_step_hook(self): pass def _heading(self, block, override_char=None, indent=0): if 'heading' in block: if isinstance(block['heading'], dict): if 'character' in block['heading']: pass else: block['heading']['character'] = override_char else: block['heading'] = { 'text': block['heading'], 'character': override_char } if block['heading']['text'] is None: logger.error('step in "{0}" is missing a heading'.format(os.path.basename(self.steps.source_fn))) return self.rst.heading(text=block['heading']['text'], char=block['heading']['character'], indent=indent) self.rst.newline() def code_step(self, block): if 'code' in block and 'content' in block: raise InvalidStep if 'heading' in block: self.block_heading(block) self.pre(block) if 'code' in block: if 'language' not in block: block['language'] = 'none' if not isinstance(block['code'], list): block['code'] = block['code'].split('\n') self.rst.directive(name='code-block', arg=block['language'], content=block['code'], indent=self.indent) self.rst.newline() if 'content' in block: self.content(block['content']) self.post(block, code_step=True) def key_name(self): key_name = os.path.splitext(os.path.basename(self.steps.source_fn))[0] if key_name.startswith('step-') or key_name.startswith('steps-'): key_name = key_name.split('-', 1)[1] return key_name
def full_example(collection, examples): """ :pram collection: An object with collection information and description. :pram examples: An object with examples, procedures and results. See :mod:`giza.content.examples.modules` for full documentation of the example data format. :returns: A populated ``RstCloth()`` object with the content of one example. """ r = RstCloth() if collection is not None: collection.render() if collection.options.show_title is True: if len(examples) == 1: ex_str = 'Example' else: ex_str = 'Examples' r.h2(ex_str) r.newline() if 'pre' in collection: r.content(collection.pre) r.newline() if 'content' in collection and collection.options.show_collection is True: r.content(collection.content) r.newline() if 'documents' in collection: r.codeblock(content=collection.documents, language='javascript') r.newline() if 'post' in collection: r.content(collection.post) r.newline() if 'final' in collection: r.content(collection.final) r.newline() for idx, example in enumerate(examples): example.render() if idx != 0: r.newline(2) if len(examples) > 1 and 'title' in example: getattr(r, 'h' + str(example.title.level))(example.title.text) r.newline() if 'pre' in example: r.content(example.pre) r.newline() lang = set() for op in example.operation: if 'pre' in op: r.content(op.pre) r.newline() # if content in op (e.g. for literalincludes) then # no need for code or language if 'content' in op: r.content(op.content) r.newline() elif 'literalinclude' in op: # Temporary and klugey include_options = [] if 'language' in op: include_options.append(('language', op.language)) r.directive('literalinclude', op.literalinclude, include_options) r.newline() elif 'code' in op: lang.add(op.language) r.codeblock(content=op.code, language=op.language) r.newline() if 'post' in op: r.content(op.post) r.newline() if 'post' in example: r.content(example.post) r.newline() if 'results' in example and example.results is not None: num_langs = len(lang) lang = list(lang)[0] if num_langs > 1: msg = 'specified more than one language for examples %s, using %s for results' logger.warning(msg, example.ref, lang) r.codeblock(content=example.results, language=lang) if 'final' in example: r.newline() r.content(example.final) return r
def generate_image_pages(dir, name, alt, output, conf): r = RstCloth() image = '/'.join([dir, name]) b = name for img_output in output: img_output['width'] = str(img_output['width']) + 'px' r.newline() if 'tag' in img_output: tag = '-' + img_output['tag'] + '.png' else: tag = '.png' options = [('alt', alt), ('align', 'center'), ('figwidth', img_output['width'])] if 'scale' in img_output: options.append(('scale', img_output['scale'])) if img_output['type'] == 'print': r.directive('only', 'latex', wrap=False, block=b) r.newline() r.directive(name='figure', arg='/images/{0}{1}'.format(name, tag), fields=options, indent=3, content=alt, block=b) else: alt_html = publish_parts(alt, writer_name='html')['body'].strip() img_tags = ['<div class="figure align-center" style="max-width:{5};">', '<img src="{0}/{1}/_images/{2}{3}" alt="{4}">', '</img>', '{6}</div>' ] img_str = ''.join(img_tags) r.directive('only', 'website and not html', wrap=False, block=b) r.newline() r.directive(name='raw', arg='html', content=img_str.format(conf.project.url, conf.git.branches.current, name, tag, alt, img_output['width'], alt_html), indent=3, block=b) r.newline(count=2) if img_output['width'] > 600: options[2] = ('figwidth', 600) r.directive('only', 'website and html', wrap=False, block=b) r.newline() r.directive(name='figure', arg='/images/{0}{1}'.format(name, tag), fields=options, indent=3, content=alt, block=b) r.newline(block=b) r.write(image + '.rst') logger.info('generated include file {0}.rst'.format(image))
class TestRstCloth(TestCase): @classmethod def setUp(self): self.r = RstCloth() def test_adding_without_blocks(self): self.r._add('foo') self.assertEqual(self.r.data[0], 'foo') def test_newline(self): self.r.newline() self.assertEqual(len(self.r.data), 1) def test_multi_newline(self): self.r.newline(count=4) self.assertEqual(len(self.r.data[0]), 4 - 1) def test_directive_simple(self): self.r.directive('test', block='d0') self.assertEqual(self.r.data[0], '.. test::') def test_directive_arg_named(self): self.r.directive('test', arg='what', block='d3') self.assertEqual(self.r.data[0], '.. test:: what') def test_directive_arg_positional(self): self.r.directive('test', 'what', block='d1') self.assertEqual(self.r.data[0], '.. test:: what') def test_directive_fields(self): self.r.directive('test', fields=[('a', 'b')], block='d2') self.assertEqual(self.r.data[0], '.. test::') self.assertEqual(self.r.data[1], ' :a: b') def test_directive_fields_with_arg(self): self.r.directive('test', arg='what', fields=[('a', 'b')], block='d4') self.assertEqual(self.r.data[0], '.. test:: what') self.assertEqual(self.r.data[1], ' :a: b') def test_directive_fields_multiple(self): self.r.directive('test', fields=[('a', 'b'), ('c', 'd')], block='d5') self.assertEqual(self.r.data[0], '.. test::') self.assertEqual(self.r.data[1], ' :a: b') self.assertEqual(self.r.data[2], ' :c: d') def test_directive_fields_multiple_arg(self): self.r.directive('test', arg='new', fields=[('a', 'b'), ('c', 'd')], block='d6') self.assertEqual(self.r.data[0], '.. test:: new') self.assertEqual(self.r.data[1], ' :a: b') self.assertEqual(self.r.data[2], ' :c: d') def test_directive_content(self): self.r.directive('test', content='string', block='d7') self.assertEqual(self.r.data[0], '.. test::') self.assertEqual(self.r.data[1], '') self.assertEqual(self.r.data[2], ' string') def test_directive_with_multiline_content(self): self.r.directive('test', content=['string', 'second'], block='d8') self.assertEqual(self.r.data[0], '.. test::') self.assertEqual(self.r.data[1], '') self.assertEqual(self.r.data[2], ' string') self.assertEqual(self.r.data[3], ' second') def test_directive_simple_indent(self): self.r.directive('test', indent=3, block='di0') self.assertEqual(self.r.data, [' .. test::']) def test_directive_arg_named_indent(self): self.r.directive('test', arg='what', indent=3, block='di3') self.assertEqual(self.r.data, [' .. test:: what']) def test_directive_arg_positional_indent(self): self.r.directive('test', 'what', indent=3, block='di1') self.assertEqual(self.r.data, [' .. test:: what']) def test_directive_fields_indent(self): self.r.directive('test', fields=[('a', 'b')], indent=3, block='di2') self.assertEqual(self.r.data, [' .. test::', ' :a: b']) def test_directive_fields_with_arg_indent(self): self.r.directive('test', arg='what', fields=[('a', 'b')], indent=3, block='di4') self.assertEqual(self.r.data, [' .. test:: what', ' :a: b']) def test_directive_fields_multiple_indent(self): self.r.directive('test', indent=3, fields=[('a', 'b'), ('c', 'd')], block='di5') self.assertEqual(self.r.data, [' .. test::', ' :a: b', ' :c: d']) def test_directive_fields_multiple_arg_indent(self): self.r.directive('test', arg='new', indent=3, fields=[('a', 'b'), ('c', 'd')], block='di6') self.assertEqual(self.r.data, [' .. test:: new', ' :a: b', ' :c: d']) def test_directive_content_indent(self): self.r.directive('test', content='string', indent=3, block='di7') self.assertEqual(self.r.data, [' .. test::', ' ', ' string']) def test_directive_with_multiline_content_indent(self): self.r.directive('test', indent=3, content=['string', 'second'], block='di8') self.assertEqual(self.r.data, [' .. test::', ' ', ' string', ' second']) def test_single_role_no_text(self): ret = self.r.role('test', 'value') self.assertEqual(ret, ':test:`value`') def test_multi_role_no_text(self): ret = self.r.role(['test', 'role'], 'value') self.assertEqual(ret, ':test:role:`value`') def test_single_role_text(self): ret = self.r.role('test', 'value', 'link') self.assertEqual(ret, ':test:`link <value>`') def test_multi_role_text(self): ret = self.r.role(['test', 'role'], 'value', 'link') self.assertEqual(ret, ':test:role:`link <value>`') def test_single_role_no_text_args(self): ret = self.r.role(name='test', value='value') self.assertEqual(ret, ':test:`value`') def test_multi_role_no_text_args(self): ret = self.r.role(name=['test', 'role'], value='value') self.assertEqual(ret, ':test:role:`value`') def test_single_role_text_args(self): ret = self.r.role(name='test', value='value', text='link') self.assertEqual(ret, ':test:`link <value>`') def test_multi_role_text_args(self): ret = self.r.role(name=['test', 'role'], value='value', text='link') self.assertEqual(ret, ':test:role:`link <value>`') def test_bold(self): ret = self.r.bold('text') self.assertEqual(ret, '**text**') def test_emph(self): ret = self.r.emph('text') self.assertEqual(ret, '*text*') def test_pre(self): ret = self.r.pre('text') self.assertEqual(ret, '``text``') def test_inline_link(self): ret = self.r.inline_link('text', 'link') self.assertEqual(ret, '`text <link>`_') def test_footnote_ref(self): ret = self.r.footnote_ref('name') self.assertEqual(ret, '[#name]_') def test_codeblock_simple(self): self.r.codeblock('ls -lha', block='cb0') self.assertEqual(self.r.data, ['::', ' ls -lha']) def test_codeblock_with_language(self): self.r.codeblock('ls -lha', language='shell',block='cb1') self.assertEqual(self.r.data, ['.. code-block:: shell', '', ' ls -lha']) def test_footnote(self): self.r.footnote('footsnotes', 'text of the note', block='fn0') self.assertEqual(self.r.data[0], '.. [#footsnotes] text of the note') def test_footnote_with_indent(self): self.r.footnote('footsnotes', 'text of the note', block='fn1', indent=3) self.assertEqual(self.r.data[0], ' .. [#footsnotes] text of the note') def test_footnote_with_wrap(self): self.r.footnote('footsnotes', 'the ' * 40, block='fn2', wrap=True) self.assertEqual(self.r.data[0], '.. [#footsnotes]' + ' the' * 14 + '\n ' + ' the' * 17 + '\n ' + ' the' * 9) def test_definition(self): self.r.definition('defitem', 'this is def text', block='dfn0') self.assertEqual(self.r.data, ['defitem', ' this is def text']) def test_definition_with_indent(self): self.r.definition('defitem', 'this is def text', indent=3, block='dfn1') self.assertEqual(self.r.data, [' defitem', ' this is def text']) def test_title_default(self): self.r.title('test text', block='hd0') self.assertEqual(self.r.data, ['=========', 'test text', '=========']) def test_title_alt(self): self.r.title('test text', char='-', block='hd1') self.assertEqual(self.r.data, ['---------', 'test text', '---------']) def test_heading_one(self): self.r.heading('test heading', char='-', indent=0, block='hd2') self.assertEqual(self.r.data, ['test heading', '------------']) def test_heading_two(self): self.r.heading('test heading', char='^', indent=0, block='hd3') self.assertEqual(self.r.data, ['test heading', '^^^^^^^^^^^^']) def test_h1(self): self.r.h1('test', block='hd4') self.assertEqual(self.r.data, ['test', '====']) def test_h2(self): self.r.h2('test', block='hd5') self.assertEqual(self.r.data, ['test', '----']) def test_h3(self): self.r.h3('test', block='hd6') self.assertEqual(self.r.data, ['test', '~~~~']) def test_h4(self): self.r.h4('test', block='hd7') self.assertEqual(self.r.data, ['test', '++++']) def test_h5(self): self.r.h5('test', block='hd8') self.assertEqual(self.r.data, ['test', '^^^^']) def test_h6(self): self.r.h6('test', block='hd9') self.assertEqual(self.r.data, ['test', ';;;;']) def test_replacement(self): self.r.replacement('foo', 'replace-with-bar', block='sub0') self.assertEqual(self.r.data, ['.. |foo| replace:: replace-with-bar']) def test_replacement_with_indent(self): self.r.replacement('foo', 'replace-with-bar', indent=3, block='sub1') self.assertEqual(self.r.data, [' .. |foo| replace:: replace-with-bar']) def test_li_simple(self): self.r.li('foo', block='li0') self.assertEqual(self.r.data, ['- foo']) def test_li_simple_indent(self): self.r.li('foo', indent=3, block='li1') self.assertEqual(self.r.data, [' - foo']) def test_li_simple_alt(self): self.r.li('foo', bullet='*', block='li2') self.assertEqual(self.r.data, ['* foo']) def test_li_simple_alt_indent(self): self.r.li('foo', bullet='*', indent=3, block='li3') self.assertEqual(self.r.data, [' * foo']) def test_li_complex(self): self.r.li(['foo', 'bar'], block='li0') self.assertEqual(self.r.data, ['- foo bar']) def test_li_complex_indent(self): self.r.li(['foo', 'bar'], indent=3, block='li1') self.assertEqual(self.r.data, [' - foo bar']) def test_li_complex_alt(self): self.r.li(['foo', 'bar'], bullet='*', block='li2') self.assertEqual(self.r.data, ['* foo bar']) def test_li_complex_alt_indent(self): self.r.li(['foo', 'bar'], bullet='*', indent=3, block='li3') self.assertEqual(self.r.data, [' * foo bar']) def test_field_simple(self): self.r.field('fname', 'fvalue', block='fld0') self.assertEqual(self.r.data, [':fname: fvalue']) def test_field_long_simple(self): self.r.field('fname is fname', 'fvalue', block='fld1') self.assertEqual(self.r.data, [':fname is fname: fvalue']) def test_field_simple_long(self): self.r.field('fname', 'v' * 54, block='fld2') self.assertEqual(self.r.data, [':fname: ' + 'v' * 54]) def test_field_simple_long_long(self): self.r.field('fname', 'v' * 55, block='fld3') self.assertEqual(self.r.data, [':fname:', '', ' ' + 'v' * 55]) def test_field_indent_simple(self): self.r.field('fname', 'fvalue', indent=3, block='fld4') self.assertEqual(self.r.data, [' :fname: fvalue']) def test_field_indent_long_simple(self): self.r.field('fname is fname', 'fvalue', indent=3, block='fld5') self.assertEqual(self.r.data, [' :fname is fname: fvalue']) def test_field_indent_simple_long(self): self.r.field('fname', 'v' * 54, indent=3, block='fld6') self.assertEqual(self.r.data, [' :fname: ' + 'v' * 54]) def test_field_indent_simple_long_long(self): self.r.field('fname', 'v' * 55, indent=3, block='fld7') self.assertEqual(self.r.data, [' :fname:', ' ', ' ' + 'v' * 55]) def test_field_wrap_simple(self): self.r.field('fname', 'the ' * 100, block='fld8') self.assertEqual(self.r.data, [':fname:', '', ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 10]) def test_field_wrap_indent_simple(self): self.r.field('fname', 'the ' * 100, indent=3, block='fld8') self.assertEqual(self.r.data, [' :fname:', ' ', ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 18, ' ' + ' the' * 10]) def test_content_string(self): self.r.content('this is sparta', block='ct0') self.assertEqual(self.r.data, ['this is sparta']) def test_content_list(self): self.r.content(['this is sparta', 'this is spinal tap'], block='ct1') self.assertEqual(self.r.data, ['this is sparta', 'this is spinal tap']) def test_content_indent_string(self): self.r.content('this is sparta', indent=3, block='ct2') self.assertEqual(self.r.data, [' this is sparta']) def test_content_indent_list(self): self.r.content(['this is sparta', 'this is spinal tap'], indent=3, block='ct3') self.assertEqual(self.r.data, [' this is sparta', ' this is spinal tap']) def test_content_long(self): self.r.content('the ' * 100, block='ct4') self.assertEqual(self.r.data, [ 'the' + ' the' * 17, 'the ' * 17 + 'the', 'the ' * 17 + 'the', 'the ' * 17 + 'the', 'the ' * 17 + 'the', 'the ' * 9 + 'the' ]) def test_ontent_indent_long(self): self.r.content('the ' * 100, indent=3 ,block='ct5') self.assertEqual(self.r.data, [ ' the' + ' the' * 17, " " + 'the ' * 17 + 'the', ' ' + 'the ' * 17 + 'the', ' ' + 'the ' * 17 + 'the', ' ' + 'the ' * 17 + 'the', ' ' + 'the ' * 9 + 'the' ]) def test_ontent_indent_long_nowrap(self): self.r.content('the ' * 100, wrap=False, indent=3 ,block='ct5') self.assertEqual(self.r.data, [ ' ' + 'the ' * 99 + 'the']) def test_ref_target_named(self): self.r.ref_target(name="foo-are-magic-ref0", block='ref0') self.assertEqual(self.r.data, ['.. _foo-are-magic-ref0:']) def test_ref_target_unnamed(self): self.r.ref_target("foo-are-magic-ref1", block='ref1') self.assertEqual(self.r.data, ['.. _foo-are-magic-ref1:']) def test_ref_target_named_with_indent(self): self.r.ref_target(name="foo-are-magic-ref2", indent=3, block='ref2') self.assertEqual(self.r.data, [' .. _foo-are-magic-ref2:']) def test_ref_target_unnamed_wo_indent(self): self.r.ref_target("foo-are-magic-ref3", 3, block='ref3') self.assertEqual(self.r.data, [' .. _foo-are-magic-ref3:'])
def generate_image_pages(image, conf): r = RstCloth() dir = image.dir name = image.name alt = image.alt output = image.outputs image = os.path.sep.join([dir, name]) for img_output in output: width = str(img_output.width) + 'px' build_type = img_output.build_type r.newline() if 'tag' in img_output: tag = ''.join(['-', img_output.tag, '.', build_type]) else: tag = '.' + build_type options = [('alt', alt), ('align', 'center'), ('figwidth', width)] if 'scale' in img_output: options.append(('scale', img_output.scale)) if 'target' in img_output: options.append(('target', (img_output.target))) if img_output.type == 'target': continue elif img_output.type == 'print': r.directive('only', 'latex and not offset', wrap=False) r.newline() r.directive(name='figure', arg='/images/{0}{1}'.format(name, tag), fields=options, indent=3) elif img_output.type == 'offset': tex_figure = [ r'\begin{figure}[h!]', r'\centering', ''.join([r'\includegraphics[width=', width, ']{', name, tag, '}']), r'\end{figure}' ] r.directive('only', 'latex and offset', wrap=False) r.newline() r.directive('raw', 'latex', content=tex_figure, indent=3) else: r.directive('only', 'website and slides', wrap=False) r.newline() r.directive(name='figure', arg='/images/{0}{1}'.format(name, tag), fields=options, indent=3) r.newline() r.directive('only', 'website and html', wrap=False) r.newline() r.directive(name='figure', arg='/images/{0}{1}'.format(name, tag), fields=options, indent=3) r.newline() if img_output.width > 740: options[2] = ('figwidth', '740px') r.directive('only', 'website and not (html or slides)', wrap=False) r.newline() img_str = ''.join(['<div class="figure align-center" style="max-width:{5};">', '<img src="{0}/{1}/_images/{2}{3}" alt="{4}">', '</img>', '{6}</div>']) alt_html = docutils.core.publish_parts(alt, writer_name='html')['body'].strip() r.directive(name='raw', arg='html', content=img_str.format(conf.project.url, conf.git.branches.current, name, tag, alt, width, alt_html), indent=3) r.newline() image_rst_file_path = os.path.join(conf.paths.projectroot, image + '.rst') r.write(image_rst_file_path) logger.info('generated include file {0}.rst'.format(image))
def generate_image_pages(dir, name, alt, output, conf): r = RstCloth() image = '/'.join([dir, name]) b = name for img_output in output: img_output['width'] = str(img_output['width']) + 'px' r.newline() if 'tag' in img_output: tag = '-' + img_output['tag'] + '.png' else: tag = '.png' options = [('alt', alt), ('align', 'center'), ('figwidth', img_output['width'])] if 'scale' in img_output: options.append(('scale', img_output['scale'])) if img_output['type'] == 'print': r.directive('only', 'latex', wrap=False, block=b) r.newline() r.directive(name='figure', arg='/images/{0}{1}'.format(name, tag), fields=options, indent=3, content=alt, block=b) else: alt_html = publish_parts(alt, writer_name='html')['body'].strip() img_tags = [ '<div class="figure align-center" style="max-width:{5};">', '<img src="{0}/{1}/_images/{2}{3}" alt="{4}">', '</img>', '{6}</div>' ] img_str = ''.join(img_tags) r.directive('only', 'website and not html', wrap=False, block=b) r.newline() r.directive(name='raw', arg='html', content=img_str.format(conf.project.url, conf.git.branches.current, name, tag, alt, img_output['width'], alt_html), indent=3, block=b) r.newline(count=2) if img_output['width'] > 600: options[2] = ('figwidth', 600) r.directive('only', 'website and html', wrap=False, block=b) r.newline() r.directive(name='figure', arg='/images/{0}{1}'.format(name, tag), fields=options, indent=3, content=alt, block=b) r.newline(block=b) image_rst_file_path = os.path.join(conf.paths.projectroot, image + '.rst') r.write(image_rst_file_path) logger.info('generated include file {0}.rst'.format(image))