juftin / hatch-pip-compile

hatch plugin to use pip-compile (or uv) to manage project dependencies and lockfiles
http://juftin.com/hatch-pip-compile/
MIT License
76 stars 3 forks source link

Bug: nonobvious unfriendly stacktrace error message output when running hatch-pip-compile for the first time with an existing requirements.txt #82

Open wis opened 4 months ago

wis commented 4 months ago

I just started trying out hatch-pip-compile, also trying out hatch for the first time too, with uv for fast installs. it's working great so far, I'm excited about this setup.

..But it errored with a nonobvious stacktrace error message the first time I ran it with pipx run hatch env run -- python myscript.py, which is supposed to have hatch install hatch-pip-compile and have it start running hatch-pip-compile automatically:

The stacktrace: (i'm not sure why it looks like that, with the weird characters framing the code)

Ôöé ÔØ▒ 143 Ôöé   Ôöé   Ôöé   new_dep_hash = environment.dependency_hash()                                   Ôöé
Ôöé   144 Ôöé   Ôöé                                                                                      Ôöé
Ôöé   145 Ôöé   Ôöé   current_dep_hash = self.env_metadata.dependency_hash(environment)                  Ôöé
Ôöé   146 Ôöé   Ôöé   if new_dep_hash != current_dep_hash:                                               Ôöé
Ôöé                                                                                                  Ôöé
Ôöé C:\Users\wis\pipx\.cache\5c892549a10c04f\Lib\site-packages\hatch_pip_compile\plugin.py:104 in  Ôöé
Ôöé dependency_hash                                                                                  Ôöé
Ôöé                                                                                                  Ôöé
Ôöé   101 Ôöé   Ôöé   """                                                                                Ôöé
Ôöé   102 Ôöé   Ôöé   Get the dependency hash                                                            Ôöé
Ôöé   103 Ôöé   Ôöé   """                                                                                Ôöé
Ôöé ÔØ▒ 104 Ôöé   Ôöé   self.run_pip_compile()                                                             Ôöé
Ôöé   105 Ôöé   Ôöé   hatch_hash = super().dependency_hash()                                             Ôöé
Ôöé   106 Ôöé   Ôöé   if not self.dependencies:                                                          Ôöé
Ôöé   107 Ôöé   Ôöé   Ôöé   return hatch_hash                                                              Ôöé
Ôöé                                                                                                  Ôöé
Ôöé C:\Users\wis\pipx\.cache\5c892549a10c04f\Lib\site-packages\hatch_pip_compile\plugin.py:121 in  Ôöé
Ôöé run_pip_compile                                                                                  Ôöé
Ôöé                                                                                                  Ôöé
Ôöé   118 Ôöé   Ôöé   Ôöé   with self.safe_activation():                                                   Ôöé
Ôöé   119 Ôöé   Ôöé   Ôöé   Ôöé   self.resolver.install_pypi_dependencies()                                  Ôöé
Ôöé   120 Ôöé   Ôöé   Ôöé   Ôöé   if self.piptools_lock_file.exists():                                       Ôöé
Ôöé ÔØ▒ 121 Ôöé   Ôöé   Ôöé   Ôöé   Ôöé   _ = self.piptools_lock.compare_python_versions(                        Ôöé
Ôöé   122 Ôöé   Ôöé   Ôöé   Ôöé   Ôöé   Ôöé   verbose=self.config.get("pip-compile-verbose", None)               Ôöé
Ôöé   123 Ôöé   Ôöé   Ôöé   Ôöé   Ôöé   )                                                                      Ôöé
Ôöé   124 Ôöé   Ôöé   Ôöé   Ôöé   self.pip_compile_cli()                                                     Ôöé
Ôöé                                                                                                  Ôöé
Ôöé C:\Users\wis\pipx\.cache\5c892549a10c04f\Lib\site-packages\hatch_pip_compile\lock.py:113 in    Ôöé
Ôöé compare_python_versions                                                                          Ôöé
Ôöé                                                                                                  Ôöé
Ôöé   110 Ôöé   Ôöé   Ôöé   Print warning if python versions are different, by default None                Ôöé
Ôöé   111 Ôöé   Ôöé   Ôöé   which will print the warning. Used as a plugin flag.                           Ôöé
Ôöé   112 Ôöé   Ôöé   """                                                                                Ôöé
Ôöé ÔØ▒ 113 Ôöé   Ôöé   lock_version = self.lock_file_version                                              Ôöé
Ôöé   114 Ôöé   Ôöé   current_version = self.current_python_version                                      Ôöé
Ôöé   115 Ôöé   Ôöé   match = (current_version.major == lock_version.major) and (                        Ôöé
Ôöé   116 Ôöé   Ôöé   Ôöé   current_version.minor == lock_version.minor                                    Ôöé
Ôöé                                                                                                  Ôöé
Ôöé C:\Users\wis\pipx\.cache\5c892549a10c04f\Lib\site-packages\hatch_pip_compile\lock.py:100 in    Ôöé
Ôöé lock_file_version                                                                                Ôöé
Ôöé                                                                                                  Ôöé
Ôöé    97 Ôöé   Ôöé   )                                                                                  Ôöé
Ôöé    98 Ôöé   Ôöé   if match is None:                                                                  Ôöé
Ôöé    99 Ôöé   Ôöé   Ôöé   msg = "Could not find lock file python version"                                Ôöé
Ôöé ÔØ▒ 100 Ôöé   Ôöé   Ôöé   raise LockFileError(msg)                                                       Ôöé
Ôöé   101 Ôöé   Ôöé   return Version(match.group(1))                                                     Ôöé
Ôöé   102 Ôöé                                                                                          Ôöé
Ôöé   103 Ôöé   def compare_python_versions(self, verbose: bool | None = None) -> bool:                Ôöé
Ôò░ÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔò»
LockFileError: Could not find lock file python version

the content of the existing (old) requirements.txt file I had:

comtypes ==1.4.4 --hash=sha256:8db0d45aca5e891b3ffb77fe47cfd256cc3799d409d8e39baf8dd7884859d828 \
    --hash=sha256:b7ead79b42ed8707ce8be8ad1e3020d9483c0bd2a905dc1903efaf73b4f6651d
kdl-py ==1.2.0 --hash=sha256:63f3f46c6277dedadce44dcfc94672bf6e6bf3330b90122e0134c22857e29973 \
    --hash=sha256:d11e556dbb226cccf666bb4ffe17c73e9d5bb08d29976649fa9292bac973d3e2
numpy ==1.26.4 --hash=sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b \
    --hash=sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818 \
    --hash=sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20 \
    --hash=sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0 \
    --hash=sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010 \
    --hash=sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a \
    --hash=sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea \
    --hash=sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c \
    --hash=sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71 \
    --hash=sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110 \
    --hash=sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be \
    --hash=sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a \
    --hash=sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a \
    --hash=sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5 \
    --hash=sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed \
    --hash=sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd \
    --hash=sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c \
    --hash=sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e \
    --hash=sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0 \
    --hash=sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c \
    --hash=sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a \
    --hash=sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b \
    --hash=sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0 \
    --hash=sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6 \
    --hash=sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2 \
    --hash=sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a \
    --hash=sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30 \
    --hash=sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218 \
    --hash=sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5 \
    --hash=sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07 \
    --hash=sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2 \
    --hash=sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4 \
    --hash=sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764 \
    --hash=sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef \
    --hash=sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3 \
    --hash=sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f
pyaudio ==0.2.14 --hash=sha256:009f357ee5aa6bc8eb19d69921cd30e98c42cddd34210615d592a71d09c4bd57 \
    --hash=sha256:126065b5e82a1c03ba16e7c0404d8f54e17368836e7d2d92427358ad44fefe61 \
    --hash=sha256:12f2f1ba04e06ff95d80700a78967897a489c05e093e3bffa05a84ed9c0a7fa3 \
    --hash=sha256:2a166fc88d435a2779810dd2678354adc33499e9d4d7f937f28b20cc55893e83 \
    --hash=sha256:2dac0d6d675fe7e181ba88f2de88d321059b69abd52e3f4934a8878e03a7a074 \
    --hash=sha256:506b32a595f8693811682ab4b127602d404df7dfc453b499c91a80d0f7bad289 \
    --hash=sha256:5fce4bcdd2e0e8c063d835dbe2860dac46437506af509353c7f8114d4bacbd5b \
    --hash=sha256:78dfff3879b4994d1f4fc6485646a57755c6ee3c19647a491f790a0895bd2f87 \
    --hash=sha256:858caf35b05c26d8fc62f1efa2e8f53d5fa1a01164842bd622f70ddc41f55000 \
    --hash=sha256:bbeb01d36a2f472ae5ee5e1451cacc42112986abe622f735bb870a5db77cf903 \
    --hash=sha256:f745109634a7c19fa4d6b8b7d6967c3123d988c9ade0cd35d4295ee1acdb53e9
pymonctl ==0.92 --hash=sha256:2495d8dab78f9a7dbce37e74543e60b8bd404a35c3108935697dda7768611b5a
pyvda ==0.4.3 --hash=sha256:321972af258c3f3a7e2da98f15016018c89128d20c8e9738c5f4c4568f389d6a \
    --hash=sha256:a4ba4c782e7a935c43b0a1355c5af3efe1b52b143c84bd18c40d28ccf5861343
pywin32 ==306 --hash=sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d \
    --hash=sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65 \
    --hash=sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e \
    --hash=sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b \
    --hash=sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4 \
    --hash=sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040 \
    --hash=sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a \
    --hash=sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36 \
    --hash=sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8 \
    --hash=sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e \
    --hash=sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802 \
    --hash=sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a \
    --hash=sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407 \
    --hash=sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0
pywinbox ==0.7 --hash=sha256:8b2506a8dd7afa0a910b368762adfac885274132ef9151b0c81b0d2c6ffd6f83
pywinctl ==0.4 --hash=sha256:8c4a92bd57e35fd280c5c04f048cc822e236abffe2fa17351096b0e28907172d
typing-extensions ==4.12.2 --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
    --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8

I generated it with this small python script, that generates a requirements.txt lock file with hashes from a Pipfile.lock. (in the process of migrating away from Pipenv, well my first attempt with pip, now I use hatch with hatch-pip-compile)

I deleted/renamed the old requirements.txt file manually and reran the command to have hatch install and run hatch-pip-compile, and it worked.

Suggested improved behavior: hatch-pip-compile should mark the requirements.txt it generates with a kind of a magic string prepended at the top of the requirements.txt in a comment, and if it does not exist, it should print that there's an existing requirements.txt and if it should overwrite it.

juftin commented 4 months ago

Oh that stacktrace is hard to read, hatch uses rich to format traceback, your terminal must not play nicely with some of the pretty printing it's doing.

hatch-pip-compile is not finding its expected header: https://github.com/juftin/hatch-pip-compile/blob/251fcd7e1f5a8041cc698d94abb9b18fab8559d9/requirements/requirements-test.txt#L1-L5

LockFileError: Could not find lock file python version

I'll look into making this a better UX.