Open wrdls opened 1 week ago
Yep, both of those should work! Let me know if either does not.
If you don't want to install pytest
in your project, you can also use uvx pytest my_script.py
uv run pytest my_script.py
won't work because we won't read the PEP 723 metadata anymore. Nor will uvx
. I'm not sure we have a good solution yet. I think we need a new uv run
option.
Edit: Ignore this, see OP's comment below. (My examples worked with pytest because I didn't actually import the dependency.)
Really? Both of those worked for me (but I'm doing something shady somewhere...?):
➜ uvexamples uv init inline
Initialized project `inline` at `/Users/dmbp/Documents/dev/uvexamples/inline`
➜ uvexamples cd inline
➜ inline git:(main) ✗ hx my_script.py
(copied and pasted OP's script)
➜ inline git:(main) ✗ uv add --script my_script.py "rich"
Updated `my_script.py`
➜ inline git:(main) ✗ uv run my_script.py
Reading inline script metadata from `my_script.py`
⠙ Resolving dependencies... INFO add_decision: root @ 0a0.dev0 without checking dependencies
⠙ rich==13.9.4 INFO add_decision: rich @ 13.9.4 without checking dependencies
⠙ markdown-it-py==3.0.0 INFO add_decision: markdown-it-py @ 3.0.0 without checking dependencies
⠙ pygments==2.18.0 INFO add_decision: pygments @ 2.18.0 without checking dependencies
⠙ mdurl==0.1.2 INFO add_decision: mdurl @ 0.1.2 without checking dependencies
Installed 4 packages in 10ms
➜ inline git:(main) ✗ uvx pytest my_script.py
⠙ Resolving dependencies... INFO add_decision: root @ 0a0.dev0 without checking dependencies
⠙ pytest==8.3.3 INFO add_decision: pytest @ 8.3.3 without checking dependencies
⠙ iniconfig==2.0.0 INFO add_decision: iniconfig @ 2.0.0 without checking dependencies
⠙ packaging==24.2 INFO add_decision: packaging @ 24.2 without checking dependencies
⠙ pluggy==1.5.0 INFO add_decision: pluggy @ 1.5.0 without checking dependencies
================================= test session starts ==================================
platform darwin -- Python 3.11.5, pytest-8.3.3, pluggy-1.5.0
rootdir: /Users/dmbp/Documents/dev/uvexamples/inline
configfile: pyproject.toml
collected 1 item
my_script.py . [100%]
================================== 1 passed in 0.00s ===================================
➜ inline git:(main) ✗
This doesn't work for me with the following script.
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "rich",
# ]
# ///
import rich
def normalize(paths):
return [p.rstrip("/") for p in paths]
def test_normalize():
assert ["foo", "bar"] == normalize(["foo/", "bar"])
if __name__ == "__main__":
rich.print(normalize(["foo/"]))
Testing in Docker to get a clean environment:
❯ docker run --rm -it --entrypoint=bash python:3
root@b441346070f6:/# apt update && apt install -y vim
...
root@b441346070f6:/# pip install uv
Collecting uv
Downloading uv-0.5.1-py3-none-manylinux_2_28_aarch64.whl.metadata (11 kB)
Downloading uv-0.5.1-py3-none-manylinux_2_28_aarch64.whl (13.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 13.0/13.0 MB 17.7 MB/s eta 0:00:00
Installing collected packages: uv
Successfully installed uv-0.5.1
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
[notice] A new release of pip is available: 24.2 -> 24.3.1
[notice] To update, run: pip install --upgrade pip
root@b441346070f6:/# vim my_script.py
root@b441346070f6:/# uv run my_script.py
Reading inline script metadata from `my_script.py`
Installed 4 packages in 6ms
['foo']
root@b441346070f6:/# uvx pytest my_script.py
Installed 4 packages in 5ms
========================================================================================== test session starts ===========================================================================================
platform linux -- Python 3.13.0, pytest-8.3.3, pluggy-1.5.0
rootdir: /
collected 0 items / 1 error
================================================================================================= ERRORS =================================================================================================
_____________________________________________________________________________________ ERROR collecting my_script.py ______________________________________________________________________________________
ImportError while importing test module '/my_script.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
usr/local/lib/python3.13/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
my_script.py:7: in <module>
import rich
E ModuleNotFoundError: No module named 'rich'
======================================================================================== short test summary info =========================================================================================
ERROR my_script.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
============================================================================================ 1 error in 0.06s ============================================================================================
root@b441346070f6:/#
Ah, thank you! That was helpful - I guess I didn't try actually importing the dependency in the previous example.
If there are only a few dependencies then you could get around it for now with uvx --with rich pytest my_script.py
(but that defeats the purpose of inline dependencies...)
Related
We've also discussed like --with-requirements <script-path>
I use
uv
to run scripts with inline dependencies.Sometimes I have a need to add a unit test to scripts. Usually my use case is something like the below example where the
normalize()
function starts off simple and grows in complexity over time (e.g. to handle edge cases) and I want to test these changes.my_script.py
If the scripts keeps growing in size, it probably makes sense to convert this to a project, but at least initially this feels like overkill.
Before
uv
, I'd execute these like this with the dependencies installed system wide or in a venv:What would be the best way to approach this in
uv
? I feel like I'm missing something obvious, so please let me know if this is the case.Ideally I'd be able to run it like
Another option I thought of was converting the inline dependencies to a venv (e.g.,
uv venv --from-script my_script.py
). This adds steps and complexity for testing, but avoids it for runtime.