{"id":30873567,"url":"https://github.com/duboviy/extdbg","last_synced_at":"2025-09-07T23:11:42.688Z","repository":{"id":57427726,"uuid":"69942556","full_name":"duboviy/extdbg","owner":"duboviy","description":"💮 Extended debugging python utilities","archived":false,"fork":false,"pushed_at":"2020-04-26T19:55:34.000Z","size":49,"stargazers_count":21,"open_issues_count":0,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-19T15:28:13.768Z","etag":null,"topics":["debug","python","testing","utility"],"latest_commit_sha":null,"homepage":"https://pypi.python.org/pypi/extdbg","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/duboviy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null}},"created_at":"2016-10-04T07:24:04.000Z","updated_at":"2023-10-23T15:55:07.000Z","dependencies_parsed_at":"2022-09-19T19:50:42.612Z","dependency_job_id":null,"html_url":"https://github.com/duboviy/extdbg","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/duboviy/extdbg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duboviy%2Fextdbg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duboviy%2Fextdbg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duboviy%2Fextdbg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duboviy%2Fextdbg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/duboviy","download_url":"https://codeload.github.com/duboviy/extdbg/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duboviy%2Fextdbg/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274107977,"owners_count":25223473,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-07T02:00:09.463Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["debug","python","testing","utility"],"created_at":"2025-09-07T23:11:37.565Z","updated_at":"2025-09-07T23:11:42.674Z","avatar_url":"https://github.com/duboviy.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1\u003e\u003cimg src=\"https://raw.githubusercontent.com/duboviy/extdbg/master/logo.png\" height=85 alt=\"logo\" title=\"logo\"\u003e extdbg\u003c/h1\u003e\n\nby [Eugene Duboviy](https://duboviy.github.io/)\n\n[![Build Status](https://travis-ci.org/duboviy/extdbg.svg?branch=master)](https://travis-ci.org/duboviy/extdbg) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/b97c91e553724c369a3ec3b2d9ea50c6)](https://www.codacy.com/app/dubovoy/extdbg?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=duboviy/extdbg\u0026amp;utm_campaign=Badge_Grade) [![PyPI](https://img.shields.io/pypi/v/extdbg.svg)](https://pypi.python.org/pypi/extdbg) [![Code Health](https://landscape.io/github/duboviy/extdbg/master/landscape.svg?style=flat)](https://landscape.io/github/duboviy/extdbg/master) [![Open Source Love](https://badges.frapsoft.com/os/mit/mit.svg?v=102)](https://github.com/duboviy/extdbg/) [![PRs \u0026 Issues Welcome](https://img.shields.io/badge/PRs%20\u0026%20Issues-welcome-brightgreen.svg)](https://github.com/duboviy/extdbg/pulls) [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/duboviy/extdbg/)\n\nExtended debugging python utilities\n\n\n\n## Installation:\n\nInstall from PyPI:\n```\npip install extdbg\n```\nOr using alternative command:\n```\npip install https://github.com/duboviy/extdbg/archive/master.zip\n```\nOr from source use:\n```\npython setup.py install\n```\n\n## Supported python versions\n\n  * 2.7\n  * 3.3\n  * 3.4\n  * 3.5\n  * PyPy\n\n## PyPI\n\n* [Package](https://pypi.python.org/pypi/extdbg)\n* [Documentation](https://pythonhosted.org/extdbg/)\n\nContents\n--------\n\n```\nfrom extdbg import ... (see variants in list below)\n```\n\n- `init_except_hook` - initialise extended traceback hook with local variables in exception message\n- `add_watcher_attribute(name, watch_get=False)` - when called within some class (for example `add_watcher_attribute('name')`) - instances of that class will log every change to the attribute. Also tracks every access to attribute if `watch_get` is `True`.\n- `where_is(object)` - return location of the object definition in code.\n- `from_where_called()` - return location in code from where function which calls this is called\n- `threaded` - allow you to decorate a function in your Python code, making it run in a separate thread\n- `get_func_calls` - return all function calls from a python file\n- `public and internal` - allow you to use additional context decorators (like public and private in other languages)\n- `hackable_properties` - properties mock setter. Use this module to mock/stub any property of New Style Class\n- `watch_for_output` - log location in code where some output is performed\n- `bound_func` - bind any function/lambda as instance's method\n- `save_object and load_object` - pickle/unpickle objects in/from files\n- `enable_debug` - use on remote process to debug it using pycharm remote server run\n \n\n... and many other features\n\nBasic usage examples\n--------\n\n- `init_except_hook` - initialise extended traceback hook with local variables in exception message\n\n```python\nfrom extdbg import init_except_hook\n\n\ninit_except_hook()\n\ndef test(a, b):\n    a / b\n\ntest(1, 0)\n```\n\n- `where_is(object)` - return location of the object definition in code\n\n```python\nfrom extdbg import where_is\n\n\nlocation = where_is(where_is)\n\nexpected_filename = \"navigate.py\"\nexpected_line_no = 17\n\nassert location.filename.endswith(expected_filename)\nassert location.line_no == expected_line_no\n```\n\n- `from_where_called()` - return location in code from where function which calls this is called\n\n```python\nfrom extdbg import from_where_called\n\n\ndef f2():\n    print(from_where_called())\n\ndef f1():\n    f2()\n    \nf1()\n```\n\n- `threaded` - allow you to decorate a function in your Python code, making it run in a separate thread\n\n```python\nfrom extdbg import threaded\n\n\ndef fib(n):\n    if n \u003c 2:\n        return n\n    return fib(n-2) + fib(n-1)\n\nprint(fib(35))\n\n@threaded(daemon=True)\ndef _fib(n):\n    if n \u003c 2:\n        return n\n    return fib(n-2) + fib(n-1)\n\nprint(_fib(35))\n```\n\n- `get_func_calls` - return all function calls from a python file\n\n```python\nimport ast\n\nfrom extdbg import get_func_calls\n\n\nfilename = __file__\ntree = ast.parse(open(__file__).read())\nprint(get_func_calls(tree))\n```\n\n- `public and internal` - allow you to use additional context decorators (like public and private in other languages). You can use decorator to wrap your code:\n\n```python\nfrom extdbg import public, internal\n\n\nclass A(object):\n\n    @internal\n    def m1(self):\n        pass\n\n    @public\n    def m2(self):\n        self.m1()\n\na = A()\na.m1()  # can't call API m1 is marked as internal!\na.m2()\n```\n\n- `hackable_properties` - properties mock setter. Use this module to mock/stub any property of New Style Class\n\n```python\nfrom extdbg import hackable_properties, ValueWrapper\n\n\nclass NewStyleCls(object):\n    @property\n    def prop_2_mock(self):\n        raise RuntimeError(\"Unmocked property!\")\n\n\n@hackable_properties\nclass NewStyleClsMocked(NewStyleCls):\n    def __init__(self, *args, **kwargs):\n        super(NewStyleClsMocked, self).__init__(*args, **kwargs)\n        self.prop_2_mock = ValueWrapper(\"MOCKING_PROP_VALUE\")\n\nmockable_cls = NewStyleClsMocked()\nassert mockable_cls.prop_2_mock == \"MOCKING_PROP_VALUE\"\n```\n\n- `watch_for_output(condition=lambda x: True, stream='stdout')` - log location in code where some output is performed\n\n```python\nimport unittest\n\nfrom mock import Mock, patch\n\n\nclass TestWatchForOutput(unittest.TestCase):\n\n    def test_works(self):\n        from extdbg import watch_for_output\n\n        mock_stdout = Mock()\n        output = []\n\n        def write(txt):\n            output.append(txt)\n\n        mock_stdout.write = write\n        with patch('sys.stdout', mock_stdout):\n            watch_for_output(lambda s: 'yes' in s)\n            print('yes')\n\n        self.assertIn('yes', output)\n```\n\n- `bound_func` - bind any function/lambda as instance's method\n\n```python\nimport unittest\nimport inspect\n\nfrom mock import Mock, patch\n\n\nclass TestBoundFunc(unittest.TestCase):\n\n    def test_works(self):\n        from extdbg import bound_func\n        # Example of usage\n        class Cls2Bound:\n            pass\n\n        instance2Bound = Cls2Bound()\n\n        def func(*args, **kwargs):\n            print(args, kwargs)\n\n        l = lambda *args, **kwargs: None\n\n        # bound method Cls2Bound.func\n        bound_method1 = bound_func(func, instance2Bound, Cls2Bound)\n        # bound method Cls2Bound.\u003clambda\u003e\n        bound_method2 = bound_func(l, instance2Bound, Cls2Bound)\n\n        self.assertTrue(inspect.ismethod(bound_method1))\n        self.assertTrue(inspect.ismethod(bound_method2))\n```\n\n- `enable_debug` - use on remote process to debug it using pycharm remote server run\n\n```python\nfrom extdbg import enable_debug\n\n\nenable_debug(\"/home/\u003cusername\u003e/pydev/debug-eggs/pycharm-debug.egg\", 'localhost')\n```\n\n## License\n\n**MIT** licensed library. See [LICENSE.txt](LICENSE.txt) for details.\n\n## Contributing\n\nIf you have suggestions for improving the extdbg, please [open an issue or\npull request on GitHub](https://github.com/duboviy/extdbg/).\n\n## Badges\n\n[![forthebadge](http://forthebadge.com/images/badges/fuck-it-ship-it.svg)](https://github.com/duboviy/extdbg/)\n[![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/duboviy/extdbg/) [![forthebadge](http://forthebadge.com/images/badges/built-by-hipsters.svg)](https://github.com/duboviy/extdbg/) [![forthebadge](http://forthebadge.com/images/badges/built-with-swag.svg)](https://github.com/duboviy/extdbg/)\n\n[![forthebadge](http://forthebadge.com/images/badges/powered-by-electricity.svg)](https://github.com/duboviy/extdbg/) [![forthebadge](http://forthebadge.com/images/badges/powered-by-oxygen.svg)](https://github.com/duboviy/extdbg/) [![forthebadge](http://forthebadge.com/images/badges/powered-by-water.svg)](https://github.com/duboviy/extdbg/) [![forthebadge](http://forthebadge.com/images/badges/powered-by-responsibility.svg)](https://github.com/duboviy/extdbg/)\n\n[![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=102)](https://github.com/ellerbrock/open-source-badge/)\n\n[![forthebadge](http://forthebadge.com/images/badges/makes-people-smile.svg)](https://github.com/duboviy/extdbg/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduboviy%2Fextdbg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fduboviy%2Fextdbg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduboviy%2Fextdbg/lists"}