Skip to main content

add my pip_freeze script

ID
a61c732
date
2023-05-28 03:50:07+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
f3870e5
message
add my pip_freeze script
changed files
2 files, 98 additions

Changed files

python/README.md (0) → python/README.md (777)

diff --git a/python/README.md b/python/README.md
new file mode 100644
index 0000000..63cc34b
--- /dev/null
+++ b/python/README.md
@@ -0,0 +1,24 @@
+# python
+
+These scripts are all related to [Python], a scripting language I use a lot of (including in the rest of this repo!).
+
+[Python]: https://www.python.org/
+
+## The individual scripts
+
+<dl>
+  <dt>
+    <a href="https://github.com/alexwlchan/scripts/blob/main/python/pip_freeze">
+      <code>pip_freeze [FILE]</code>
+    </a>
+  </dt>
+  <dd>
+    this tries to add a comment to any imports I have in a file, telling me what version I had installed when I wrote a script, e.g.
+    <pre><code>import os
+import humanize</code></pre>
+becomes
+    <pre><code>import os
+import humanize  # humanize==4.4.0</code></pre>
+    I use it for lightweight dependency tracking, when I have a script that I don’t want to write an entire <code>requirements.txt</code> file for.
+  </dd>
+</dl>

python/pip_freeze (0) → python/pip_freeze (2065)

diff --git a/python/pip_freeze b/python/pip_freeze
new file mode 100755
index 0000000..dd47df2
--- /dev/null
+++ b/python/pip_freeze
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+"""
+This is a script for lightweight dependency tracking.
+
+This tries to add a comment to any imports I have in a file, telling me
+what version I had installed when I wrote a script, e.g.
+
+    import os
+    import humanize
+
+becomes
+
+    import os
+    import humanize  # humanize==4.4.0
+
+I use this for a lot of scripts in this repo, when:
+
+-   I don't want to set up a requirements.txt file for each script
+    (and it wouldn't be accurate anyway)
+
+-   I might go a long time between writing and running a script, and
+    a third-party library might upgrade in the meantime -- and then it's
+    useful to know what I originally used if the script breaks
+
+-   I don't want to retest every script every time I upgrade a library.
+
+"""
+
+import os
+import re
+import subprocess
+import sys
+import tempfile
+
+
+def get_freeze_string(library_name):
+    if library_name in {"os", "re", "subprocess", "sys", "tempfile"}:
+        return None
+
+    try:
+        pip_output = subprocess.check_output(
+            f"pip freeze | grep {library_name}", shell=True
+        )
+    except subprocess.CalledProcessError:
+        return None
+    else:
+        return pip_output.decode("utf8").strip()
+
+
+if __name__ == "__main__":
+    try:
+        infile = sys.argv[1]
+    except IndexError:
+        sys.exit(f"Usage: {__file__} <PATH>")
+
+    with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as tmpfile:
+        with open(tmpfile.name, "w") as outfile:
+            for line in open(infile):
+                m = re.match(r"^import (?P<library_name>[a-zA-Z]+)\n$", line)
+
+                if m is None:
+                    outfile.write(line)
+                else:
+                    library_name = m.group("library_name")
+
+                    freeze = get_freeze_string(library_name)
+
+                    if freeze:
+                        outfile.write(f"import {library_name}  # {freeze}\n")
+                    else:
+                        outfile.write(line)
+
+        os.rename(infile, infile + ".pip_freeze.bak")
+        os.rename(tmpfile.name, infile)