Skip to content

Commit

Permalink
Removed uvloop and winloop as required dependencies and left them as …
Browse files Browse the repository at this point in the history
…optional dependencies
  • Loading branch information
owenlamont committed Jan 26, 2025
1 parent 56e1495 commit 840f42f
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 90 deletions.
51 changes: 30 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,30 @@ pipx install uv-secure
you can optionally install uv-secure as a development dependency in a virtual
environment.

## Optional Dependencies

uv-secure uses highly asynchronous code to request multiple API responses or file opens
concurrently. You can install uvloop on Linux/Mac or winloop on Windows to speed up the
asynchronous event loop (at the expense of debuggability if you want to develop
uv-secure yourself). Also note, winloop is a relatively young package and may give you
some stability issues on particular versions of Python

If you want to install the optional dependency with uv do it like this:

```shell
uv tool install uv-secure --with uvloop
```

or with pipx like this:

```powershell
pipx install uv-secure
pipx inject uv-secure winloop
```

uv-secure will automatically use uvloop or winloop if it finds them in the same
environment as itself.

## Usage

After installation, you can run uv-secure --help to see the options.
Expand Down Expand Up @@ -255,31 +279,16 @@ installed by default, so I request PyCharm _Install packaging tool_ in the
_Python Interpreter_ settings (I may just add these in future are dev dependencies to
reduce the friction if this causes others too much pain). I have also encountered some
test failures on Windows if you use winloop with setuptools and pip - so you probably do
want to switch to the asyncio eventloop if installing those (I'm hoping to continue
using winloop, but it's a relatively young project and has some rough edges - I may drop
it as a dependency on Windows if it causes to many issues).
want to remove winloop if debugging in that environment if you added it.

#### Debugging Async Code

Given uv-secure is often IO bound waiting on API responses or file reads I've tried to
make it as asynchronous as I can. uv-secure also uses uvloop and winloop which should be
more performant than the vanilla asyncio event loop - but they don't play nice with
Python debuggers. The hacky way at present to use asyncio event loop when debugging is
uncommenting the run import in run.py:

```python
if sys.platform in ("win32", "cygwin", "cli"):
from winloop import run
else:
from uvloop import run
# from asyncio import run # uncomment for local dev and debugging
```

I definitely want to come up with a nicer scheme in the future. Either make the import
depend on an environment variable to set local development, or perhaps make uvloop and
winloop extra dependencies with asyncio event loop being the fallback so you can choose
not to include them (I need to research best/common practise here some more and pick
something).
make it as asynchronous as I can. uv-secure also uses uvloop and winloop if installed
which should be more performant than the vanilla asyncio event loop - but they don't
play nice with Python debuggers. If you intend to do debugging I suggest leaving them
out of the virtual environment. By default, winloop or uvloop won't be installed the
repo venv unless you explicitly add them.

## Related Work and Motivation

Expand Down
6 changes: 2 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,9 @@ dependencies = [
"httpx>=0.28.1",
"inflect>=7.4.0",
"pydantic>=2.10.3",
"pytest-asyncio>=0.25.2",
"rich>=13.9.4",
'tomli; python_version < "3.11"',
"typer>=0.15.1",
"uvloop>=0.21.0 ; sys_platform != 'win32'",
"winloop>=0.1.7 ; sys_platform == 'win32'",
]

[project.scripts]
Expand Down Expand Up @@ -99,7 +96,7 @@ init_typed = true
warn_required_dynamic_aliases = true

[tool.pytest.ini_options]
asyncio_default_fixture_loop_scope = "function"
asyncio_default_fixture_loop_scope = "session"
filterwarnings = [
"error",
"ignore::ResourceWarning" # Disabling as I think pytest-httpx is somehow causing
Expand Down Expand Up @@ -201,6 +198,7 @@ convention = "google"
dev = [
"coverage>=7.6.9",
"pytest>=8.3.4",
"pytest-asyncio>=0.25.2",
"pytest-cov>=6.0.0",
"pytest-httpx>=0.35.0",
"pytest-mock>=3.14.0",
Expand Down
18 changes: 10 additions & 8 deletions src/uv_secure/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@
from uv_secure.dependency_checker import check_lock_files, RunStatus


if sys.platform in ("win32", "cygwin", "cli"):
from winloop import run
else:
from uvloop import run
# from asyncio import run # uncomment for local dev and debugging


app = typer.Typer()


Expand Down Expand Up @@ -55,7 +48,6 @@ def _version_callback(value: bool) -> None:
help="Flag whether to disable caching for vulnerability http requests",
)


_ignore_option = typer.Option(
None,
"--ignore",
Expand Down Expand Up @@ -92,6 +84,16 @@ def main(
version: bool = _version_option,
) -> None:
"""Parse uv.lock files, check vulnerabilities, and display summary."""

# Use uvloop or winloop if present
try:
if sys.platform in {"win32", "cygwin", "cli"}:
from winloop import run
else:
from uvloop import run
except ImportError:
from asyncio import run

run_status = run(
check_lock_files(file_paths, aliases, desc, disable_cache, ignore, config_path)
)
Expand Down
59 changes: 2 additions & 57 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 840f42f

Please sign in to comment.