def multi_choice (values, argument): """ Checks a space-separated list of actual values against a list of approved values. Raises ValueError if it finds any value that is not in the list. Usage: option_spec = {'option' : functools.partial (multi_choice, list_of_values) } """ entries = argument.split () for e in entries: directives.choice (e, values) return entries
def choice (values, argument): """ Checks an actual value against a list of approved values. Raises ValueError if the value is not found in the list of values. Usage: option_spec = {'option' : functools.partial (choice, list_of_values) } """ return directives.choice (argument, values)
def lightbox_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ lightbox image directive usage: .. lightbox:: thumb_url img_url Title """ classes = ["lightbox-img"] if 'align' in options: directives.choice(options['align'], align_values) if isinstance(state, states.SubstitutionDef): # Check for align_v_values. if options['align'] not in align_v_values: raise DirectiveError(3, 'Error in "%s" directive: "%s" is not a valid value ' 'for the "align" option within a substitution ' 'definition. Valid values for "align" are: "%s".' % (name, options['align'], '", "'.join(align_v_values))) elif options['align'] not in align_h_values: raise DirectiveError(3, 'Error in "%s" directive: "%s" is not a valid value for ' 'the "align" option. Valid values for "align" are: "%s".' % (name, options['align'], '", "'.join(align_h_values))) classes.append('align-%s' % options['align']) thumb_href = arguments[0] img_href = arguments[1] title = u" ".join(content) alt = options.get('alt', '') html = '<a title="%(title)s" rel="lightbox" href="%(img_href)s"><img %(classes)s src="%(thumb_href)s" title="%(title)s" alt="%(alt)s"/></a>' % { "classes": 'class="%s"' % " ".join(classes) if classes else "", "title": title, "img_href": img_href, "thumb_href": thumb_href, "alt": alt, } return [nodes.raw("", html, format="html")]
def align(argument): """Convert and validate the :align: option. Args: argument: The argument passed to the :align: option. """ # This is not callable as self.align. We cannot make it a # staticmethod because we're saving an unbound method in # option_spec below. return directives.choice(argument, directives.images.Image.align_values)
def check_samples_slot(value): """Validate the samples_slot option to the TypeDocumenter. Valid positions are 'before-docstring' and 'after-docstring'. Using the explicit 'none' disables sample output. The default is after-docstring. """ if not value: return 'after-docstring' val = directives.choice( value, ('none', # do not include 'before-docstring', # show samples then docstring 'after-docstring', # show docstring then samples )) return val
def metricunits(unitname): return directives.choice( unitname.lower(), ( "ratio", "percent", "kbits", "mbits", "bytes", "kbytes", "mbytes", "nanoseconds", "microseconds", "milliseconds", "seconds", ), )
def run(self): name = self.arguments[0] command = directives.choice(self.arguments[1], allowed_commands) if command == 'init': # Create a temporary file to hold the database db_fh = tempfile.NamedTemporaryFile(delete = False) ehive_db_urls[name] = 'sqlite:///' + db_fh.name command_array = ['init_pipeline.pl', self.arguments[2], '-pipeline_url', ehive_db_urls[name]] for tweak in self.options.get('tweaks', '').split(): command_array.extend(['-tweak', tweak]) else: db = ehive_db_urls[name] if command == 'run_job': command_array = ['runWorker.pl', '-url', db, '-job_id', self.arguments[2]] elif command == 'sync': command_array = ['beekeeper.pl', '-url', db, '-sync'] if self.options.has_key('analyses_pattern'): command_array.extend(['-analyses_pattern', self.options['analyses_pattern']]) elif command == 'analysis_diagram': default_config_file = os.environ["EHIVE_ROOT_DIR"] + os.path.sep + "hive_config.json" command_array = ['generate_graph.pl', '-url', db, '-output', '/dev/stdout', '-format', 'dot', '-config_file', default_config_file] elif command == 'job_diagram': default_config_file = os.environ["EHIVE_ROOT_DIR"] + os.path.sep + "hive_config.json" command_array = ['visualize_jobs.pl', '-url', db, '-output', '/dev/stdout', '-format', 'dot', '-config_file', default_config_file] command_array.extend(self.options.get('vj_options', '').split()) command_array[0] = os.path.join(os.environ["EHIVE_ROOT_DIR"], 'scripts', command_array[0]) dotcontent = subprocess.check_output(command_array, stderr=sys.stderr) if command.endswith('diagram'): # We reuse the graphviz node (from the graphviz extension) as it deals better with image formats vs builders graphviz_node = graphviz() graphviz_node['code'] = dotcontent graphviz_node['options'] = {} return [graphviz_node] else: return []
class BokehPlotDirective(Directive): """ Sphinx directive. """ has_content = True optional_arguments = 2 option_spec = { 'source-position': lambda x: choice(x, ('below', 'above', 'none')), 'linenos': lambda x: True if flag(x) is None else False, } def run(self): env = self.state.document.settings.env app = env.app # filename *or* python code content, but not both if self.arguments and self.content: raise SphinxError( "bokeh-plot:: directive can't have both args and content") # process inline examples here if self.content: app.debug("[bokeh-plot] handling inline example in %r", env.docname) source = '\n'.join(self.content) # need docname not to look like a path docname = env.docname.replace("/", "-") js_name = "bokeh-plot-%s-inline-%s.js" % (docname, uuid4().hex) # the code runner just needs a real path to cd to, this will do path = join(env.bokeh_plot_auxdir, js_name) (script, js, js_path, source) = _process_script(source, path, env.bokeh_plot_auxdir, js_name) env.bokeh_plot_files[js_name] = (script, js, js_path, source) # process example files here else: example_path = self.arguments[0][:-3] # remove the ".py" # if it's an "internal" example, the python parser has already handled it if example_path in env.bokeh_plot_files: app.debug("[bokeh-plot] handling internal example in %r: %s", env.docname, self.arguments[0]) (script, js, js_path, source) = env.bokeh_plot_files[example_path] # handle examples external to the docs source, e.g. gallery examples else: app.debug("[bokeh-plot] handling external example in %r: %s", env.docname, self.arguments[0]) source = open(self.arguments[0]).read() source = decode_utf8(source) docname = env.docname.replace("/", "-") js_name = "bokeh-plot-%s-external-%s.js" % (docname, uuid4().hex) (script, js, js_path, source) = _process_script(source, self.arguments[0], env.bokeh_plot_auxdir, js_name) env.bokeh_plot_files[js_name] = (script, js, js_path, source) # use the source file name to construct a friendly target_id target_id = "%s.%s" % (env.docname, basename(js_path)) target = nodes.target('', '', ids=[target_id]) result = [target] linenos = self.options.get('linenos', False) code = nodes.literal_block(source, source, language="python", linenos=linenos, classes=[]) set_source_info(self, code) source_position = self.options.get('source-position', 'below') if source_position == "above": result += [code] result += [nodes.raw('', script, format="html")] if source_position == "below": result += [code] return result
def wmode(argument): """Conversion function for the "wmode" option.""" return directives.choice(argument, ('window', 'opaque', 'transparent'))
def choose_builders(arguments): return [directives.choice(argument, AVAILABLE_BUILDERS) for argument in arguments]
def align(argument): return directives.choice(argument, Figure.align_h_values)
def lhs_litstyle(argument): return directives.choice(argument, ('bird', 'latex'))
def yes_no_zero_one(argument): return directives.choice(argument, ('yes', 'no', '0', '1'))
class ManimDirective(Directive): r"""The manim directive, rendering videos while building the documentation. See the module docstring for documentation. """ has_content = True required_arguments = 1 optional_arguments = 0 option_spec = { "hide_source": bool, "quality": lambda arg: directives.choice( arg, ("low", "medium", "high", "fourk"), ), "save_as_gif": bool, "save_last_frame": bool, "ref_modules": lambda arg: process_name_list(arg, "mod"), "ref_classes": lambda arg: process_name_list(arg, "class"), "ref_functions": lambda arg: process_name_list(arg, "func"), "ref_methods": lambda arg: process_name_list(arg, "meth"), } final_argument_whitespace = True def run(self): # Rendering is skipped if the tag skip-manim is present, # or if we are making the pot-files should_skip = ( "skip-manim" in self.state.document.settings.env.app.builder.tags.tags or self.state.document.settings.env.app.builder.name == "gettext" ) if should_skip: node = SkipManimNode() self.state.nested_parse( StringList( [ f"Placeholder block for ``{self.arguments[0]}``.", "", ".. code-block:: python", "", ] + [" " + line for line in self.content] ), self.content_offset, node, ) return [node] from manim import config, tempconfig global classnamedict clsname = self.arguments[0] if clsname not in classnamedict: classnamedict[clsname] = 1 else: classnamedict[clsname] += 1 hide_source = "hide_source" in self.options save_as_gif = "save_as_gif" in self.options save_last_frame = "save_last_frame" in self.options assert not (save_as_gif and save_last_frame) ref_content = ( self.options.get("ref_modules", []) + self.options.get("ref_classes", []) + self.options.get("ref_functions", []) + self.options.get("ref_methods", []) ) if ref_content: ref_block = "References: " + " ".join(ref_content) else: ref_block = "" if "quality" in self.options: quality = f'{self.options["quality"]}_quality' else: quality = "example_quality" frame_rate = QUALITIES[quality]["frame_rate"] pixel_height = QUALITIES[quality]["pixel_height"] pixel_width = QUALITIES[quality]["pixel_width"] state_machine = self.state_machine document = state_machine.document source_file_name = Path(document.attributes["source"]) source_rel_name = source_file_name.relative_to(setup.confdir) source_rel_dir = source_rel_name.parents[0] dest_dir = Path(setup.app.builder.outdir, source_rel_dir).absolute() if not dest_dir.exists(): dest_dir.mkdir(parents=True, exist_ok=True) source_block = [ ".. code-block:: python", "", " from manim import *\n", *(" " + line for line in self.content), ] source_block = "\n".join(source_block) config.media_dir = (Path(setup.confdir) / "media").absolute() config.images_dir = "{media_dir}/images" config.video_dir = "{media_dir}/videos/{quality}" output_file = f"{clsname}-{classnamedict[clsname]}" config.assets_dir = Path("_static") config.progress_bar = "none" config.verbosity = "WARNING" example_config = { "frame_rate": frame_rate, "pixel_height": pixel_height, "pixel_width": pixel_width, "save_last_frame": save_last_frame, "write_to_movie": not save_last_frame, "output_file": output_file, } if save_last_frame: example_config["format"] = None if save_as_gif: example_config["format"] = "gif" user_code = self.content if user_code[0].startswith(">>> "): # check whether block comes from doctest user_code = [ line[4:] for line in user_code if line.startswith((">>> ", "... ")) ] code = [ "from manim import *", *user_code, f"{clsname}().render()", ] with tempconfig(example_config): run_time = timeit(lambda: exec("\n".join(code), globals()), number=1) video_dir = config.get_dir("video_dir") images_dir = config.get_dir("images_dir") _write_rendering_stats( clsname, run_time, self.state.document.settings.env.docname, ) # copy video file to output directory if not (save_as_gif or save_last_frame): filename = f"{output_file}.mp4" filesrc = video_dir / filename destfile = Path(dest_dir, filename) shutil.copyfile(filesrc, destfile) elif save_as_gif: filename = f"{output_file}.gif" filesrc = video_dir / filename elif save_last_frame: filename = f"{output_file}.png" filesrc = images_dir / filename else: raise ValueError("Invalid combination of render flags received.") rendered_template = jinja2.Template(TEMPLATE).render( clsname=clsname, clsname_lowercase=clsname.lower(), hide_source=hide_source, filesrc_rel=Path(filesrc).relative_to(setup.confdir).as_posix(), output_file=output_file, save_last_frame=save_last_frame, save_as_gif=save_as_gif, source_block=source_block, ref_block=ref_block, ) state_machine.insert_input( rendered_template.split("\n"), source=document.attributes["source"], ) return []
def showhide(argument): """Conversion function for the "showhide" option.""" return directives.choice(argument, ('show', 'hide', 'none'))
def backlinks(arg): value = directives.choice(arg, Contents.backlinks_values) if value == 'none': return None else: return value
def directive_truefalse(argument): return directives.choice(argument, ('true', 'false'))
def metricunits(unitname): return directives.choice( unitname.lower(), ('ratio', 'percent', 'kbits', 'mbits', 'bytes', 'kbytes', 'mbytes', 'nanoseconds', 'microseconds', 'milliseconds', 'seconds'))
def metrictypes(typename): return directives.choice( typename.lower(), ('counter', 'gauge', 'derivative', 'flag', 'text'))
def _option_graph2use(arg): return directives.choice( arg, ('hierarchical', 'colored', 'flat', 'orig', 'exec'))
def align(argument): return directives.choice(argument, ('left', 'center', 'right'))
def _source_position(argument): return choice(argument, ('below', 'above', 'none'))
def align(argument): """Conversion function for the "align" option.""" return directives.choice(argument, ('left', 'center', 'right'))
def align(argument): return directives.choice(argument, ("left", "center", "right"))
class PyReverse(Directive): """Runs pyreverse to generate UML for specified module name and options. The directive accepts the same arguments as pyreverse, except you should not specify ``--project`` or ``-o`` (output format). These are automatically specified. If you pass ``-c`` to this, the figure generated is forced to be the className.png like ``BurnMatrix.png``. For .gitignore purposes, this is a pain. Thus, we auto-prefix ALL images generated by this directive with ``pyrev_``. """ has_content = True required_arguments = 1 optional_arguments = 50 option_spec = { "alt": directives.unchanged, "height": directives.length_or_percentage_or_unitless, "width": directives.length_or_percentage_or_unitless, "align": lambda arg: directives.choice(arg, ("left", "right", "center")), "filename": directives.unchanged, } def run(self): try: args = list(self.arguments) args.append("--project") args.append(f"{args[0]}") args.append("-opng") # cannot use "pylint.pyreverse.main.Run" because it calls `sys.exit`. why? fig_name = self.options.get("filename", "classes_{}.png".format(args[0])) command = [sys.executable, "-m", "pylint.pyreverse.main"] print("Running {}".format(command + args)) env = dict(os.environ) # apply any runtime path mods to the pythonpath env variable (e.g. sys.path # mods made during doc confs) env["PYTHONPATH"] = os.pathsep.join(sys.path) subprocess.check_call(command + args, env=env) try: os.remove(os.path.join(APIDOC_DIR, fig_name)) except: pass shutil.move(fig_name, APIDOC_DIR) # add .gitignore helper prefix shutil.move( os.path.join(APIDOC_DIR, fig_name), os.path.join(APIDOC_DIR, f"pyr_{fig_name}"), ) new_content = [f".. figure:: /{APIDOC_DIR}/pyr_{fig_name}"] # assume we don't need the packages_, and delete. try: os.remove("packages_{}.png".format(args[0])) except: pass # pass the other args through (figure args like align) for opt, val in self.options.items(): if opt in ("filename", ): continue new_content.append(" :{}: {}\n".format(opt, val)) new_content.append("\n") for line in self.content: new_content.append(" " + line) para = nodes.container() # tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) lines = statemachine.StringList(new_content) self.state.nested_parse(lines, self.content_offset, para) return [para] except Exception as e: docname = self.state.document.settings.env.docname # add the error message directly to the built documentation and also tell the # builder raise self.error( "Unable to execute embedded doc code at {}:{} ... {}\n{}". format(docname, self.lineno, datetime.datetime.now(), str(e)))
def align(argument): return directives.choice(argument, directives.images.Image.align_h_values)
def hide_title(argument): return directives.choice(argument, ("true", "false"))
def _option_align(arg): return directives.choice(arg, ("top", "middle", "bottom", "left", "center", "right"))
def figure_align(argument): return directives.choice(argument, align_h_values)
def capalign(argument): # This is not callable as self.align. We cannot make it a # staticmethod because we're saving an unbound method in # option_spec below. return directives.choice( argument, ['left', 'right', 'center', 'justify', 'inherit'])
def bottom_right(argument): return directives.choice(argument, ('bottom', 'right'))
def _option_language(arg): """ Check language option. """ return directives.choice(arg, ("bash", "python"))
def nice_bool(arg): tvalues = ('true', 't', 'yes', 'y') fvalues = ('false', 'f', 'no', 'n') arg = directives.choice(arg, tvalues + fvalues) return arg in tvalues
def _option_context(arg): if arg in [None, 'reset']: return arg else: raise ValueError("argument should be None or 'reset'") return directives.choice(arg, ('None', 'reset'))
def align_spec(argument): # type: (Any) -> bool return directives.choice(argument, ('left', 'center', 'right'))
def align(argument): return directives.choice(argument, align_values)
def rendered_block_choice(argument): return directives.choice(argument, RENDERED_BLOCK_CHOICES)
def metrictypes(typename): return directives.choice(typename.lower(), ("counter", "gauge", "derivative", "flag", "text"))
def output(argument): """Conversion function for the "output" option.""" return directives.choice(argument, ('show', 'hide'))
def heading(argument): """ directives choices for heading tag """ return directives.choice(argument, ('h1', 'h2', 'h3', 'h4', 'h5', 'h6'))
def align(argument): """Conversion function for the "align" option.""" return directives.choice(argument, ("left", "center", "right"))
def _option_format(arg): return directives.choice(arg, ("python", "lisp"))
def httpOption(argument): """Conversion function for the "http" option.""" return directives.choice(argument, ("http", "https"))
def boolean(argument): return directives.choice(argument, ('true', 'false'))
def _option_format(arg): return directives.choice(arg, ('python', 'lisp'))
def fontset_choice(arg): return directives.choice(arg, ['cm', 'stix', 'stixsans'])
def align(argument): # This is not callable as self.align. We cannot make it a # staticmethod because we're saving an unbound method in # option_spec below. return directives.choice(argument, Image.align_values)
def csharp_unicodelevel(argument): return directives.choice(argument, ('none', 'basic', 'full'))
def align(argument): """Return thumbnail alignment.""" return directives.choice(argument, Image.align_values)
def raw_compress(argument): return directives.choice(argument, ('gz', 'bz2'))
def _option_format(arg): return directives.choice(arg, ('python', 'doctest'))
def _option_align(arg): return directives.choice( arg, ("top", "middle", "bottom", "left", "center", "right"))
def align_spec(argument): return directives.choice(argument, ('left', 'center', 'right'))
def backlinks(arg): value = directives.choice(arg, backlinks_values) if value == 'none': return None else: return value
class ManimDirective(Directive): r"""The manim directive, rendering videos while building the documentation. See the module docstring for documentation. """ has_content = True required_arguments = 1 optional_arguments = 0 option_spec = { "hide_source": bool, "quality": lambda arg: directives.choice(arg, ("low", "medium", "high", "fourk")), "save_as_gif": bool, "save_last_frame": bool, "ref_modules": lambda arg: process_name_list(arg, "mod"), "ref_classes": lambda arg: process_name_list(arg, "class"), "ref_functions": lambda arg: process_name_list(arg, "func"), "ref_methods": lambda arg: process_name_list(arg, "meth"), } final_argument_whitespace = True def run(self): if "skip-manim" in self.state.document.settings.env.app.builder.tags.tags: node = skip_manim_node() self.state.nested_parse(StringList(self.content[0]), self.content_offset, node) return [node] from manim import config global classnamedict clsname = self.arguments[0] if clsname not in classnamedict: classnamedict[clsname] = 1 else: classnamedict[clsname] += 1 hide_source = "hide_source" in self.options save_as_gif = "save_as_gif" in self.options save_last_frame = "save_last_frame" in self.options assert not (save_as_gif and save_last_frame) ref_content = (self.options.get("ref_modules", []) + self.options.get("ref_classes", []) + self.options.get("ref_functions", []) + self.options.get("ref_methods", [])) if ref_content: ref_block = f""" .. admonition:: Example References :class: example-reference {' '.join(ref_content)}""" else: ref_block = "" if "quality" in self.options: quality = f'{self.options["quality"]}_quality' else: quality = "example_quality" frame_rate = QUALITIES[quality]["frame_rate"] pixel_height = QUALITIES[quality]["pixel_height"] pixel_width = QUALITIES[quality]["pixel_width"] qualitydir = f"{pixel_height}p{frame_rate}" state_machine = self.state_machine document = state_machine.document source_file_name = document.attributes["source"] source_rel_name = relpath(source_file_name, setup.confdir) source_rel_dir = os.path.dirname(source_rel_name) while source_rel_dir.startswith(os.path.sep): source_rel_dir = source_rel_dir[1:] dest_dir = os.path.abspath( os.path.join(setup.app.builder.outdir, source_rel_dir)) if not os.path.exists(dest_dir): os.makedirs(dest_dir) source_block = [ ".. code-block:: python", "", *[" " + line for line in self.content], ] source_block = "\n".join(source_block) config.media_dir = Path(setup.confdir) / "media" config.images_dir = "{media_dir}/images" config.video_dir = "{media_dir}/videos/{quality}" output_file = f"{clsname}-{classnamedict[clsname]}" config.assets_dir = Path("_static") config_code = [ f'config["frame_rate"] = {frame_rate}', f'config["pixel_height"] = {pixel_height}', f'config["pixel_width"] = {pixel_width}', f'config["save_last_frame"] = {save_last_frame}', f'config["save_as_gif"] = {save_as_gif}', f'config["write_to_movie"] = {not save_last_frame}', f'config["output_file"] = r"{output_file}"', ] user_code = self.content if user_code[0].startswith( ">>> "): # check whether block comes from doctest user_code = [ line[4:] for line in user_code if line.startswith((">>> ", "... ")) ] code = [ "from manim import *", *config_code, *user_code, f"{clsname}().render()", ] exec("\n".join(code), globals()) # copy video file to output directory if not (save_as_gif or save_last_frame): filename = f"{output_file}.mp4" filesrc = config.get_dir("video_dir") / filename destfile = os.path.join(dest_dir, filename) shutil.copyfile(filesrc, destfile) elif save_as_gif: filename = f"{output_file}.gif" filesrc = config.get_dir("video_dir") / filename elif save_last_frame: filename = f"{output_file}.png" filesrc = config.get_dir("images_dir") / filename else: raise ValueError("Invalid combination of render flags received.") rendered_template = jinja2.Template(TEMPLATE).render( clsname=clsname, clsname_lowercase=clsname.lower(), hide_source=hide_source, filesrc_rel=os.path.relpath(filesrc, setup.confdir), output_file=output_file, save_last_frame=save_last_frame, save_as_gif=save_as_gif, source_block=source_block, ref_block=ref_block, ) state_machine.insert_input(rendered_template.split("\n"), source=document.attributes["source"]) return []