All Projects → lonetwin → Pythonrc

lonetwin / Pythonrc

Licence: mit
lonetwin's pimped-up pythonrc

Programming Languages

python
139335 projects - #7 most used programming language

Labels

Projects that are alternatives of or similar to Pythonrc

Dotfiles
👾 ~/
Stars: ✭ 91 (-14.95%)
Mutual labels:  dotfiles
Dotfiles
Awesome personal dotfiles
Stars: ✭ 99 (-7.48%)
Mutual labels:  dotfiles
Dotfiles
This is a mirror from https://gitlab.com/andreyorst/dotfiles
Stars: ✭ 103 (-3.74%)
Mutual labels:  dotfiles
Dotfiles
🤘 My collection of dotfiles for tmux, vim and zsh
Stars: ✭ 94 (-12.15%)
Mutual labels:  dotfiles
Vim Config Framework
📗 VIM / Neovim configuration framework
Stars: ✭ 97 (-9.35%)
Mutual labels:  dotfiles
Beemo
🤖 Centralized configuration layer for dev tools. Beep boop.
Stars: ✭ 100 (-6.54%)
Mutual labels:  dotfiles
Dotfiles
My configuration files
Stars: ✭ 89 (-16.82%)
Mutual labels:  dotfiles
Emplace
👩‍❤️‍💋‍👩 Synchronize installed packages on multiple machines
Stars: ✭ 105 (-1.87%)
Mutual labels:  dotfiles
Dotfiles
My dotfiles managed by GNU Stow - Arch, i3-gaps, bspwm, ncmpcpp, (neo)vim, zsh etc.
Stars: ✭ 99 (-7.48%)
Mutual labels:  dotfiles
.dot Config
📚 Example dot configs for tmux, tmuxp, vim, vcspull, i3 and awesome
Stars: ✭ 102 (-4.67%)
Mutual labels:  dotfiles
Fish Utils
🔧 My utility belt of fish functions, writing these has saved me many hours in the long run... I hope...
Stars: ✭ 94 (-12.15%)
Mutual labels:  dotfiles
Mac Bootstrap
💻 Provision a new Mac for web development with dotfiles + Fish/Zsh, Neovim, and Tmux
Stars: ✭ 96 (-10.28%)
Mutual labels:  dotfiles
My dotfiles
Just a collections of my dotfiles...
Stars: ✭ 101 (-5.61%)
Mutual labels:  dotfiles
System
My system configuration
Stars: ✭ 94 (-12.15%)
Mutual labels:  dotfiles
Dogfiles
dog + dotfiles = dogfiles
Stars: ✭ 104 (-2.8%)
Mutual labels:  dotfiles
Dots
just dotfiles ¯\_(ツ)_/¯
Stars: ✭ 90 (-15.89%)
Mutual labels:  dotfiles
Dots
A Repository For Config Files / Dotfiles / Themes / Color Schemes / Etc...
Stars: ✭ 100 (-6.54%)
Mutual labels:  dotfiles
Dotfiles
My personal collection of configuration files.
Stars: ✭ 105 (-1.87%)
Mutual labels:  dotfiles
Home
🏡 $HOME directory (dot files & bin scripts)
Stars: ✭ 103 (-3.74%)
Mutual labels:  dotfiles
Dotfiles
My dotfiles and themes.
Stars: ✭ 101 (-5.61%)
Mutual labels:  dotfiles

============================= lonetwin's pimped-up pythonrc

What is this ?

This is a python script intended to improve on the default Python interactive shell experience.

Unlike ipython_, bpython_ or any of the many other options out there, this is not designed to be used as a separate interactive environment. The intent is to keep it as a single file and use it as any other rcfile. This script relies solely on the standard python library and will always remain that way.


.. note::

This branch targets **python-3.8+**. If you wish to use/try this out with an
earlier version of python please use the `support/2.x`_ branch. Any new
development will be done on this version but I'm happy to fix any reported
bugs on the `support/2.x`_ branch.

.. _support/2.x: https://github.com/lonetwin/pythonrc/tree/support/py2.x


Demo

|demo|

Usage

The pythonrc file will be executed when the Python interactive shell is started, if $PYTHONSTARTUP is in your environment and points to the file.

You could also simply make the file executable and call it directly.

Additionally, this file will in turn, execute a virtual env specific rc file [#]_ if it exists, for the current session, enabling you to pre-populate sessions specific to virtual environments.

Features

The file creates an InteractiveConsole_ instance and executes it. This instance provides:

  • execution history

  • colored prompts and pretty printing

  • auto-indentation

  • intelligent tab completion [#]_

    • without preceding text four spaces

    • with preceding text

      • names in the current namespace
      • for objects, their attributes/methods
      • for strings with a /, pathname completion
      • module name completion in an import statement
  • edit the session or a file in your $EDITOR (the \e command)

    • with no arguments, opens your $EDITOR with the session hstory
    • with filename argument, opens the file in your $EDITOR
    • with object as an argument, opens the source code for the object in $EDITOR
  • list the source code for objects when available (the \l command)

  • temporary escape to $SHELL or ability to execute a shell command and capturing the output in to the _ variable (the ! command)

  • convenient printing of doc stings (the ? command) and search for entries in online docs (the ?? command)

  • auto-execution of a virtual env specific (.venv_rc.py) file at startup

If you have any other good ideas please feel free to submit pull requests or issues. There's an section below which shows you how to add new commands.

Configuration

The code attempts to be easy to read and modify to suit personal preferences. You can change any of the commands or the options like the path to the history file, its size etc in the config dict at the top of the rc file. For instance, if you prefer to set the default edit command to %edit instead of the default \e, you just have to change the entry in the config dict.

Note that, the init_readline() method also reads your .inputrc file if it exists. This allows you to share the same readline behavior as all other tools that use readline. For instance, in my personal ~/.inputrc I have the following::

# - when performing completion in the middle of a word, do not insert characters
# from the completion that match characters after point in the word being
# completed
set skip-completed-text on

# - displays possible completions using different colors according to file type.
set colored-stats on

# - show completed prefix in a different color
set colored-completion-prefix on

# - jump temporarily to matching open parenthesis
set blink-matching-paren on

set expand-tilde on
set history-size -1
set history-preserve-point on

"\e[A": history-search-backward
"\e[B": history-search-forward

Adding new commands

It is relatively simple to add new commands to the ImprovedConsole class:

  1. Add the string that would invoke your new command to the config dict.
  2. Create a method in the ImprovedConsole class which receives a string argument and returns either a string that can be evaluated as a python expression or None. The method may do anything it fancies.
  3. Add an entry mapping the command to the method in the commands dict.

That's all !

The way commands work is, the text entered at the prompt is examined against the commands_re regular expression. This regular expression is simply the grouping of all valid commands, obtained from the keys of the commands dict.

If a match is found the corresponding function from the commands dict is called with the rest of the text following the command provided as the argument to the function.

You may choose to resolve this string argument to an object in the session namespace by using the helper function lookup().

Whatever text is returned by the function is then passed on for further evaluation by the python interpreter.

Various helper functions exist like all the globally defined color functions (initialized by the init_colors method), the _doc_to_usage decorator, _mktemp_buffer and _exec_from_file whose intent ought to be hopefully obvious.

Here's a complete example demonstrating the idea, by specifying a new command \s which prints the size of the specified object or of all objects in the current namespace.

::

config = dict(
    ...
    SIZE_OF = '\s',
)
...

class ImprovedConsole(...)
    ...

    def __init__(...):
       ...
       self.commands = {
           ...
           config['SIZE_OF']: self.print_sizeof,
           ...
       }
    ...


    @_doc_to_usage
    def print_sizeof(self, arg=''):
        """{SIZE_OF} <object>

        Print the size of specified object or of all objects in current
        namespace
        """
        if arg:
            obj = self.lookup(arg)
            if obj:
                return print(sys.getsizeof(obj))
            else:
                return self.print_sizeof('-h')
        print({k: sys.getsizeof(v) for k, v in self.locals.items()})

A little history

Ever since around 2005_, I've been obsessed with tweaking my python interactive console to have it behave the way I prefer. Despite multiple attempts I've failed to embrace ipython on the command line because some of ipython's approach just don't fit my head. Additionally, ipython is a full environment and I just need some conveniences added to the default environment. This is why I started maintaining my own pythonrc. I started eventually sharing it as a gist_ back in 2014 and now about 38 revisions later, I think it might just make sense to set it up as a project so that I can accept pull requests, bug reports or suggestions in case somebody bothers to use it and contribute back.

Known Issue

The console is not __main__. The issue was first reported by @deeenes in the gist_ I used to maintain. In essence, this code fails::

>>> import timeit
>>>
>>> def getExecutionTime():
...     t = timeit.Timer("sayHello()", "from __main__ import sayHello")
...     return t.timeit(2)
...
>>> def sayHello():
...     print("Hello")
...
>>> print(getExecutionTime())
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "<console>", line 3, in getExecutionTime
  File "/usr/lib64/python2.7/timeit.py", line 202, in timeit
    timing = self.inner(it, self.timer)
  File "<timeit-src>", line 3, in inner
ImportError: cannot import name sayHello
>>>

There are two possible workarounds for this:

  • When within the console, if you have to reference local names via __main__, remember to do it via __main__.pymp.locals instead, something like (for the example above)::

    ...
    def getExecutionTime():
        t = timeit.Timer("sayHello()", "from __main__ import pymp; sayHello = pymp.locals['sayHello']")
    ...
    
  • Or in the pythonrc file, change the initialization of ImprovedConsole to accept locals(). That is something like this::

    pymp = ImprovedConsole(locals=locals())
    

    Although the downside of this is, doing it will pollute your console namespace with everything in the pythonrc file.

.. [#] Named .venv_rc.py by default, but like almost everything else, is configurable .. [#] Since python 3.4 the default interpreter also has tab completion enabled however it does not do pathname completion .. _ipython: https://ipython.org/ .. _bpython: https://bpython-interpreter.org/ .. _InteractiveConsole: https://docs.python.org/3.6/library/code.html#code.InteractiveConsole .. _2005: http://code.activestate.com/recipes/438813/ .. _gist: https://gist.github.com/lonetwin/5902720 .. |demo| image:: https://asciinema.org/a/134711.png :target: https://asciinema.org/a/134711?speed=2

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].