Raincoat has your code covered when you can't stay DRY.
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.
Lets say you’re using a lib named umbrella which provides a function named use_umbrella and it reads as such :
def use_umbrella(umbrella): # Prepare umbrella umbrella.remove_pouch() umbrella.open() # Use umbrella while rain_detector.still_raining(): umbrella.keep_over_me() # Put umbrella away umbrella.close() while not umbrella.is_wet(): time.sleep(1) umbrella.put_pouch()
This function does what it says it does, but it’s not ideally splitted, 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 call time.sleep in your app. Or do something else with the umbrella when it’s open 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 personnal reason. So what do you do ? There’s no real alternative. You copy and 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.
You have made your own private copy of umbrella.use_umbrella (umbrella being at the time at version 14.5.7) and it looks like this :
def dance_with_umbrella(umbrella): """ I'm siiiiiinging in the rain ! """ # Prepare umbrella umbrella.remove_pouch() umbrella.open() # Use umbrella while rain_detector.still_raining(): Dancer.sing_in_the_rain(umbrella) # Put umbrella away umbrella.close() while not umbrella.is_wet() time.sleep(1) umbrella.put_pouch()
Now simply add a comment somewhere (preferably just after the docstring) that says something like:
def dance_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, if you run raincoat in your project (At this stage, I assume you’ve installed it with pip install raincoat)
# Raincoat:comments and for each 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…
Note that if you omit the last argument, Raincoat will analyze the whole module:
# Raincoat: pypi package: umbrella==16.0.3 path: umbrella/__init__.py
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:
# Raincoat: django ticket: #26976
# Raincoat: pygithub repo: python/cpython@43ba8861 branch: master path: Lib/mailbox.py element: Maildir._lookup
Of course, feel free to code your own !
Things I’d like to add at some point
This code is open-sourced and maintained by me (Joachim Jablon) during both my free time and my time working at PeopleDoc, based on an idea and a first implemention made at Smart Impulse. Kudos to these 2 companies.
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
|File Name & Checksum SHA256 Checksum Help||Version||File Type||Upload Date|
|raincoat-0.8.2-py2.py3-none-any.whl (23.2 kB) Copy SHA256 Checksum SHA256||3.5||Wheel||Jul 4, 2017|
|raincoat-0.8.2.tar.gz (16.8 kB) Copy SHA256 Checksum SHA256||–||Source||Jul 4, 2017|