diff -Nru objgraph-3.4.1/appveyor.yml objgraph-3.5.0/appveyor.yml --- objgraph-3.4.1/appveyor.yml 2019-04-23 17:07:11.000000000 +0000 +++ objgraph-3.5.0/appveyor.yml 2020-10-08 16:41:24.000000000 +0000 @@ -5,16 +5,23 @@ # https://www.appveyor.com/docs/installed-software#python lists available # versions - PYTHON: "C:\\Python27" - - PYTHON: "C:\\Python35" - PYTHON: "C:\\Python36" - PYTHON: "C:\\Python37" + - PYTHON: "C:\\Python38" init: - "echo %PYTHON%" install: + - ps: | + if (-not (Test-Path $env:PYTHON)) { + curl -o install_python.ps1 https://raw.githubusercontent.com/matthew-brett/multibuild/11a389d78892cf90addac8f69433d5e22bfa422a/install_python.ps1 + .\install_python.ps1 + } + - ps: if (-not (Test-Path $env:PYTHON)) { throw "No $env:PYTHON" } - "set PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - python --version + - pip install -U virtualenv # upgrade pip in tox's virtualenvs - pip install tox - choco install graphviz - "set PATH=c:\\Program Files (x86)\\graphviz2.38\\bin;%PATH%" diff -Nru objgraph-3.4.1/CHANGES.rst objgraph-3.5.0/CHANGES.rst --- objgraph-3.4.1/CHANGES.rst 2019-04-23 17:32:17.000000000 +0000 +++ objgraph-3.5.0/CHANGES.rst 2020-10-11 11:07:03.000000000 +0000 @@ -3,6 +3,28 @@ .. currentmodule:: objgraph +3.5.0 (2020-10-11) +------------------ + +- Do not require ``mock`` for the test suite on Python 3; use unittest.mock + instead. + +- 100% test coverage for each version of Python rather than combined, using + ``coverage-python-version``. + +- Add the optional ``extra_node_attrs`` parameter to ``show_backrefs`` and + ``show_backrefs`` + +- Fix IPython/Jupyter inline graph support code that would kick in even if you + explicitly passed a filename='foo.png' argument to + ``show_refs``/``show_backrefs``. See `issue 47 + `_. + +- Add support for Python 3.8. + +- Drop support for Python 3.5. + + 3.4.1 (2019-04-23) ------------------ @@ -107,7 +129,7 @@ - Made internal helper methods private. This includes :func:`find_chain`, :func:`show_graph`, :func:`obj_node_id`, :func:`obj_label`, :func:`quote`, - :func:`long_typename`, :func:`safe_repr`, :func:`short_repr`, + :func:`long_typename`, :func:`safe_repr`, :func:`short_repr`, :func:`gradient`, :func:`edge_label`, and :func:`_program_in_path`. - Correctly determine the name of old-style classes in :func:`count`, diff -Nru objgraph-3.4.1/.coveragerc objgraph-3.5.0/.coveragerc --- objgraph-3.4.1/.coveragerc 1970-01-01 00:00:00.000000000 +0000 +++ objgraph-3.5.0/.coveragerc 2020-10-08 16:24:49.000000000 +0000 @@ -0,0 +1,4 @@ +[run] +source = objgraph +plugins = + coverage_python_version diff -Nru objgraph-3.4.1/debian/changelog objgraph-3.5.0/debian/changelog --- objgraph-3.4.1/debian/changelog 2019-08-31 13:17:55.000000000 +0000 +++ objgraph-3.5.0/debian/changelog 2020-10-15 02:45:57.000000000 +0000 @@ -1,3 +1,33 @@ +objgraph (3.5.0-1) unstable; urgency=medium + + [ Stefano Rivera ] + * New upstream release. + * Refresh patches. + * Update upstream metadata. + * Bump copyright years. + * Bump Standards-Version to 4.5.0, no changes needed. + * Drop Build-Depends and autopkgtest Depends on python3-mock, stdlib mock is + now used. + * Bump xdot to Recommends, objgraph tends to be used directly by developers, + so the Recommends set doesn't need to be minimal. + * Drop Suggests & Recommends on graphviz & xdot from python-objgraph-doc, + there aren't dot files there. + * Recommend python3-graphviz, it has been packaged for a while now, and is + useful when using objgraph in Jupyter. + * Depend on python3-setuptools in the autopkgtest: setup.py is tested. + + [ Ondřej Nový ] + * d/control: Update Maintainer field with new Debian Python Team + contact address. + * d/control: Update Vcs-* fields with new Debian Python Team Salsa + layout. + + [ Debian Janitor ] + * Apply multi-arch hints. + + python-objgraph-doc: Add Multi-Arch: foreign. + + -- Stefano Rivera Wed, 14 Oct 2020 19:45:57 -0700 + objgraph (3.4.1-2) unstable; urgency=medium * Remove python 2 library (Closes: #937178) diff -Nru objgraph-3.4.1/debian/control objgraph-3.5.0/debian/control --- objgraph-3.4.1/debian/control 2019-08-31 13:17:55.000000000 +0000 +++ objgraph-3.5.0/debian/control 2020-10-15 02:45:57.000000000 +0000 @@ -1,27 +1,27 @@ Source: objgraph Section: python Priority: optional -Maintainer: Debian Python Modules Team +Maintainer: Debian Python Team Uploaders: Stefano Rivera Build-Depends: debhelper-compat (= 12), dh-python, graphviz, - python3-sphinx (>= 1.0.7+dfsg), python3-all (>= 3.3), - python3-mock, - python3-setuptools -Standards-Version: 4.4.0 + python3-graphviz, + python3-setuptools, + python3-sphinx (>= 1.0.7+dfsg) +Standards-Version: 4.5.0 Homepage: https://mg.pov.lt/objgraph/ -Vcs-Git: https://salsa.debian.org/python-team/modules/objgraph.git -Vcs-Browser: https://salsa.debian.org/python-team/modules/objgraph +Vcs-Git: https://salsa.debian.org/python-team/packages/objgraph.git +Vcs-Browser: https://salsa.debian.org/python-team/packages/objgraph Rules-Requires-Root: no Package: python3-objgraph Architecture: all Depends: ${misc:Depends}, ${python3:Depends} -Recommends: graphviz -Suggests: python-objgraph-doc, xdot +Recommends: graphviz, python3-graphviz, xdot +Suggests: python-objgraph-doc Description: Module for exploring Python object reference graphs objgraph is a module that lets you visually explore Python object graphs. . @@ -33,8 +33,7 @@ Architecture: all Section: doc Depends: ${misc:Depends}, ${sphinxdoc:Depends} -Recommends: graphviz -Suggests: xdot +Multi-Arch: foreign Description: Module for exploring Python object reference graphs (Documentation) objgraph is a module that lets you visually explore Python object graphs. . diff -Nru objgraph-3.4.1/debian/copyright objgraph-3.5.0/debian/copyright --- objgraph-3.4.1/debian/copyright 2019-08-31 13:17:55.000000000 +0000 +++ objgraph-3.5.0/debian/copyright 2020-10-15 02:45:57.000000000 +0000 @@ -4,7 +4,7 @@ Source: https://pypi.org/project/objgraph/ Files: * -Copyright: 2008-2019, Marius Gedminas and contributors +Copyright: 2008-2020, Marius Gedminas and contributors License: Expat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -25,7 +25,7 @@ SOFTWARE. Files: debian/* -Copyright: 2010-2019, Stefano Rivera +Copyright: 2010-2020, Stefano Rivera License: GPL-2+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff -Nru objgraph-3.4.1/debian/patches/no-graphviz objgraph-3.5.0/debian/patches/no-graphviz --- objgraph-3.4.1/debian/patches/no-graphviz 2019-08-31 13:17:55.000000000 +0000 +++ objgraph-3.5.0/debian/patches/no-graphviz 2020-10-15 02:45:57.000000000 +0000 @@ -2,7 +2,7 @@ Date: Sun, 18 Feb 2018 18:21:41 -0800 Subject: Remove dependency on python-graphviz -Not packaged in Debian yet, and not actually needed. +We reduce this to a Recommends, it's only used by Jupyter Notebooks Forwarded: not-needed --- @@ -10,7 +10,7 @@ 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py -index af7f3cf..4cceba5 100755 +index f28ca18..0325d00 100755 --- a/setup.py +++ b/setup.py @@ -80,7 +80,6 @@ setup( @@ -19,5 +19,5 @@ install_requires=[ - 'graphviz', # just for ipython support currently ], - tests_require=['mock'], + tests_require=['mock;python_version=="2.7"'], test_suite='tests.test_suite', diff -Nru objgraph-3.4.1/debian/tests/control objgraph-3.5.0/debian/tests/control --- objgraph-3.4.1/debian/tests/control 2019-08-31 13:17:55.000000000 +0000 +++ objgraph-3.5.0/debian/tests/control 2020-10-15 02:45:57.000000000 +0000 @@ -1,2 +1,2 @@ Tests: unittests3 -Depends: python3-mock, python3-objgraph, python3-all, graphviz +Depends: graphviz, python3-all, python3-objgraph, python3-setuptools diff -Nru objgraph-3.4.1/debian/upstream/metadata objgraph-3.5.0/debian/upstream/metadata --- objgraph-3.4.1/debian/upstream/metadata 2019-08-31 13:17:55.000000000 +0000 +++ objgraph-3.5.0/debian/upstream/metadata 2020-10-15 02:45:57.000000000 +0000 @@ -1,7 +1,10 @@ -Name: objgraph -Archive: PyPI +--- Bug-Database: https://github.com/mgedmin/objgraph/issues Bug-Submit: https://github.com/mgedmin/objgraph/issues/new -Changelog: https://github.com/mgedmin/objgraph/blob/master/CHANGES.rst -Homepage: https://mg.pov.lt/objgraph +Changelog: https://mg.pov.lt/objgraph/CHANGES.html +Documentation: https://mg.pov.lt/objgraph +Registry: + - Name: PyPI + Entry: objgraph +Repository-Browse: https://github.com/mgedmin/objgraph Repository: https://github.com/mgedmin/objgraph diff -Nru objgraph-3.4.1/HACKING.rst objgraph-3.5.0/HACKING.rst --- objgraph-3.4.1/HACKING.rst 2017-11-24 16:31:12.000000000 +0000 +++ objgraph-3.5.0/HACKING.rst 2020-10-08 17:54:11.000000000 +0000 @@ -15,7 +15,7 @@ wrong output will be missed). I hope to improve that in the future, but don't hold your breath. Most of the testing is done manually or semi-automatically, e.g. by running ``make images`` and eyeballing the results (`imgdiff -`_ is handy there). +`_ is handy there). Sending me patches @@ -31,14 +31,11 @@ Supported Python versions ------------------------- -Python 2.4 through 2.7, as well as 3.x. +Python 2.7 and 3.5+. You can run the test suite for all supported Python versions with :: - make test-all-pythons - -or with `detox `_ (which will be faster, -since it runs the tests in parallel). + tox -p auto If a test fails, often the easiest way to debug is is to compare the output visually :: @@ -49,20 +46,20 @@ git checkout -- docs/*.png docs/*.dot -An easy way to get Pythons 2.4 through 2.7 (and 3.x) on Ubuntu is to use Felix +An easy way to get multiple Pythons versions on Ubuntu is to use Felix Krull's "`deadsnakes `_" PPA:: - sudo add-apt-repository ppa:fkrull/deadsnakes + sudo add-apt-repository -y ppa:deadsnakes sudo apt-get update - sudo apt-get install python2.{4,5,6,7} python3.{1,2,3} + sudo apt-get install python3.{6,7,8,9} Test coverage ------------- As I mentioned, the tests are mostly smoke tests, and even then they're -incomplete. Install `coverage `_ +incomplete. Install `coverage `_ to see how incomplete they are with :: make coverage @@ -93,7 +90,7 @@ (Many of the images include things like memory addresses which tend to change from run to run.) -`imgdiff `_ is useful for comparing the +`imgdiff `_ is useful for comparing the images with their older versions:: git config diff.imgdiff.command 'f() { imgdiff $1 $2; }; f' @@ -138,7 +135,7 @@ """ -I find `restview `_ very handy for +I find `restview `_ very handy for documentation writing: it lets me see how the text looks by pressing Ctrl-R in a browser window, without having to re-run any documentation building commands. The downside is that ``restview`` doesn't support Sphinx extensions @@ -184,5 +181,5 @@ every time. (I've later written a standalone tool, `check-manifest -`_ that can do this check for +`_ that can do this check for every Python package.) diff -Nru objgraph-3.4.1/Makefile objgraph-3.5.0/Makefile --- objgraph-3.4.1/Makefile 2019-04-23 17:33:06.000000000 +0000 +++ objgraph-3.5.0/Makefile 2020-10-11 11:08:25.000000000 +0000 @@ -1,4 +1,4 @@ -PYTHON = python +PYTHON = python3 FILE_WITH_VERSION = objgraph.py FILE_WITH_CHANGELOG = CHANGES.rst @@ -11,48 +11,41 @@ ALLSPHINXOPTS = -d $(SPHINXBUILDDIR)/doctrees $(SPHINXOPTS) docs/ -.PHONY: default -default: +.PHONY: all +all: @echo "Nothing to build here" .PHONY: images -images: +images: ##: regenerate graphs used in documentation $(PYTHON) setup.py --build-images .PHONY: docs -docs: +docs: ##: build HTML documentation $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/html @echo @echo "Now look at $(SPHINXBUILDDIR)/html/index.html" .PHONY: clean -clean: +clean: ##: remove build artifacts -rm -rf $(SPHINXBUILDDIR)/* build .PHONY: test -test: - $(PYTHON) tests.py +test: ##: run tests + tox -p auto .PHONY: -check: coverage - -.PHONY: test-all-pythons -test-all-pythons: - tox - -.PHONY: preview-pypi-description -preview-pypi-description: - # pip install restview, if missing - restview --long-description +check: +# 'make check' is defined in release.mk and here's how you can override it +define check_recipe = + @$(MAKE) coverage +endef .PHONY: coverage -coverage: - python2 -m coverage run --source=objgraph tests.py - python3 -m coverage run -a --source=objgraph tests.py - coverage report -m --fail-under=100 +coverage: ##: measure test coverage + tox -e coverage2,coverage3 -.PHONY: lint -lint: +.PHONY: flake8 +flake8: ##: check for style problems flake8 # Make sure $(VCS_DIFF_IMAGES) can work @@ -61,7 +54,7 @@ @test -z "`git config diff.imgdiff.command`" && git config diff.imgdiff.command 'f() { imgdiff --eog -H $$1 $$2; }; f' || true .PHONY: imgdiff -imgdiff: config-imgdiff +imgdiff: config-imgdiff ##: compare differences in generated images $(VCS_DIFF_IMAGES) @@ -78,21 +71,21 @@ echo "Please run make update-date"; exit 1; } .PHONY: update-date -update-date: +update-date: ##: set release date in source code to today sed -i -e "s/^__date__ = '.*'/__date__ = '`date +%Y-%m-%d`'/" $(FILE_WITH_VERSION) .PHONY: do-release do-release: config-imgdiff +# override the release recipe in release.mk define release_recipe = # I'm chicken so I won't actually do these things yet @echo "It is a good idea to run" @echo - @echo " make test-all-pythons" @echo " make clean images docs" @echo - @echo "about now. Then sanity-check the images with" + @echo "about now. Then review the images for unexpected differences with" @echo @echo " make imgdiff" @echo @@ -109,8 +102,9 @@ @echo endef +# XXX: I should switch to readthedocs.org .PHONY: publish-docs -publish-docs: +publish-docs: ##: publish documentation on the website test -d ~/www/objgraph || { \ echo "There's no ~/www/objgraph, do you have the website checked out?"; exit 1; } make clean docs @@ -122,4 +116,3 @@ @echo " cd ~/www/ && git commit -m \"Released objgraph `$(PYTHON) setup.py --version`\" && git push" @echo " ssh fridge 'cd www && git pull'" @echo - diff -Nru objgraph-3.4.1/MANIFEST.in objgraph-3.5.0/MANIFEST.in --- objgraph-3.4.1/MANIFEST.in 2017-12-19 18:49:07.000000000 +0000 +++ objgraph-3.5.0/MANIFEST.in 2020-10-08 16:24:49.000000000 +0000 @@ -19,3 +19,6 @@ # added by check_manifest.py include *.mk + +# added by check_manifest.py +include .coveragerc diff -Nru objgraph-3.4.1/objgraph.egg-info/pbr.json objgraph-3.5.0/objgraph.egg-info/pbr.json --- objgraph-3.4.1/objgraph.egg-info/pbr.json 2017-01-20 09:30:25.000000000 +0000 +++ objgraph-3.5.0/objgraph.egg-info/pbr.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"is_release": false, "git_version": "e8d4597"} \ No newline at end of file diff -Nru objgraph-3.4.1/objgraph.egg-info/PKG-INFO objgraph-3.5.0/objgraph.egg-info/PKG-INFO --- objgraph-3.4.1/objgraph.egg-info/PKG-INFO 2019-04-23 17:35:25.000000000 +0000 +++ objgraph-3.5.0/objgraph.egg-info/PKG-INFO 2020-10-11 11:16:05.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: objgraph -Version: 3.4.1 +Version: 3.5.0 Summary: Draws Python object reference graphs with graphviz Home-page: https://mg.pov.lt/objgraph/ Author: Marius Gedminas @@ -81,6 +81,28 @@ + 3.5.0 (2020-10-11) + ------------------ + + - Do not require ``mock`` for the test suite on Python 3; use unittest.mock + instead. + + - 100% test coverage for each version of Python rather than combined, using + ``coverage-python-version``. + + - Add the optional ``extra_node_attrs`` parameter to ``show_backrefs`` and + ``show_backrefs`` + + - Fix IPython/Jupyter inline graph support code that would kick in even if you + explicitly passed a filename='foo.png' argument to + ``show_refs``/``show_backrefs``. See `issue 47 + `_. + + - Add support for Python 3.8. + + - Drop support for Python 3.5. + + 3.4.1 (2019-04-23) ------------------ @@ -185,7 +207,7 @@ - Made internal helper methods private. This includes `find_chain`, `show_graph`, `obj_node_id`, `obj_label`, `quote`, - `long_typename`, `safe_repr`, `short_repr`, + `long_typename`, `safe_repr`, `short_repr`, `gradient`, `edge_label`, and `_program_in_path`. - Correctly determine the name of old-style classes in `count`, @@ -402,6 +424,6 @@ Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 diff -Nru objgraph-3.4.1/objgraph.egg-info/SOURCES.txt objgraph-3.5.0/objgraph.egg-info/SOURCES.txt --- objgraph-3.4.1/objgraph.egg-info/SOURCES.txt 2019-04-23 17:35:25.000000000 +0000 +++ objgraph-3.5.0/objgraph.egg-info/SOURCES.txt 2020-10-11 11:16:05.000000000 +0000 @@ -1,3 +1,4 @@ +.coveragerc .gitattributes .gitignore .travis.yml @@ -46,7 +47,6 @@ objgraph.egg-info/PKG-INFO objgraph.egg-info/SOURCES.txt objgraph.egg-info/dependency_links.txt -objgraph.egg-info/pbr.json objgraph.egg-info/requires.txt objgraph.egg-info/top_level.txt objgraph.egg-info/zip-safe \ No newline at end of file diff -Nru objgraph-3.4.1/objgraph.py objgraph-3.5.0/objgraph.py --- objgraph-3.4.1/objgraph.py 2019-04-23 17:32:17.000000000 +0000 +++ objgraph-3.5.0/objgraph.py 2020-10-11 11:07:15.000000000 +0000 @@ -43,12 +43,12 @@ try: # Python 2.x compatibility from StringIO import StringIO -except ImportError: +except ImportError: # pragma: PY3 from io import StringIO try: from types import InstanceType -except ImportError: +except ImportError: # pragma: PY3 # Python 3.x compatibility InstanceType = None @@ -56,26 +56,30 @@ __author__ = "Marius Gedminas (marius@gedmin.as)" __copyright__ = "Copyright (c) 2008-2017 Marius Gedminas and contributors" __license__ = "MIT" -__version__ = '3.4.1' -__date__ = '2019-04-23' +__version__ = '3.5.0' +__date__ = '2020-10-11' try: basestring -except NameError: +except NameError: # pragma: PY3 # Python 3.x compatibility basestring = str try: iteritems = dict.iteritems -except AttributeError: +except AttributeError: # pragma: PY3 # Python 3.x compatibility iteritems = dict.items IS_INTERACTIVE = False try: # pragma: nocover import graphviz - if get_ipython().__class__.__name__ != 'TerminalInteractiveShell': + if 'TerminalInteractiveShell' not in get_ipython().__class__.__name__: + # So far I know two shells where it's inappropriate to use inline + # graphics, because they're text only: + # - ipython uses a TerminalInteractiveShell + # - pycharm's console uses PyDevTerminalInteractiveShell IS_INTERACTIVE = True except (NameError, ImportError): pass @@ -642,7 +646,8 @@ def show_backrefs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10, highlight=None, filename=None, extra_info=None, - refcounts=False, shortnames=True, output=None): + refcounts=False, shortnames=True, output=None, + extra_node_attrs=None): """Generate an object reference graph ending at ``objs``. The graph will show you what objects refer to ``objs``, directly and @@ -675,6 +680,11 @@ Use ``extra_info`` (a function taking one argument and returning a string) to report extra information for objects. + Use ``extra_node_attrs`` (a function taking the current object as argument, + returning a dict of strings) to add extra attributes to the nodes. See + https://www.graphviz.org/doc/info/attrs.html for a list of possible node + attributes. + Specify ``refcounts=True`` if you want to see reference counts. These will mostly match the number of arrows pointing to an object, but can be different for various reasons. @@ -691,6 +701,7 @@ >>> show_backrefs(obj, filter=lambda x: not inspect.isclass(x)) >>> show_backrefs(obj, highlight=inspect.isclass) >>> show_backrefs(obj, extra_ignore=[id(locals())]) + >>> show_backrefs(obj, extra_node_attrs=lambda x: dict(URL=str(id(x)))) .. versionchanged:: 1.3 New parameters: ``filename``, ``extra_info``. @@ -704,6 +715,8 @@ .. versionchanged:: 2.0 New parameter: ``output``. + .. versionchanged:: 3.5 + New parameter: ``extra_node_attrs``. """ # For show_backrefs(), it makes sense to stop when reaching a # module because you'll end up in sys.modules and explode the @@ -714,12 +727,14 @@ edge_func=gc.get_referrers, swap_source_target=False, filename=filename, output=output, extra_info=extra_info, refcounts=refcounts, shortnames=shortnames, - cull_func=is_proper_module) + cull_func=is_proper_module, + extra_node_attrs=extra_node_attrs) def show_refs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10, highlight=None, filename=None, extra_info=None, - refcounts=False, shortnames=True, output=None): + refcounts=False, shortnames=True, output=None, + extra_node_attrs=None): """Generate an object reference graph starting at ``objs``. The graph will show you what objects are reachable from ``objs``, directly @@ -752,6 +767,11 @@ Use ``extra_info`` (a function returning a string) to report extra information for objects. + Use ``extra_node_attrs`` (a function taking the current object as argument, + returning a dict of strings) to add extra attributes to the nodes. See + https://www.graphviz.org/doc/info/attrs.html for a list of possible node + attributes. + Specify ``refcounts=True`` if you want to see reference counts. Examples: @@ -762,6 +782,7 @@ >>> show_refs(obj, filter=lambda x: not inspect.isclass(x)) >>> show_refs(obj, highlight=inspect.isclass) >>> show_refs(obj, extra_ignore=[id(locals())]) + >>> show_refs(obj, extra_node_attrs=lambda x: dict(URL=str(id(x)))) .. versionadded:: 1.1 @@ -777,13 +798,16 @@ .. versionchanged:: 2.0 New parameter: ``output``. + + .. versionchanged:: 3.5 + New parameter: ``extra_node_attrs``. """ return _show_graph(objs, max_depth=max_depth, extra_ignore=extra_ignore, filter=filter, too_many=too_many, highlight=highlight, edge_func=gc.get_referents, swap_source_target=True, filename=filename, extra_info=extra_info, refcounts=refcounts, shortnames=shortnames, - output=output) + output=output, extra_node_attrs=extra_node_attrs) def show_chain(*chains, **kw): @@ -896,7 +920,7 @@ max_depth=3, extra_ignore=(), filter=None, too_many=10, highlight=None, filename=None, extra_info=None, refcounts=False, shortnames=True, output=None, - cull_func=None): + cull_func=None, extra_node_attrs=None): if not _isinstance(objs, (list, tuple)): objs = [objs] @@ -908,14 +932,14 @@ elif filename and filename.endswith('.dot'): f = codecs.open(filename, 'w', encoding='utf-8') dot_filename = filename - elif IS_INTERACTIVE: + elif IS_INTERACTIVE and not filename: is_interactive = True f = StringIO() else: fd, dot_filename = tempfile.mkstemp(prefix='objgraph-', suffix='.dot', text=True) f = os.fdopen(fd, "w") - if getattr(f, 'encoding', None): + if getattr(f, 'encoding', None): # pragma: PY3 # Python 3 will wrap the file in the user's preferred encoding # Re-wrap it for utf-8 import io @@ -948,9 +972,11 @@ # traversing the reference graph backwards. 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))) + f.write(' %s[label="%s"%s];\n' % (_obj_node_id(target), + _obj_label(target, extra_info, + refcounts, shortnames), + _obj_attrs(target, + extra_node_attrs))) h, s, v = _gradient((0, 0, 1), (0, 0, .3), tdepth, max_depth) if inspect.ismodule(target): h = .3 @@ -1073,6 +1099,16 @@ return ('o%d' % id(obj)).replace('-', '_') +def _obj_attrs(obj, extra_node_attrs): + if extra_node_attrs is not None: + attrs = extra_node_attrs(obj) + return ", " + ", ".join('%s="%s"' % (name, _quote(value)) + for name, value in sorted(iteritems(attrs)) + if value is not None) + else: + return "" + + def _obj_label(obj, extra_info=None, refcounts=False, shortnames=True): if shortnames: label = [_short_typename(obj)] @@ -1100,7 +1136,7 @@ def _get_obj_type(obj): objtype = type(obj) - if type(obj) == InstanceType: + if type(obj) == InstanceType: # pragma: PY2 -- no old-style classes on PY3 objtype = obj.__class__ return objtype @@ -1146,7 +1182,7 @@ name = _name_or_repr(obj.__func__) if obj.__self__: return name + ' (bound)' - else: + else: # pragma: PY2 -- no unbound methods on Python 3 return name # NB: types.LambdaType is an alias for types.FunctionType! if _isinstance(obj, types.LambdaType) and obj.__name__ == '': diff -Nru objgraph-3.4.1/PKG-INFO objgraph-3.5.0/PKG-INFO --- objgraph-3.4.1/PKG-INFO 2019-04-23 17:35:25.000000000 +0000 +++ objgraph-3.5.0/PKG-INFO 2020-10-11 11:16:05.914251300 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: objgraph -Version: 3.4.1 +Version: 3.5.0 Summary: Draws Python object reference graphs with graphviz Home-page: https://mg.pov.lt/objgraph/ Author: Marius Gedminas @@ -81,6 +81,28 @@ + 3.5.0 (2020-10-11) + ------------------ + + - Do not require ``mock`` for the test suite on Python 3; use unittest.mock + instead. + + - 100% test coverage for each version of Python rather than combined, using + ``coverage-python-version``. + + - Add the optional ``extra_node_attrs`` parameter to ``show_backrefs`` and + ``show_backrefs`` + + - Fix IPython/Jupyter inline graph support code that would kick in even if you + explicitly passed a filename='foo.png' argument to + ``show_refs``/``show_backrefs``. See `issue 47 + `_. + + - Add support for Python 3.8. + + - Drop support for Python 3.5. + + 3.4.1 (2019-04-23) ------------------ @@ -185,7 +207,7 @@ - Made internal helper methods private. This includes `find_chain`, `show_graph`, `obj_node_id`, `obj_label`, `quote`, - `long_typename`, `safe_repr`, `short_repr`, + `long_typename`, `safe_repr`, `short_repr`, `gradient`, `edge_label`, and `_program_in_path`. - Correctly determine the name of old-style classes in `count`, @@ -402,6 +424,6 @@ Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 diff -Nru objgraph-3.4.1/release.mk objgraph-3.5.0/release.mk --- objgraph-3.4.1/release.mk 2019-04-23 17:32:17.000000000 +0000 +++ objgraph-3.5.0/release.mk 2020-10-11 10:54:04.000000000 +0000 @@ -1,4 +1,4 @@ -# release.mk version 1.4 (2019-04-23) +# release.mk version 2.0 (2020-10-11) # # Helpful Makefile rules for releasing Python packages. # https://github.com/mgedmin/python-project-skel @@ -11,10 +11,10 @@ DISTCHECK_DIFF_OPTS ?= $(DISTCHECK_DIFF_DEFAULT_OPTS) # These should be fine -PYTHON ?= python +PYTHON ?= python3 PYPI_PUBLISH ?= rm -rf dist && $(PYTHON) setup.py -q sdist bdist_wheel && twine check dist/* && twine upload dist/* LATEST_RELEASE_MK_URL = https://raw.githubusercontent.com/mgedmin/python-project-skel/master/release.mk -DISTCHECK_DIFF_DEFAULT_OPTS = -x PKG-INFO -x setup.cfg -x '*.egg-info' -I'^\#' +DISTCHECK_DIFF_DEFAULT_OPTS = -x PKG-INFO -x setup.cfg -x '*.egg-info' -x .github -I'^\#' # These should be fine, as long as you use Git VCS_GET_LATEST ?= git pull @@ -27,30 +27,58 @@ changelog_ver = `$(PYTHON) setup.py --version` changelog_date = `LC_ALL=C date +'$(CHANGELOG_DATE_FORMAT)'` +# Tweaking the look of 'make help'; most of these are awk literals and need the quotes +HELP_INDENT = "" +HELP_PREFIX = "make " +HELP_WIDTH = 24 +HELP_SEPARATOR = " \# " +HELP_SECTION_SEP = "\n" + +.PHONY: help +help: + @grep -Eh -e '^[a-zA-Z0-9_ -]+:.*?##: .*$$' -e '^##:' $(MAKEFILE_LIST) \ + | awk 'BEGIN {FS = "(^|:[^#]*)##: "; section=""}; \ + /^##:/ {printf "%s%s\n%s", section, $$2, $(HELP_SECTION_SEP); section=$(HELP_SECTION_SEP)} \ + /^[^#]/ {printf "%s\033[36m%-$(HELP_WIDTH)s\033[0m%s%s\n", \ + $(HELP_INDENT), $(HELP_PREFIX) $$1, $(HELP_SEPARATOR), $$2}' .PHONY: dist dist: $(PYTHON) setup.py -q sdist bdist_wheel +# Provide a default 'make check' to be the same as 'make test', since that's +# what 80% of my projects use, but make it possible to override. Now +# overriding Make rules is painful, so instead of a regular rule definition +# you'll have to override the check_recipe macro. +.PHONY: check +check: + $(check_recipe) + +ifndef check_recipe +define check_recipe = + @$(MAKE) test +endef +endif + .PHONY: distcheck distcheck: distcheck-vcs distcheck-sdist .PHONY: distcheck-vcs distcheck-vcs: +ifndef FORCE # Bit of a chicken-and-egg here, but if the tree is unclean, make # distcheck-sdist will fail. -ifndef FORCE @test -z "`$(VCS_STATUS) 2>&1`" || { echo; echo "Your working tree is not clean:" 1>&2; $(VCS_STATUS) 1>&2; exit 1; } endif -# NB: do not use $(MAKE) because then make -n distcheck will actually run -# it instead of just printing what it does +# NB: do not use $(MAKE) in rules with multiple shell commands joined by && +# because then make -n distcheck will actually run those instead of just +# printing what it does # TBH this could (and probably should) be replaced by check-manifest .PHONY: distcheck-sdist -distcheck-sdist: - make dist +distcheck-sdist: dist pkg_and_version=`$(PYTHON) setup.py --name`-`$(PYTHON) setup.py --version` && \ rm -rf tmp && \ mkdir tmp && \ @@ -97,20 +125,24 @@ grep -q "^$$ver_and_date$$" $(FILE_WITH_CHANGELOG) || { \ echo "$(FILE_WITH_CHANGELOG) has no entry for $$ver_and_date"; exit 1; } -# NB: do not use $(MAKE) because then make -n releasechecklist will -# actually run the distcheck instead of just printing what it does + +# NB: the Makefile that includes release.mk may want to add additional +# dependencies to the releasechecklist target, but I want 'make distcheck' to +# happen last, so that's why I put it into the recipe and not at the end of the +# list of dependencies. .PHONY: releasechecklist releasechecklist: check-latest-rules check-latest-version check-version-number check-long-description check-changelog - make distcheck + $(MAKE) distcheck .PHONY: release -release: releasechecklist do-release +release: releasechecklist do-release ##: prepare a new PyPI release .PHONY: do-release do-release: $(release_recipe) +ifndef release_recipe define release_recipe = # I'm chicken so I won't actually do these things yet @echo "Please run" @@ -124,3 +156,4 @@ @echo ' $(VCS_COMMIT_AND_PUSH)' @echo endef +endif diff -Nru objgraph-3.4.1/setup.py objgraph-3.5.0/setup.py --- objgraph-3.4.1/setup.py 2019-04-23 17:07:06.000000000 +0000 +++ objgraph-3.5.0/setup.py 2020-10-08 16:41:24.000000000 +0000 @@ -73,16 +73,16 @@ 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', ], keywords='object graph visualization graphviz garbage collection', py_modules=['objgraph'], install_requires=[ 'graphviz', # just for ipython support currently ], - tests_require=['mock'], + tests_require=['mock;python_version=="2.7"'], test_suite='tests.test_suite', zip_safe=True, ) diff -Nru objgraph-3.4.1/tests.py objgraph-3.5.0/tests.py --- objgraph-3.4.1/tests.py 2019-04-23 17:32:17.000000000 +0000 +++ objgraph-3.5.0/tests.py 2020-10-08 16:24:49.000000000 +0000 @@ -131,6 +131,16 @@ ''') +SINGLE_ELEMENT_OUTPUT_WITH_ATTR = textwrap.dedent('''\ + digraph ObjectGraph { + node[shape=box, style=filled, fillcolor=white]; + ${label_a}[fontcolor=red]; + ${label_a}[label="TestObject\\nTestObject(A)", x="y"]; + ${label_a}[fillcolor="0,0,1"]; + } +''') + + TWO_ELEMENT_OUTPUT = textwrap.dedent('''\ digraph ObjectGraph { node[shape=box, style=filled, fillcolor=white]; @@ -192,6 +202,18 @@ format(SINGLE_ELEMENT_OUTPUT, label_a=label)) + def test_with_extra_node_attrs(self): + obj = TestObject.get("A") + output = StringIO() + objgraph._show_graph([obj], edge_function(), False, output=output, + shortnames=True, + extra_node_attrs=lambda o: {'x': 'y'}) + output_value = output.getvalue() + label = objgraph._obj_node_id(obj) + self.assertEqual(output_value, + format(SINGLE_ELEMENT_OUTPUT_WITH_ATTR, + label_a=label)) + def test_filename_and_output(self): output = StringIO() self.assertRaises(ValueError, objgraph._show_graph, [], @@ -411,6 +433,16 @@ objgraph._obj_label(x, shortnames=False), r'mymodule\.MyClass\\n 2, "Python 3 has no unbound methods") def test_edge_label_unbound_method(self): class MyClass(object): @@ -486,6 +523,14 @@ objgraph._edge_label(MyClass.a_method, MyClass.a_method.__func__)) + def test_edge_label_bound_method(self): + class MyClass(object): + def a_method(self): + pass + self.assertEqual(' [label="__func__",weight=10]', + objgraph._edge_label(MyClass().a_method, + MyClass().a_method.__func__)) + def test_edge_label_long_type_names(self): x = type('MyClass', (), {'__module__': 'mymodule'})() d = {x: 1} diff -Nru objgraph-3.4.1/tox.ini objgraph-3.5.0/tox.ini --- objgraph-3.4.1/tox.ini 2019-04-23 17:07:08.000000000 +0000 +++ objgraph-3.5.0/tox.ini 2020-10-11 11:08:02.000000000 +0000 @@ -1,12 +1,32 @@ [tox] -envlist = py27, py35, py36, py37 +envlist = py27, py36, py37, py38 [testenv] -deps = mock +deps = + py,py27,coverage,coverage2: mock commands = - python tests.py {posargs} + python tests.py {posargs} [testenv:py] commands = - python --version - python tests.py {posargs} + python --version + python tests.py {posargs} + +[testenv:coverage] +deps = + {[testenv]deps} + coverage + coverage-python-version +commands = + coverage run tests.py + coverage report -m --fail-under=100 + +[testenv:coverage2] +basepython = python2 +deps = {[testenv:coverage]deps} +commands = {[testenv:coverage]commands} + +[testenv:coverage3] +basepython = python3 +deps = {[testenv:coverage]deps} +commands = {[testenv:coverage]commands} diff -Nru objgraph-3.4.1/.travis.yml objgraph-3.5.0/.travis.yml --- objgraph-3.4.1/.travis.yml 2019-04-23 17:07:10.000000000 +0000 +++ objgraph-3.5.0/.travis.yml 2020-10-08 16:41:24.000000000 +0000 @@ -2,19 +2,20 @@ dist: xenial python: - 2.7 - - 3.5 - 3.6 - 3.7 + - 3.8 addons: apt: packages: - graphviz install: - - pip install coverage coveralls flake8 -e . + - pip install coverage coverage-python-version coveralls flake8 -e . before_script: - make lint script: - - coverage run --source=objgraph tests.py + - coverage run tests.py + - coverage report -m --fail-under=100 after_success: - coveralls notifications: