├── HISTORY.markdown ├── README.markdown ├── UNLICENSE ├── debug.py ├── manual_test.py ├── manual_test_directory ├── __init__.py └── debug.py └── setup.py /HISTORY.markdown: -------------------------------------------------------------------------------- 1 | import debug history 2 | ==================== 3 | 4 | This file only covers changes important for the end-user. Visit GitHub 5 | for [full history][]. 6 | 7 | [full history]: https://github.com/narfdotpl/debug/commits/master 8 | 9 | 10 | [v0.3.2][] 11 | ---------- 12 | 13 | - Fixed a bug where `from .debug import foo` was broken. 14 | Thanks to @qarkai! 15 | 16 | 17 | [v0.3.1][] 18 | ---------- 19 | 20 | - Lowered ipdb requirement to the highest released version (#6). 21 | 22 | 23 | [v0.3][] 24 | -------- 25 | 26 | - Updated for Python 3 (#5). 27 | 28 | 29 | [v0.2.1][] 30 | ---------- 31 | 32 | - Allowed newer versions of ipdb (#4). 33 | 34 | 35 | [v0.2][] 36 | -------- 37 | 38 | - Added support for multiple entry points (#2). 39 | 40 | - Added support for [IPython][] 0.11 by relying on [ipdb][] (#1, #3). 41 | 42 | [IPython]: http://ipython.org/ 43 | [ipdb]: https://github.com/gotcha/ipdb 44 | 45 | 46 | [v0.1][] 47 | -------- 48 | 49 | - Initial release. 50 | 51 | 52 | [v0.3.2]: https://github.com/narfdotpl/debug/compare/v0.3.1...v0.3.2 53 | [v0.3.1]: https://github.com/narfdotpl/debug/compare/v0.3.0...v0.3.1 54 | [v0.3]: https://github.com/narfdotpl/debug/compare/v0.2.1...v0.3.0 55 | [v0.2.1]: https://github.com/narfdotpl/debug/compare/v0.2.0...v0.2.1 56 | [v0.2]: https://github.com/narfdotpl/debug/compare/v0.1.0...v0.2.0 57 | [v0.1]: https://github.com/narfdotpl/debug/compare/9fd90f8...v0.1.0 58 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | import debug 2 | ============ 3 | 4 | Start fancy debugger in a single statement. 5 | 6 | People debug with `print`. It's great in simple cases. Another 7 | debugging tool, [pdb][], is less popular as it requires more effort: one 8 | has to do a Google search, skim through documentation, type some long 9 | "trace... sth", and all of this only to get some unfriendly two-color 10 | shell that doesn't even seem to understand how tab key should work. 11 | 12 | [pdb]: http://docs.python.org/library/pdb.html 13 | 14 | This project FTFY: you `import debug` and you find yourself in a 15 | debugger with syntax highlighting, tab completion, and readable `dir()` 16 | alternative. From there you can pretend you're just using interactive 17 | console -- you don't have to know any `pdb` commands, just remember that 18 | "c" closes debugger and goes back to your program. 19 | 20 | (What really happens is that we simply start [ipdb][] and import [see][] 21 | for you.) 22 | 23 | [ipdb]: https://github.com/gotcha/ipdb 24 | [see]: http://inky.github.com/see/ 25 | 26 | 27 | Usage 28 | ----- 29 | 30 | Put `import debug` right where you want to start debugging (it's like 31 | [antigravity][]). 32 | 33 | Thanks to some monkeys and some patches, it will work as many times as 34 | you need it to. 35 | 36 | [antigravity]: http://xkcd.com/353/ 37 | 38 | 39 | Installation 40 | ------------ 41 | 42 | pip install debug 43 | 44 | 45 | Meta 46 | ---- 47 | 48 | This little piece of glue code is written by [Maciej Konieczny][]. It's 49 | released into the [public domain][] and uses [semantic versioning][] for 50 | release numbering. 51 | 52 | [Maciej Konieczny]: http://narf.pl/ 53 | [public domain]: http://unlicense.org/ 54 | [semantic versioning]: http://semver.org/ 55 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /debug.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | """ 4 | import debug: https://github.com/narfdotpl/debug 5 | """ 6 | 7 | try: 8 | import __builtin__ 9 | except ImportError: 10 | # Python 3.x 11 | import builtins as __builtin__ 12 | from sys import _getframe 13 | 14 | from ipdb import set_trace 15 | 16 | 17 | # do not forget 18 | old_import = __builtin__.__import__ 19 | 20 | def debug(): 21 | # get frame 22 | frame = _getframe(2) 23 | 24 | # inject see (`from see import see`) 25 | ns = frame.f_globals 26 | if 'see' not in ns: 27 | ns['see'] = old_import('see', fromlist=['see']).see 28 | 29 | # start ipdb 30 | set_trace(frame) 31 | 32 | # run on first import 33 | debug() 34 | 35 | # monkeypatch `import` so `import debug` will work every time 36 | def new_import(*args, **kwargs): 37 | # don't touch non-debug imports 38 | name = args[0] 39 | if name != 'debug': 40 | return old_import(*args, **kwargs) 41 | 42 | # Make sure that the name "debug" refers to *this* module, 43 | # i.e. that the import is `import debug` and not for example 44 | # `from .debug import foo`. 45 | # 46 | # To check this I have to look at the value of the `level` 47 | # argument. It's the last argument and it has a default value. 48 | # I don't want to add it to the signature of `new_import` because 49 | # `__import__` is different in Python 2 and 3: 50 | # 51 | # __import__(name, globals={}, locals={}, fromlist=[], level=-1) 52 | # __import__(name, globals=None, locals=None, fromlist=(), level=0) 53 | # 54 | # I work around this by getting `level` from `kwargs` and `args`, 55 | # which works the same way in both Python versions. 56 | is_relative = False 57 | if 'level' in kwargs: 58 | is_relative = kwargs['level'] > 0 59 | elif len(args) == 5: 60 | is_relative = args[-1] > 0 61 | 62 | if is_relative: 63 | return old_import(*args, **kwargs) 64 | else: 65 | debug() 66 | 67 | __builtin__.__import__ = new_import 68 | -------------------------------------------------------------------------------- /manual_test.py: -------------------------------------------------------------------------------- 1 | print 1 2 | import debug 3 | print 2 4 | import debug 5 | print 3 6 | import manual_test_directory 7 | print 4 8 | -------------------------------------------------------------------------------- /manual_test_directory/__init__.py: -------------------------------------------------------------------------------- 1 | print 'manual_test_directory/__init__.py says hi' 2 | 3 | from .debug import x 4 | -------------------------------------------------------------------------------- /manual_test_directory/debug.py: -------------------------------------------------------------------------------- 1 | print 'manual_test_directory/debug.py says hi' 2 | 3 | x = 0 4 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | from distutils.core import setup 5 | 6 | 7 | setup( 8 | name='debug', 9 | version='0.3.2', 10 | description='Start fancy debugger in a single statement.', 11 | author='Maciej Konieczny', 12 | author_email='hello@narf.pl', 13 | url='https://github.com/narfdotpl/debug', 14 | py_modules=['debug'], 15 | install_requires=['ipdb >= 0.8', 'see >= 1.1'] 16 | ) 17 | --------------------------------------------------------------------------------