Package: pyflyby
Pyflyby is a set of Python programming productivity tools for Python 3.7+.For command-line interaction:py: command-line multitoolFor IPython interaction:autoimporter: automatically imports symbols when needed.For editing python source code:tidy-imports: adds missing ‘import’s, removes unused ‘import’s,
and also reformats import blocks.find-import: prints to stdout how to import a particular symbol.reformat-imports: reformatsimportblockscollect-imports: prints out all the imports in a given set of files.collect-exports: prints out definitions in a given set of modules,
in the form of import statements.transform-imports: renames imported modules/functions.Installation$pipinstallpyflybyThis creates an alias for youripythonnamedpywhich runs thepyflybyplug internally.pyflybyhas a dependency onipython, if it isn’t already installed do install it with:$pipinstallipythonQuick start: Autoimporter + IPython$pyIn[1]:re.search("[a-z]+","....hello...").group(0)[PYFLYBY]importreOut[1]:'hello'In[2]:chisqprob(arange(5),2)[PYFLYBY]fromnumpyimportarange[PYFLYBY]fromscipy.statsimportchisqprobOut[2]:[1.0.60650.36790.22310.1353]To load pyflyby into an existing IPython session as a 1-off:$ipythonIn[1]:%load_extpyflybyTo configure IPython/Jupyter Notebook to load pyflyby automatically:$pypyflyby.install_in_ipython_config_fileor$echo'c.InteractiveShellApp.extensions.append("pyflyby")'\>>~/.ipython/profile_default/ipython_config.py$ipythonIn[1]:b64decode('aGVsbG8=')[PYFLYBY]frombase64importb64decodeOut[1]:'hello'Quick start:pycommand-line multi-tool$pyb64decodeaGVsbG8=[PYFLYBY]frombase64importb64decode[PYFLYBY]b64decode('aGVsbG8=',altchars=None)'hello'$pylog2sys.maxint[PYFLYBY]fromnumpyimportlog2[PYFLYBY]importsys[PYFLYBY]log2(9223372036854775807)63.0$py'plot(cos(arange(30)))'[PYFLYBY]fromnumpyimportarange[PYFLYBY]fromnumpyimportcos[PYFLYBY]frommatplotlib.pyplotimportplot[PYFLYBY]plot(cos(arange(30)))<plot>$py38497631/139514462.7594007818257693$pyfoo.pyQuick start:tidy-importsTo usetidy-imports, just specify the filename(s) to tidy.For example:$ echo 're.search("[a-z]+", "....hello..."), chisqprob(arange(5), 2)' > foo.py

$ tidy-imports foo.py
--- /tmp/foo.py
+++ /tmp/foo.py
@@ -1 +1,9 @@
+from __future__ import absolute_import, division, with_statement
+
+from   numpy                    import arange
+from   scipy.stats              import chisqprob
+import re
+
 re.search("[a-z]+", "....hello..."), chisqprob(arange(5), 2)

Replace /tmp/foo.py? [y/N]Quick start: import librariesCreate a file named .pyflyby with lines such asfrommypackage.mymoduleimportMyClass,my_functionimportanotherpackage.anothermoduleYou can put this file in your home directory or in the same directory as your*.pyfiles.Details: automatic importsAUTOMATIC IMPORTS - never type “import” again!This module allows your “known imports” to work automatically in your IPython
interactive session without having to type the ‘import’ statements (and also
without having to slow down your Python startup with imports you only use
occasionally).Example:In [1]: re.search("[a-z]+", "....hello...").group(0)
[PYFLYBY] import re
Out[1]: 'hello'

In [2]: chisqprob(arange(5), 2)
[PYFLYBY] from numpy import arange
[PYFLYBY] from scipy.stats import chisqprob
Out[2]: [ 1.      0.6065  0.3679  0.2231  0.1353]

In [3]: np.sin(arandom(5))
[PYFLYBY] from numpy.random import random as arandom
[PYFLYBY] import numpy as np
Out[3]: [ 0.0282  0.0603  0.4653  0.8371  0.3347]

In [4]: isinstance(42, Number)
[PYFLYBY] from numbers import Number
Out[4]: TrueIt just worksTab completion works, even on modules that are not yet imported.  In the
following example, notice that numpy is imported when we need to know its
members, and only then:$ ipython
In [1]: nump<TAB>
In [1]: numpy
In [1]: numpy.arang<TAB>
[PYFLYBY] import numpy
In [1]: numpy.arangeThe IPython “?” magic help (pinfo/pinfo2) automatically imports symbols first
if necessary:$ ipython
In [1]: arange?
[PYFLYBY] from numpy import arange
... Docstring: arange([start,] stop[, step,], dtype=None) ...Other IPython magic commands work as well:$ ipython
In [1]: %timeit np.cos(pi)
[PYFLYBY] import numpy as np
[PYFLYBY] from numpy import pi
100000 loops, best of 3: 2.51 us per loop

$ echo 'print arange(4)' > foo.py
$ ipython
In [1]: %run foo.py
[PYFLYBY] from numpy import arange
[0 1 2 3]Implementation detailsThe automatic importing happens at parse time, before code is executed.  The
namespace never contains entries for names that are not yet imported.This method of importing at parse time contrasts with previous implementations
of automatic importing that use proxy objects.  Those implementations using
proxy objects don’t work as well, because it is impossible to make proxy
objects behave perfectly.  For example, instance(x, T) will return the wrong
answer if either x or T is a proxy object.CompatibilityTested with:Python 3.8, 3.9, 3.10IPython 0.10, 0.11, 0.12, 0.13, 1.0, 1.2, 2.0, 2.1, 2.2, 2.3, 2.4, 3.0,
3.1, 3.2, 4.0., 7.11 (latest)IPython (text console), IPython Notebook, SpyderDetails: import librariesPyflyby uses “import libraries” that tell how to import a given symbol.An import library file is simply a python source file containing ‘import’ (or
‘from … import …’) lines.  These can be generated automatically withcollect-importsandcollect-exports.Known importsFind-imports,tidy-imports, and autoimport consult the database of known
imports to figure out where to get an import.  For example, if the
imports database contains:from numpy import arange, NaNthen when you type the following in IPython:print(arange(10))the autoimporter would automatically executefrom numpy import arange.The database can be one file or multiple files.  This makes it easy to have
project-specific known_imports along with global and per-user defaults.ThePYFLYBY_PATHenvironment variable specifies which files to read.
This is a colon-separated list of filenames or directory names.  The default
is:PYFLYBY_PATH=/etc/pyflyby:~/.pyflyby:.../.pyflybyIf you set:PYFLYBY_PATH=/foo1/bar1:/foo2/bar2then this replaces the default.You can use a hyphen to include the default in the path.  If you set:PYFLYBY_PATH=/foo1/bar1:-:/foo2/bar2then this reads/foo1/bar1, then the default locations, then/foo2/bar2.In$PYFLYBY_PATH,.../.pyflyby(with _three_ dots) means that all ancestor
directories are searched for a member named “.pyflyby”.For example, suppose the following files exist:/etc/pyflyby/stuff.py
/u/quarl/.pyflyby/blah1.py
/u/quarl/.pyflyby/more/blah2.py
/proj/share/mypythonstuff/.pyflyby
/proj/share/mypythonstuff/foo/bar/.pyflyby/baz.py
/.pyflybyFurther, suppose:/projis on a separate file system from/.$HOME=/u/quarlThentidy-imports/proj/share/mypythonstuff/foo/bar/quux/zot.pywill by
default use the following:/etc/pyflyby/stuff.py
/u/quarl/.pyflyby/blah1.py
/u/quarl/.pyflyby/more/blah2.py
/proj/share/mypythonstuff/foo/bar/.pyflyby/baz.py
/proj/share/mypythonstuff/.pyflyby (a file)Note/.pyflybyis not included, because traversal stops at file system
boundaries, and in this example,/projis on a different file system than/..pyflyby(in$HOMEor near the target file) can be a file or a directory.
If it is a directory, then it is recursively searched for*.pyfiles.The order usually doesn’t matter, but if there are “forget” instructions
(see below), then the order matters.  In the default$PYFLYBY_PATH,
…/.pyflyby is placed last so that per-directory configuration can
override per-user configuration, which can override systemwide
configuration.Forgetting importsOccasionally you may have reason to tell pyflyby to “forget” entries from the
database of known imports.You can put the following in any file reachable from$PYFLYBY_PATH:__forget_imports__ = ["from numpy import NaN"]This is useful if you want to use a set of imports maintained by someone else
except for a few particular imports.Entries in$PYFLYBY_PATHare processed left-to-right in the order specified,
so put the files containing these at the end of your$PYFLYBY_PATH.  By
default,tidy-importsand friends process/etc/pyflyby, then~/.pyflyby,
then the per-directory.pyflyby.Mandatory importsWithin a certain project you may have a policy to always include certain
imports.  For example, maybe you always want to dofrom __future__ import divisionin all files.You can put the following in any file reachable from$PYFLYBY_PATH:__mandatory_imports__ = ["from __future__ import division"]To undo mandatory imports inherited from other.pyflybyfiles, use__forget_imports__(see above).Canonicalize importsSometimes you want every run oftidy-importsto automatically rename an import
to a new name.You can put the following in any file reachable from$PYFLYBY_PATH:__canonical_imports__ = {"oldmodule.oldfunction": "newmodule.newfunction"}This is equivalent to running:tidy-imports --transform=oldmodule.oldfunction=newmodule.newfunctionSoapbox: avoid “star” importsWhen programming in Python, a good software engineering practice is to avoid
usingfrom foopackage import *in production code.This style is a maintenance nightmare:It becomes difficult to figure out where various symbols
(functions/classes/etc) come from.It’s hard to tell what gets shadowed by what.When the package changes in trivial ways, your code will be affected.
Consider the following example: Supposefoopackage.pycontainsimport sys, andmyprogram.pycontainsfrom foopackage import *; if some_condition: sys.exit(0).  Iffoopackage.pychanges so thatimport sysis removed,myprogram.pyis now broken because it’s missingimport sys.To fix such code, you can runtidy-imports--replace-star-importsto
automatically replace star imports with the specific needed imports.Per-Project configuration of tidy-importsYou can configure Pyflyby on a per-repository basis by using the[tool.pyflyby]section ofpyproject.tomlfiles. Pyflyby will look in current
working directory and all it’s parent until it find apyproject.tomlfile from
which it will load the defaults.Most of the long command line flags default values can be configured in this
section. Simply use the long form option name by replacing dashes-by
underscore_. For long option that have the form–xxxand–no-xxx, you
can assign a boolean toxxx. For example:[tool.pyflyby]
add_missing=true
from_spaces=7
remove_unused=falseEmacs supportTo get aM-xtidy-importscommand in GNU Emacs, add to your~/.emacs:(load "/path/to/pyflyby/lib/emacs/pyflyby.el")Pyflyby.el doesn’t yet work with XEmacs; patches welcome.AuthorshipThis plugin was contributed back to the community by theD. E. Shaw group.Pyflyby is written by Karl Chen <quarl@8166.clguba.z.quarl.org>We love contributions! Before you can contribute, please sign and submit thisContributor License Agreement (CLA).
This CLA is in place to protect all users of this project.LicensePyflyby is released under a very permissive license, the MIT/X11 license; see
LICENSE.txt.ReleaseCheck version number inlib/python/pyflyby/_version.py, maybe increase it.Commit and tag if necessary, and push tags/commits.Optional: Set SOURCE_DATE_EPOCH for reproducible build:export SOURCE_DATE_EPOCH=$(git show -s --format=%ct HEAD)Build the SDIST:python setup.py sdistOptional Repack the Sdist to make sure the ZIP only contain SOURCE_DATE_EPOCH
date using IPython tools:python ~/dev/ipython/tools/retar.py dist/pyflyby-1.7.8.tar.gz
shasum -a 256 dist/*Optional, redo 4 & 5 to verify checksum is unchanged.Upload using twine:twine upload dist/*Check/updatehttps://github.com/conda-forge/pyflyby-feedstockfor new pyflyby
release on conda-forge