Package: raincoat
Raincoat has you covered when you can’t stay DRY. When the time comes where you HAVE to
copy code from a third party, Raincoat will let you know when this code is changed so
that you can update your local copy.The problemLet’s say you’re using a lib namedumbrellawhich provides a function nameduse_umbrellaand it reads as such:defuse_umbrella(umbrella):# Prepare umbrellaumbrella.remove_pouch()umbrella.open()# Use umbrellawhilerain_detector.still_raining():umbrella.keep_over_me()# Put umbrella awayumbrella.close()whilenotumbrella.is_wet():time.sleep(1)umbrella.put_pouch()This function does what it says it does, but it’s not ideally split, depending on
your needs. For example, maybe at some point you realize you need each of the 3 separate
parts to be a function of its own. Or maybe you can’t calltime.sleepin your app. Or do
something else with theumbrellawhen it’s opened, like dance with it.It’s also possible that you can’t really make a pull request because your needs are
specific, or you don’t have the time (that’s sad but, hey, I know it happens) or any
other personal reason. So what do you do? There’s no real alternative. You copy/paste
the code, modify it to fit your needs and use your modified version. And whenever
there’s a change to the upstream function, chances are you’ll never know.The solutionEnter Raincoat.You have made your own private copy ofumbrella.use_umbrella(umbrella being at the
time at version 14.5.7) and it looks like this:defdance_with_umbrella(umbrella):"""
    I'm siiiiiinging in the rain!
    """# Prepare umbrellaumbrella.remove_pouch()umbrella.open()# Use umbrellawhilerain_detector.still_raining():Dancer.sing_in_the_rain(umbrella)# Put umbrella awayumbrella.close()whilenotumbrella.is_wet()time.sleep(1)umbrella.put_pouch()Now simply add a comment somewhere (preferably just after the docstring) that says
something like:defdance_with_umbrella(umbrella):"""
    I'm siiiiiinging in the rain!
    """# This code was adapted from the original umbrella.use_umbrella function# (we just changed the part inside the middle while loop)# Raincoat: pypi package: umbrella==14.5.7 path: umbrella/__init__.py element: use_umbrella...Now, install and runraincoatin your project:$pipinstallraincoat$raincoatIt will:Grep the code for all# Raincoat:comments and for each comment:Look at the currently installed version of the lib (say, umbrella 16.0.3) (or, if not
found, the latest version)Compare with the version in the Raincoat comment (here, 14.5.7)If they are different, download and pip install the specified version in a temp dir
(using cached wheel as pip does by default, this should be quite fast in most cases)Locate the code using the provided path for both the downloaded and the currently
installed versionsDiff itTell you if there’s a difference (and mention the location of the original Raincoat
comment)Whether there is something to change or not, you’ve now verified your code with umbrella
16.0.3, so you can update manually the umbrella comment.# Raincoat: pypi package: umbrella==16.0.3 path: umbrella/__init__.py element: use_umbrella"Raincoat can be used like a linter, you can integrate it in CI, make it a tox target…And beyond!Actually, the base principle of Raincoat can be extended to many other subjects than
PyPI packages. To fit this, Raincoat was written with a modular achitecture allowing
other kinds of Raincoat comments.For now Raincoat comes with:PyPI: The module presented aboveDjango: A module that checks if a given bug in Django for which you may have had
to write a workaround is fixed in your (or the latest) version of Django. Syntax is :# Raincoat: django ticket: #26976PyGitHub: Same as the PyPI module but using Github. It’s useful if your upstream is
a python package that’s not on PyPI, like, say, the Python Standard Library itself.
Say you want to know if the elementMaildir._lookupin the fileLib/mailbox.pychanged on the master branch since commit 43ba8861. What you can do is:# Raincoat: pygithub repo: python/cpython@43ba8861 branch: master path: Lib/mailbox.py element: Maildir._lookupYou can also create your own Raincoat comment checker.You can head to theQuickstartsection for a general tour
or to theHow-Tosections for specific features. TheDiscussionssection should hopefully
answer your questions. Otherwise, feel free to open anissue.Where to go from hereThe completedocsis probably the best place to learn about the project.If you encounter a bug, or want to get in touch, you’re always welcome to open aticket.