Make reqsort its own thing
This commit is contained in:
parent
bcacdd70c1
commit
aef66f2e77
3 changed files with 11 additions and 0 deletions
projects/reqsort
7
projects/reqsort/BUILD
Normal file
7
projects/reqsort/BUILD
Normal file
|
@ -0,0 +1,7 @@
|
|||
py_binary(
|
||||
name = "reqsort",
|
||||
main = "__main__.py",
|
||||
deps = [
|
||||
py_requirement("click"),
|
||||
]
|
||||
)
|
3
projects/reqsort/README.md
Normal file
3
projects/reqsort/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# reqsort
|
||||
|
||||
A `requirements.txt` formatter and sorter.
|
73
projects/reqsort/__main__.py
Normal file
73
projects/reqsort/__main__.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
"""
|
||||
Platform independent sorting/formatting for requirements.txt
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
import click
|
||||
|
||||
|
||||
REQ_PATTERN = re.compile(
|
||||
r"(?P<pkgname>[a-zA-Z0-9_-]+)(?P<features>\[.*?\])?==(?P<version>[^\s;#]+)|(.*?#egg=(?P<eggname>[a-zA-Z0-9_-]+))"
|
||||
)
|
||||
|
||||
|
||||
SHITLIST = [
|
||||
"pip",
|
||||
"pkg-resources",
|
||||
"setuptools",
|
||||
]
|
||||
|
||||
|
||||
def sort_key(requirement: str) -> str:
|
||||
requirement = requirement.lower()
|
||||
match = re.match(REQ_PATTERN, requirement)
|
||||
sort_key = (
|
||||
(match.group("pkgname") or match.group("eggname")) # Get the match group
|
||||
.replace("-", "") # We ignore -
|
||||
.replace("_", "") # And _
|
||||
)
|
||||
return sort_key
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option("--execute/--dryrun", "execute", default=False)
|
||||
@click.argument("requirements")
|
||||
def main(requirements, execute):
|
||||
"""Given the path of a requirements.txt, format it.
|
||||
|
||||
If running in --execute, rewrite the source file with sorted contents and exit 0.
|
||||
|
||||
If running in --dryrun, exit 0 if --execute would produce no changes otherwise exit 1.
|
||||
|
||||
"""
|
||||
|
||||
with open(requirements) as f:
|
||||
lines = f.readlines()
|
||||
f.seek(0)
|
||||
# Preserve an initial "buffer" for equality testing
|
||||
initial_buff = f.read()
|
||||
|
||||
# Trim whitespace
|
||||
lines = [l.strip() for l in lines]
|
||||
|
||||
# Discard comments and shitlisted packages
|
||||
lines = [l for l in lines if not l.startswith("#") and not sort_key(l) in SHITLIST]
|
||||
|
||||
# And sort, ignoring case explicitly
|
||||
lines = sorted(lines, key=sort_key)
|
||||
|
||||
# And generate a new "buffer"
|
||||
new_buff = "\n".join(lines) + "\n"
|
||||
|
||||
if new_buff != initial_buff and not execute:
|
||||
exit(1)
|
||||
|
||||
else:
|
||||
with open(requirements, "w") as f:
|
||||
f.write(new_buff)
|
||||
exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Add table
Add a link
Reference in a new issue