def disvg(paths=None, colors=None,<EOL>filename=os_path.join(getcwd(), '<STR_LIT>'),<EOL>stroke_widths=None, nodes=None, node_colors=None, node_radii=None,<EOL>openinbrowser=True, timestamp=False,<EOL>margin_size=<NUM_LIT:0.1>, mindim=<NUM_LIT>, dimensions=None,<EOL>viewbox=None, text=None, text_path=None, font_size=None,<EOL>attributes=None, svg_attributes=None, svgwrite_debug=False, paths2Drawing=False):
_default_relative_node_radius = <NUM_LIT><EOL>_default_relative_stroke_width = <NUM_LIT><EOL>_default_path_color = '<STR_LIT>'  <EOL>_default_node_color = '<STR_LIT>'  <EOL>_default_font_size = <NUM_LIT:12><EOL>if os_path.dirname(filename) == '<STR_LIT>':<EOL><INDENT>filename = os_path.join(getcwd(), filename)<EOL><DEDENT>if timestamp:<EOL><INDENT>fbname, fext = os_path.splitext(filename)<EOL>dirname = os_path.dirname(filename)<EOL>tstamp = str(time()).replace('<STR_LIT:.>', '<STR_LIT>')<EOL>stfilename = os_path.split(fbname)[<NUM_LIT:1>] + '<STR_LIT:_>' + tstamp + fext<EOL>filename = os_path.join(dirname, stfilename)<EOL><DEDENT>if isinstance(paths, Path) or is_path_segment(paths):<EOL><INDENT>paths = [paths]<EOL><DEDENT>if paths:<EOL><INDENT>if not colors:<EOL><INDENT>colors = [_default_path_color] * len(paths)<EOL><DEDENT>else:<EOL><INDENT>assert len(colors) == len(paths)<EOL>if isinstance(colors, str):<EOL><INDENT>colors = str2colorlist(colors,<EOL>default_color=_default_path_color)<EOL><DEDENT>elif isinstance(colors, list):<EOL><INDENT>for idx, c in enumerate(colors):<EOL><INDENT>if is3tuple(c):<EOL><INDENT>colors[idx] = "<STR_LIT>" + str(c)<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>if nodes:<EOL><INDENT>if not node_colors:<EOL><INDENT>node_colors = [_default_node_color] * len(nodes)<EOL><DEDENT>else:<EOL><INDENT>assert len(node_colors) == len(nodes)<EOL>if isinstance(node_colors, str):<EOL><INDENT>node_colors = str2colorlist(node_colors,<EOL>default_color=_default_node_color)<EOL><DEDENT>elif isinstance(node_colors, list):<EOL><INDENT>for idx, c in enumerate(node_colors):<EOL><INDENT>if is3tuple(c):<EOL><INDENT>node_colors[idx] = "<STR_LIT>" + str(c)<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>assert paths or nodes<EOL>stuff2bound = []<EOL>if viewbox:<EOL><INDENT>if not isinstance(viewbox, str):<EOL><INDENT>viewbox = '<STR_LIT>' % viewbox<EOL><DEDENT>if dimensions is None:<EOL><INDENT>dimensions = viewbox.split('<STR_LIT:U+0020>')[<NUM_LIT:2>:<NUM_LIT:4>]<EOL><DEDENT><DEDENT>elif dimensions:<EOL><INDENT>dimensions = tuple(map(str, dimensions))<EOL>def strip_units(s):<EOL><INDENT>return re.search(r'<STR_LIT>', s.strip()).group()<EOL><DEDENT>viewbox = '<STR_LIT>' % tuple(map(strip_units, dimensions))<EOL><DEDENT>else:<EOL><INDENT>if paths:<EOL><INDENT>stuff2bound += paths<EOL><DEDENT>if nodes:<EOL><INDENT>stuff2bound += nodes<EOL><DEDENT>if text_path:<EOL><INDENT>stuff2bound += text_path<EOL><DEDENT>xmin, xmax, ymin, ymax = big_bounding_box(stuff2bound)<EOL>dx = xmax - xmin<EOL>dy = ymax - ymin<EOL>if dx == <NUM_LIT:0>:<EOL><INDENT>dx = <NUM_LIT:1><EOL><DEDENT>if dy == <NUM_LIT:0>:<EOL><INDENT>dy = <NUM_LIT:1><EOL><DEDENT>if paths:<EOL><INDENT>if not stroke_widths:<EOL><INDENT>sw = max(dx, dy) * _default_relative_stroke_width<EOL>stroke_widths = [sw]*len(paths)<EOL>max_stroke_width = sw<EOL><DEDENT>else:<EOL><INDENT>assert len(paths) == len(stroke_widths)<EOL>max_stroke_width = max(stroke_widths)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>max_stroke_width = <NUM_LIT:0><EOL><DEDENT>if nodes:<EOL><INDENT>if not node_radii:<EOL><INDENT>r = max(dx, dy) * _default_relative_node_radius<EOL>node_radii = [r]*len(nodes)<EOL>max_node_diameter = <NUM_LIT:2>*r<EOL><DEDENT>else:<EOL><INDENT>assert len(nodes) == len(node_radii)<EOL>max_node_diameter = <NUM_LIT:2>*max(node_radii)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>max_node_diameter = <NUM_LIT:0><EOL><DEDENT>extra_space_for_style = max(max_stroke_width, max_node_diameter)<EOL>xmin -= margin_size*dx + extra_space_for_style/<NUM_LIT:2><EOL>ymin -= margin_size*dy + extra_space_for_style/<NUM_LIT:2><EOL>dx += <NUM_LIT:2>*margin_size*dx + extra_space_for_style<EOL>dy += <NUM_LIT:2>*margin_size*dy + extra_space_for_style<EOL>viewbox = "<STR_LIT>" % (xmin, ymin, dx, dy)<EOL>if dx > dy:<EOL><INDENT>szx = str(mindim) + '<STR_LIT>'<EOL>szy = str(int(ceil(mindim * dy / dx))) + '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>szx = str(int(ceil(mindim * dx / dy))) + '<STR_LIT>'<EOL>szy = str(mindim) + '<STR_LIT>'<EOL><DEDENT>dimensions = szx, szy<EOL><DEDENT>if svg_attributes is not None:<EOL><INDENT>dimensions = (svg_attributes.get("<STR_LIT:width>", dimensions[<NUM_LIT:0>]),<EOL>svg_attributes.get("<STR_LIT>", dimensions[<NUM_LIT:1>]))<EOL>debug = svg_attributes.get("<STR_LIT>", svgwrite_debug)<EOL>dwg = Drawing(filename=filename, size=dimensions, debug=debug,<EOL>**svg_attributes)<EOL><DEDENT>else:<EOL><INDENT>dwg = Drawing(filename=filename, size=dimensions, debug=svgwrite_debug,<EOL>viewBox=viewbox)<EOL><DEDENT>if paths:<EOL><INDENT>for i, p in enumerate(paths):<EOL><INDENT>if isinstance(p, Path):<EOL><INDENT>ps = p.d()<EOL><DEDENT>elif is_path_segment(p):<EOL><INDENT>ps = Path(p).d()<EOL><DEDENT>else:  <EOL><INDENT>ps = p<EOL><DEDENT>if attributes:<EOL><INDENT>good_attribs = {'<STR_LIT:d>': ps}<EOL>for key in attributes[i]:<EOL><INDENT>val = attributes[i][key]<EOL>if key != '<STR_LIT:d>':<EOL><INDENT>try:<EOL><INDENT>dwg.path(ps, **{key: val})<EOL>good_attribs.update({key: val})<EOL><DEDENT>except Exception as e:<EOL><INDENT>warn(str(e))<EOL><DEDENT><DEDENT><DEDENT>dwg.add(dwg.path(**good_attribs))<EOL><DEDENT>else:<EOL><INDENT>dwg.add(dwg.path(ps, stroke=colors[i],<EOL>stroke_width=str(stroke_widths[i]),<EOL>fill='<STR_LIT:none>'))<EOL><DEDENT><DEDENT><DEDENT>if nodes:<EOL><INDENT>for i_pt, pt in enumerate([(z.real, z.imag) for z in nodes]):<EOL><INDENT>dwg.add(dwg.circle(pt, node_radii[i_pt], fill=node_colors[i_pt]))<EOL><DEDENT><DEDENT>if text:<EOL><INDENT>assert isinstance(text, str) or (isinstance(text, list) and<EOL>isinstance(text_path, list) and<EOL>len(text_path) == len(text))<EOL>if isinstance(text, str):<EOL><INDENT>text = [text]<EOL>if not font_size:<EOL><INDENT>font_size = [_default_font_size]<EOL><DEDENT>if not text_path:<EOL><INDENT>pos = complex(xmin + margin_size*dx, ymin + margin_size*dy)<EOL>text_path = [Line(pos, pos + <NUM_LIT:1>).d()]<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if font_size:<EOL><INDENT>if isinstance(font_size, list):<EOL><INDENT>assert len(font_size) == len(text)<EOL><DEDENT>else:<EOL><INDENT>font_size = [font_size] * len(text)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>font_size = [_default_font_size] * len(text)<EOL><DEDENT><DEDENT>for idx, s in enumerate(text):<EOL><INDENT>p = text_path[idx]<EOL>if isinstance(p, Path):<EOL><INDENT>ps = p.d()<EOL><DEDENT>elif is_path_segment(p):<EOL><INDENT>ps = Path(p).d()<EOL><DEDENT>else:  <EOL><INDENT>ps = p<EOL><DEDENT>pathid = '<STR_LIT>' + str(idx)<EOL>dwg.defs.add(dwg.path(d=ps, id=pathid))<EOL>txter = dwg.add(dwg.text('<STR_LIT>', font_size=font_size[idx]))<EOL>txter.add(txt.TextPath('<STR_LIT:#>'+pathid, s))<EOL><DEDENT><DEDENT>if paths2Drawing:<EOL><INDENT>return dwg<EOL><DEDENT>if not os_path.exists(os_path.dirname(filename)):<EOL><INDENT>makedirs(os_path.dirname(filename))<EOL><DEDENT>dwg.save()<EOL>xmlstring = md_xml_parse(filename).toprettyxml()<EOL>with open(filename, '<STR_LIT:w>') as f:<EOL><INDENT>f.write(xmlstring)<EOL><DEDENT>if openinbrowser:<EOL><INDENT>try:<EOL><INDENT>open_in_browser(filename)<EOL><DEDENT>except:<EOL><INDENT>print("<STR_LIT>")<EOL>print(filename)<EOL><DEDENT><DEDENT>
Takes in a list of paths and creates an SVG file containing said paths.
    REQUIRED INPUTS:
        :param paths - a list of paths

    OPTIONAL INPUT:
        :param colors - specifies the path stroke color.  By default all paths
        will be black (#000000).  This paramater can be input in a few ways
        1) a list of strings that will be input into the path elements stroke
            attribute (so anything that is understood by the svg viewer).
        2) a string of single character colors -- e.g. setting colors='rrr' is
            equivalent to setting colors=['red', 'red', 'red'] (see the
            'color_dict' dictionary above for a list of possibilities).
        3) a list of rgb 3-tuples -- e.g. colors = [(255, 0, 0), ...].

        :param filename - the desired location/filename of the SVG file
        created (by default the SVG will be stored in the current working
        directory and named 'disvg_output.svg').

        :param stroke_widths - a list of stroke_widths to use for paths
        (default is 0.5% of the SVG's width or length)

        :param nodes - a list of points to draw as filled-in circles

        :param node_colors - a list of colors to use for the nodes (by default
        nodes will be red)

        :param node_radii - a list of radii to use for the nodes (by default
        nodes will be radius will be 1 percent of the svg's width/length)

        :param text - string or list of strings to be displayed

        :param text_path - if text is a list, then this should be a list of
        path (or path segments of the same length.  Note: the path must be
        long enough to display the text or the text will be cropped by the svg
        viewer.

        :param font_size - a single float of list of floats.

        :param openinbrowser -  Set to True to automatically open the created
        SVG in the user's default web browser.

        :param timestamp - if True, then the a timestamp will be appended to
        the output SVG's filename.  This will fix issues with rapidly opening
        multiple SVGs in your browser.

        :param margin_size - The min margin (empty area framing the collection
        of paths) size used for creating the canvas and background of the SVG.

        :param mindim - The minimum dimension (height or width) of the output
        SVG (default is 600).

        :param dimensions - The (x,y) display dimensions of the output SVG.
        I.e. this specifies the `width` and `height` SVG attributes. Note that 
        these also can be used to specify units other than pixels. Using this 
        will override the `mindim` parameter.

        :param viewbox - This specifies the coordinated system used in the svg.
        The SVG `viewBox` attribute works together with the the `height` and 
        `width` attrinutes.  Using these three attributes allows for shifting 
        and scaling of the SVG canvas without changing the any values other 
        than those in `viewBox`, `height`, and `width`.  `viewbox` should be 
        input as a 4-tuple, (min_x, min_y, width, height), or a string 
        "min_x min_y width height".  Using this will override the `mindim` 
        parameter.

        :param attributes - a list of dictionaries of attributes for the input
        paths.  Note: This will override any other conflicting settings.

        :param svg_attributes - a dictionary of attributes for output svg.

        :param svgwrite_debug - This parameter turns on/off `svgwrite`'s 
        debugging mode.  By default svgwrite_debug=False.  This increases 
        speed and also prevents `svgwrite` from raising of an error when not 
        all `svg_attributes` key-value pairs are understood.

        :param paths2Drawing - If true, an `svgwrite.Drawing` object is 
        returned and no file is written.  This `Drawing` can later be saved 
        using the `svgwrite.Drawing.save()` method.

    NOTES:
        * The `svg_attributes` parameter will override any other conflicting 
        settings.

        * Any `extra` parameters that `svgwrite.Drawing()` accepts can be 
        controlled by passing them in through `svg_attributes`.

        * The unit of length here is assumed to be pixels in all variables.

        * If this function is used multiple times in quick succession to
        display multiple SVGs (all using the default filename), the
        svgviewer/browser will likely fail to load some of the SVGs in time.
        To fix this, use the timestamp attribute, or give the files unique
        names, or use a pause command (e.g. time.sleep(1)) between uses.