All Projects → ewjoachim → raincoat

ewjoachim / raincoat

Licence: MIT license
Raincoat has you covered when you can't stay DRY

Programming Languages

python
139335 projects - #7 most used programming language

Projects that are alternatives of or similar to raincoat

nano-staged
Tiny tool to run commands for modified, staged, and committed files in a GIT repository.
Stars: ✭ 347 (+1185.19%)
Mutual labels:  diff, linter
SublimeLinter-contrib-markdownlint
A Sublime Text Linter for Markdown/CommonMark files.
Stars: ✭ 29 (+7.41%)
Mutual labels:  linter
ncdu-diff
ncdu fork that can compare and diff results
Stars: ✭ 21 (-22.22%)
Mutual labels:  diff
diff-parser
A parser for unified diffs
Stars: ✭ 22 (-18.52%)
Mutual labels:  diff
rubocop-linter-action
Rubocop Linter Action: A GitHub Action to run Rubocop against your code!
Stars: ✭ 86 (+218.52%)
Mutual labels:  linter
lint-sass-vue
Atom linter for Vue.js
Stars: ✭ 19 (-29.63%)
Mutual labels:  linter
unindent
Report code that is unnecessarily indented
Stars: ✭ 18 (-33.33%)
Mutual labels:  linter
TSLint.MSBuild
[Deprecated] An MSBuild task for running TSLint.
Stars: ✭ 13 (-51.85%)
Mutual labels:  linter
BusinessCentral.LinterCop
Community driven code linter for AL (MS Dynamics 365 Business Central)
Stars: ✭ 29 (+7.41%)
Mutual labels:  linter
wd
Comparing strings on a word per word basis and generating a coloured diff. This repository has migrated to https://gitlab.com/opennota/wd
Stars: ✭ 16 (-40.74%)
Mutual labels:  diff
branch-name-lint
Lint your branch names
Stars: ✭ 60 (+122.22%)
Mutual labels:  linter
jQuery-Merge-for-php-diff
A client side merge tool for JBlonds PHP-Diff @ https://github.com/JBlond/php-diff.
Stars: ✭ 74 (+174.07%)
Mutual labels:  diff
solid
Solid Android components
Stars: ✭ 33 (+22.22%)
Mutual labels:  dry
eaf-linter
🤪 A linter, prettier, and test suite that does everything as-simple-as-possible.
Stars: ✭ 17 (-37.04%)
Mutual labels:  linter
Compare-UserJS
PowerShell script for comparing user.js (or prefs.js) files.
Stars: ✭ 79 (+192.59%)
Mutual labels:  diff
got
An enjoyable golang test framework.
Stars: ✭ 234 (+766.67%)
Mutual labels:  diff
SublimePapyrus
A Sublime Text 2 and 3 package for the Papyrus scripting language.
Stars: ✭ 44 (+62.96%)
Mutual labels:  linter
go-fastly-cli
CLI tool for interacting with Fastly CDN services via official REST API.
Stars: ✭ 14 (-48.15%)
Mutual labels:  diff
litho-lint-rules
Lint rules for Litho by Facebook http://fblitho.com/
Stars: ✭ 14 (-48.15%)
Mutual labels:  linter
vscode-stylelint-plus
A Visual Studio Code extension to lint CSS/SCSS/Less with stylelint, support auto fix on save.
Stars: ✭ 32 (+18.52%)
Mutual labels:  linter

Raincoat

Deployed to PyPI Documentation Status Continuous Integration Status Coverage Status MIT License Contributor Covenant

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 problem

Let's 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 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 call time.sleep in your app. Or do something else with the umbrella when 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 solution

Enter Raincoat.

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, install and run raincoat in your project:

$ pip install raincoat
$ raincoat

It will:

Grep the code for all # Raincoat: comments and for each comment:

  1. Look at the currently installed version of the lib (say, umbrella 16.0.3) (or, if not found, the latest version)
  2. Compare with the version in the Raincoat comment (here, 14.5.7)
  3. 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)
  4. Locate the code using the provided path for both the downloaded and the currently installed versions
  5. Diff it
  6. Tell 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 above
  • Django: 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: #26976
  • PyGitHub: 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 element Maildir._lookup in the file Lib/mailbox.py changed 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._lookup

You can also create your own Raincoat comment checker.

You can head to the Quickstart section for a general tour or to the How-To sections for specific features. The Discussions section should hopefully answer your questions. Otherwise, feel free to open an issue.

Where to go from here

The complete docs is 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 a ticket.

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].