Package: slicker
Slicker: A Tool for Moving Things in PythonIf you've ever tried to move a function or class in python, you'll find it's
kind of a pain: you have to not only move the definition (and its imports,
etc.) but also update references across the codebase.  Slicker is a tool for
doing just that!Installationpip install slickerUsageTo move a functionmyfuncdefined infoo/bar.pytofoo/baz.py:slicker foo.bar.myfunc foo.baz.myfuncThe same syntax works ifmyfuncis instead a constant or class (although I
sure hope you didn't name a classmyfunc!).  It also works if you want to
change the name ofmyfunc:slicker foo.bar.myfunc foo.bar.new_name_for_myfunc(And you can also make both changes at once, in the natural way.)To move an entire modulefoo/bar.pytofoo/baz.pyyou can do similarly:slicker foo.bar foo.bazor use filenames like:slicker foo/bar.py foo/baz.pyYou can also move a symbol into an existing module, or a module into an
existing directory, just likemv.  So this is equivalent to the first
example:slicker foo.bar.myfunc foo.bazAnd to movefoo/bar.pyto a new filenewfoo/bar.pyin an existing directorynewfoo/, you could doslicker foo.bar newfoo  # (or slicker foo/bar.py newfoo/)Using this syntax, you can also specify multiple things to move, so you could
move bothfoo/bar.pyandfoo/baz.pytonewfoo/withslicker foo/bar.py foo/baz.py newfoo/You can tell slicker to use an alias when adding imports using-a/--alias:slicker foo.bar.myfunc foo.baz.myfunc --alias bazin which case slicker will addfrom foo import bazeverywhere instead ofimport foo.baz.  (You could also have used--alias foobazin which case
we would have doneimport foo.baz as foobaz.)If you prefer to move the actual definition yourself, and just have slicker
update the references, you can pass--no-automove.  It's probably best to runslickerafter doing said move.For a full list of options, runslicker --help.Frequently and Infrequently Asked QuestionsWhat does slicker mean if it says "This import may be used implicitly."?If you doimport foo.bar, and some other file (perhaps another one you
import) doesimport foo.baz, then yourfoonow also has afoo.baz, and so
you can dofoo.baz.func()with impunity, even though no import in your file
directly mentions that module.  (This is becausefooin both files refers to
the same object -- a.k.a.sys.modules['foo']-- and so when the other file
doesimport foo.bazit attachesbazto that shared object.)  So if you've
asked slicker to movefoo.bartonewfoo.bar, when updating this file, it
would like to replace theimport foo.barwithimport newfoo.bar, but it
can't -- you're actually still using the import.  So it will warn you of this
case, and let you sort things out by hand.Slicker left me with a bunch of misindented or long lines!Yep, we don't fix these correctly (yet).  Your linter should tell you what to
fix, though.Why is it called slicker?Because pythons slither to move around, but this way is, uh, slicker.  Which is
to say: it seemed like a good idea at the time and as far as I could tell the
name wasn't already taken.How does it work?See theblog postfor
an overview.  If that's not enough, bug the authors or read the source!Why don't you just usePyCharmorrope?Good question -- we tried!  Both are great projects and do a lot of things
slicker doesn't; if they work for you then definitely use them.  But for us,
they were a little buggy and didn't fit our workflow.  For more details, see
theblog post.Why don't you just usecodemodorsed/perl?Good question -- we tried!  But it takes a lot of gluing things together to
figure out all the right references to fix up in each file.  And there's
basically no hope of doing the right thing when fixing up string-references.
We needed something that knew what python imports mean and could handle their
special cases.Changelog0.9.2Fix description on PyPI, again0.9.2Fix description on PyPI0.9.1Handle relative imports correctlyLots of internal refactoring0.9Initial release to PyPI