Example #1
0
def dotest(outputname, nostamp=True):
    pdf = FPDF(unit="pt")
    pdf._putinfo = lambda: common.test_putinfo(pdf)
    pdf.add_page()
    pdf.set_font("Times", size=12)
    pdf.cell(0, 12, "Dummy content")

    # Get the PDF data the usual way via a real file
    pdf.output(outputname)
    with open(outputname, "rb") as file:
        data = file.read(1000)
        assert len(data) == 966, "Unexpected PDF file size"

    try:  # Python < 3 (Python 2.5 does not have the "io" module)
        from cStringIO import StringIO
        capture = StringIO()
        detach = lambda: capture
    except ImportError:  # Python >= 3.1
        from io import TextIOWrapper, BytesIO
        # Ensure that no text encoding is actually done
        capture = TextIOWrapper(BytesIO(), "undefined")
        detach = lambda: capture.detach()

    # Compare data when output() writes to stdout
    original_stdout = sys.stdout
    try:
        sys.stdout = capture
        pdf.output()
        capture = detach()
    finally:
        sys.stdout = original_stdout
    assert capture.getvalue() == data, "Unexpected stdout data"

    # Compare data when output() returns a byte string
    returned = pdf.output(dest="S")
    assert isinstance(returned, bytes), "output() should return bytes"
    assert returned == data, "Unexpected PDF data returned"
Example #2
0
def dotest(outputname, nostamp=True):
    pdf = FPDF(unit="pt")
    pdf._putinfo = lambda: common.test_putinfo(pdf)
    pdf.add_page()
    pdf.set_font("Times", size=12)
    pdf.cell(0, 12, "Dummy content")
    
    # Get the PDF data the usual way via a real file
    pdf.output(outputname)
    with open(outputname, "rb") as file:
        data = file.read(1000)
        assert len(data) == 966, "Unexpected PDF file size"
    
    try:  # Python < 3 (Python 2.5 does not have the "io" module)
        from cStringIO import StringIO
        capture = StringIO()
        detach = lambda: capture
    except ImportError:  # Python >= 3.1
        from io import TextIOWrapper, BytesIO
        # Ensure that no text encoding is actually done
        capture = TextIOWrapper(BytesIO(), "undefined")
        detach = lambda: capture.detach()
    
    # Compare data when output() writes to stdout
    original_stdout = sys.stdout
    try:
        sys.stdout = capture
        pdf.output()
        capture = detach()
    finally:
        sys.stdout = original_stdout
    assert capture.getvalue() == data, "Unexpected stdout data"
    
    # Compare data when output() returns a byte string
    returned = pdf.output(dest="S")
    assert isinstance(returned, bytes), "output() should return bytes"
    assert returned == data, "Unexpected PDF data returned"
Example #3
0
def show_graph(objs, edge_func, swap_source_target,
               max_depth=3, extra_ignore=(), filter=None, too_many=10,
               highlight=None, filename=None, extra_info=None,
               refcounts=False, shortnames=True):
    if not isinstance(objs, (list, tuple)):
        objs = [objs]

    # Write to a file-like string buffer, rather than disk.
    if filename == "string":
        f = StringIO()
    if filename and filename.endswith('.dot'):
        f = codecs.open(filename, 'w', encoding='utf-8')
        dot_filename = filename
    else:
        fd, dot_filename = tempfile.mkstemp(prefix='objgraph-',
                                            suffix='.dot', text=True)
        f = os.fdopen(fd, "w")
        if getattr(f, 'encoding', None):
            # Python 3 will wrap the file in the user's preferred encoding
            # Re-wrap it for utf-8
            import io
            f = io.TextIOWrapper(f.detach(), 'utf-8')
    f.write('digraph ObjectGraph {\n'
            '  node[shape=box, style=filled, fillcolor=white];\n')
    queue = []
    depth = {}
    ignore = set(extra_ignore)
    ignore.add(id(objs))
    ignore.add(id(extra_ignore))
    ignore.add(id(queue))
    ignore.add(id(depth))
    ignore.add(id(ignore))
    ignore.add(id(sys._getframe()))  # this function
    ignore.add(id(sys._getframe().f_locals))
    ignore.add(id(sys._getframe(1))) # show_refs/show_backrefs, most likely
    ignore.add(id(sys._getframe(1).f_locals))
    for obj in objs:
        f.write('  %s[fontcolor=red];\n' % (obj_node_id(obj)))
        depth[id(obj)] = 0
        queue.append(obj)
        del obj
    gc.collect()
    nodes = 0
    while queue:
        nodes += 1
        target = queue.pop(0)
        tdepth = depth[id(target)]
        f.write('  %s[label="%s"];\n' % (obj_node_id(target), obj_label(target, extra_info, refcounts, shortnames)))
        h, s, v = gradient((0, 0, 1), (0, 0, .3), tdepth, max_depth)
        if inspect.ismodule(target):
            h = .3
            s = 1
        if highlight and highlight(target):
            h = .6
            s = .6
            v = 0.5 + v * 0.5
        f.write('  %s[fillcolor="%g,%g,%g"];\n' % (obj_node_id(target), h, s, v))
        if v < 0.5:
            f.write('  %s[fontcolor=white];\n' % (obj_node_id(target)))
        if hasattr(getattr(target, '__class__', None), '__del__'):
            f.write("  %s->%s_has_a_del[color=red,style=dotted,len=0.25,weight=10];\n" % (obj_node_id(target), obj_node_id(target)))
            f.write('  %s_has_a_del[label="__del__",shape=doublecircle,height=0.25,color=red,fillcolor="0,.5,1",fontsize=6];\n' % (obj_node_id(target)))
        if tdepth >= max_depth:
            continue
        if is_proper_module(target) and not swap_source_target:
            # For show_backrefs(), it makes sense to stop when reaching a
            # module because you'll end up in sys.modules and explode the
            # graph with useless clutter.  For show_refs(), it makes sense
            # to continue.
            continue
        neighbours = edge_func(target)
        ignore.add(id(neighbours))
        n = 0
        skipped = 0
        for source in neighbours:
            if id(source) in ignore:
                continue
            if filter and not filter(source):
                continue
            if n >= too_many:
                skipped += 1
                continue
            if swap_source_target:
                srcnode, tgtnode = target, source
            else:
                srcnode, tgtnode = source, target
            elabel = edge_label(srcnode, tgtnode, shortnames)
            f.write('  %s -> %s%s;\n' % (obj_node_id(srcnode), obj_node_id(tgtnode), elabel))
            if id(source) not in depth:
                depth[id(source)] = tdepth + 1
                queue.append(source)
            n += 1
            del source
        del neighbours
        if skipped > 0:
            h, s, v = gradient((0, 1, 1), (0, 1, .3), tdepth + 1, max_depth)
            if swap_source_target:
                label = "%d more references" % skipped
                edge = "%s->too_many_%s" % (obj_node_id(target), obj_node_id(target))
            else:
                label = "%d more backreferences" % skipped
                edge = "too_many_%s->%s" % (obj_node_id(target), obj_node_id(target))
            f.write('  %s[color=red,style=dotted,len=0.25,weight=10];\n' % edge)
            f.write('  too_many_%s[label="%s",shape=box,height=0.25,color=red,fillcolor="%g,%g,%g",fontsize=6];\n' % (obj_node_id(target), label, h, s, v))
            f.write('  too_many_%s[fontcolor=white];\n' % (obj_node_id(target)))
    f.write("}\n")
    
    # If writing to a string, perform cleanup and return early.
    if filename == "string":
        graph = f.getvalue()
        f.close()
        return graph
    else:
        print("Graph written to %s (%d nodes)" % (dot_filename, nodes))        
        f.close()

    if filename and filename.endswith('.dot'):
        # nothing else to do, the user asked for a .dot file
        return
    if not filename and program_in_path('xdot'):
        print("Spawning graph viewer (xdot)")
        subprocess.Popen(['xdot', dot_filename], close_fds=True)
    elif program_in_path('dot'):
        if not filename:
            print("Graph viewer (xdot) not found, generating a png instead")
            filename = dot_filename[:-4] + '.png'
        stem, ext = os.path.splitext(filename)
        f = open(filename, 'wb')
        dot = subprocess.Popen(['dot', ('-T' + ext[1:]), dot_filename],
                               stdout=f, close_fds=False)
        dot.wait()
        if dot.returncode != 0:
            # XXX: shouldn't this go to stderr or a log?
            print("dot failed to generate '%s' image: output format not supported?")
        f.close()
        print("Image generated as %s" % filename)
    else:
        if filename:
            print("Graph viewer (xdot) and image renderer (dot) not found, not doing anything else")
        else:
            print("Unrecognized file type (%s), not doing anything else" % filename)