Skip to content

fix(config): use uv by default and honor AIRBYTE_NO_UV - #1099

Merged
Aaron ("AJ") Steers (aaronsteers) merged 3 commits into
mainfrom
devin/1785969891-fix-no-uv-inversion
Aug 5, 2026
Merged

fix(config): use uv by default and honor AIRBYTE_NO_UV#1099
Aaron ("AJ") Steers (aaronsteers) merged 3 commits into
mainfrom
devin/1785969891-fix-no-uv-inversion

Conversation

@aaronsteers

@aaronsteers Aaron ("AJ") Steers (aaronsteers) commented Aug 5, 2026

Copy link
Copy Markdown
Member

Summary

AIRBYTE_NO_UV has been wired backwards since a2b051e ("feat: replace pip with uv"), with the practical result that PyAirbyte has been installing connectors with pip, not uv, in the default configuration — the opposite of that PR's stated goal and of the constant's own docstring.

The mapping is off by one not:

# before — unset env var yields NO_UV = True
NO_UV: bool = os.getenv("AIRBYTE_NO_UV", "").lower() not in {"1", "true", "yes"}

# after — unset env var yields NO_UV = False
NO_UV: bool = os.getenv("AIRBYTE_NO_UV", "").lower() in {"1", "true", "yes"}

Every consumer already reads the constant the natural way (airbyte/_executors/python.py, airbyte/validate.py):

uv_cmd_prefix = ["uv"] if not NO_UV else []

so NO_UV = True by default meant the uv prefix was never applied and the venv/install fell back to sys.executable -m venv and pip. No consumer logic changes here; only the environment-variable mapping does.

Behavior table:

AIRBYTE_NO_UV before after
unset (default) pip uv
1 / true / yes uv pip
0 / false / anything else pip uv

uv>=0.5.0,<0.9.0 is a direct runtime dependency, so uv is always present and the new default cannot fail for lack of the binary.

Note for reviewers: tests/conftest.py sets AIRBYTE_NO_UV=1 for its use_uv=False parametrization. Under the old mapping that case was silently exercising uv, and its use_uv=True counterpart was exercising pip — the two connector-install paths were swapped. This fix makes both match their names, so it also restores the intended test coverage rather than just flipping a default.

Test plan

tests/unit_tests/test_constants.py pins the corrected mapping across unset, 1, true, TRUE, YeS, 0, false, no, and an arbitrary value. Each case runs in a subprocess because NO_UV is evaluated at import time and cannot be re-read by monkeypatching the environment in-process.

Local: uv run pytest -q tests/unit_tests/ (445 passed, 1 skipped), ruff check, ruff format --check, pyrefly check all clean.

Related

Conflicts textually with #1098, which rewrites the same line to load from pydantic-settings and pins the old inverted behavior in a characterization test. Whichever lands second needs a rebase; if this one lands first, that characterization test should be updated to assert the corrected mapping.

Link to Devin session: https://app.devin.ai/sessions/9b54bbbb80a945d99ce92c8940d41503
Requested by: Aaron ("AJ") Steers (@aaronsteers)

Summary by CodeRabbit

  • Bug Fixes

    • Corrected handling of the AIRBYTE_NO_UV setting so recognized truthy values consistently disable uv and use pip.
    • Improved behavior for unset, falsy, and unrecognized setting values.
  • Tests

    • Added coverage for environment-variable parsing across supported and miscellaneous values.

Important

Auto-merge enabled.

This PR is set to merge automatically when all requirements are met.

devin-ai-integration Bot and others added 2 commits August 5, 2026 22:48
Co-Authored-By: AJ Steers <aj@airbyte.io>
Co-Authored-By: AJ Steers <aj@airbyte.io>
Copilot AI review requested due to automatic review settings August 5, 2026 22:49
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

Testing This PyAirbyte Version

You can test this version of PyAirbyte using the following:

# Run PyAirbyte CLI from this branch:
uvx --from 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1785969891-fix-no-uv-inversion' pyairbyte --help

# Install PyAirbyte from this branch for development:
pip install 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1785969891-fix-no-uv-inversion'

PR Slash Commands

Airbyte Maintainers can execute the following slash commands on your PR:

  • /fix-pr - Fixes most formatting and linting issues
  • /uv-lock - Updates uv.lock file
  • /test-pr - Runs tests with the updated PyAirbyte
  • /prerelease - Builds and publishes a prerelease version to PyPI
📚 Show Repo Guidance

Helpful Resources

Community Support

Questions? Join the #pyairbyte channel in our Slack workspace.

📝 Edit this welcome message.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

NO_UV now directly indicates whether uv is disabled. Tests verify parsing for unset, truthy, falsy, and miscellaneous environment values.

Changes

NO_UV parsing

Layer / File(s) Summary
Parse and validate NO_UV
airbyte/constants.py, tests/unit_tests/test_constants.py
NO_UV defaults to False and becomes True for "1", "true", or "yes". Subprocess tests verify supported and unsupported values.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: use uv by default and honor the AIRBYTE_NO_UV setting.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch devin/1785969891-fix-no-uv-inversion

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@aaronsteers
Aaron ("AJ") Steers (aaronsteers) marked this pull request as ready for review August 5, 2026 22:50

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the AIRBYTE_NO_UV environment-variable mapping so that uv is used by default (and pip is only used when opting out), aligning runtime behavior with the constant name/docstring and existing consumer logic.

Changes:

  • Correct NO_UV to be True only when AIRBYTE_NO_UV is explicitly set to a truthy value (1/true/yes), making uv the default.
  • Update the NO_UV docstring to describe the corrected behavior.
  • Add a subprocess-based unit test to validate the import-time env-var mapping across common values and casing.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
airbyte/constants.py Fixes AIRBYTE_NO_UVNO_UV parsing so uv is default and the opt-out flag behaves as named.
tests/unit_tests/test_constants.py Adds coverage for the corrected env-var mapping using a subprocess to account for import-time evaluation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/unit_tests/test_constants.py
Co-Authored-By: AJ Steers <aj@airbyte.io>
Copilot AI review requested due to automatic review settings August 5, 2026 22:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

airbyte/constants.py:190

  • The final sentence implies that setting AIRBYTE_NO_UV to any value opts out of uv, but the implementation only disables uv for the explicit truthy values {"1","true","yes"}. Tweaking the wording avoids ambiguity for users who might set AIRBYTE_NO_UV=0/false and expect pip.
If the variable is not set or set to any other value, uv will be used by default. Set this
variable to opt out of uv and use pip instead.

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Runtime verification — real connector installs confirm the flip

Verified at the real subprocess level (not unit assertions): actually installed source-faker from PyPI into fresh venvs from three driver environments on Python 3.11.15, and captured the command lines _executors/python.py echoes to stderr before executing them. Verified at c3bd1c0.

AIRBYTE_NO_UV unset AIRBYTE_NO_UV=1
main (pre-fix) python -m venv … + pip --python … install … (uv — inverted)
this branch uv venv … + uv pip install --python … python -m venv … + pip --python … install …
# Test 1 — branch, AIRBYTE_NO_UV unset  →  NO_UV = False
Creating 'source-faker' virtual environment with command 'uv venv /tmp/nouv/t1/.venv-source-faker'
Installing 'source-faker' into virtual environment '/tmp/nouv/t1/.venv-source-faker' with command 'uv pip install --python /tmp/nouv/t1/.venv-source-faker/bin/python airbyte-source-faker'
Connector 'source-faker' installed successfully!   → version 7.2.1

# Test 2 — branch, AIRBYTE_NO_UV=1  →  NO_UV = True
Creating 'source-faker' virtual environment with command '/home/ubuntu/drv-branch/bin/python -m venv /tmp/nouv/t2/.venv-source-faker'
Installing 'source-faker' into virtual environment '/tmp/nouv/t2/.venv-source-faker' with command 'pip --python /tmp/nouv/t2/.venv-source-faker/bin/python install airbyte-source-faker'
Connector 'source-faker' installed successfully!   → version 7.2.1

# Test 3 — main @ 35f4691 (scratch worktree), AIRBYTE_NO_UV unset  →  NO_UV = True  (the bug)
Creating 'source-faker' virtual environment with command '/home/ubuntu/drv-main/bin/python -m venv /tmp/nouv/t3/.venv-source-faker'
Installing 'source-faker' into virtual environment '/tmp/nouv/t3/.venv-source-faker' with command 'pip --python /tmp/nouv/t3/.venv-source-faker/bin/python install airbyte-source-faker'

Tests 1 and 3 use identical inputs and differ only in which tree is imported, so the opposite package manager is direct proof this one line is what flipped the behavior. Every case used a pristine AIRBYTE_INSTALL_DIR so no pre-existing venv could mask the result, and all three installs genuinely succeeded (airbyte-source-faker 7.2.1).

The uv-built venv is actually usable

Reusing the venv created by uv venv in Test 1:

[usability] NO_UV = False
[usability] reusing venv at /tmp/nouv/t1/.venv-source-faker/bin/python
[usability] source.check() -> OK (no exception)
[usability] available streams = ['products', 'users', 'purchases']
[usability] records read from 'users' = 10
[usability] first record id = 1
[usability] PASS

So defaulting to uv does not produce a broken venv.

⚠️ Pre-existing caveat: the pip path needs a modern pip on PATH

The AIRBYTE_NO_UV=1 branch shells out to a bare pip and calls pip --python <interp> install. Ubuntu's system pip (22.0.2) fails with no such option: --python; pip 26.2.1 had to be installed into the driver venv for Test 2 to run. This is not introduced by this PR (it is the same on main), but now that pip is the opt-out path rather than the default, it may be worth documenting alongside AIRBYTE_NO_UV.

Not covered: airbyte/validate.py (the other NO_UV consumer) at runtime, the use_python override branches, non-Python executors, and AIRBYTE_NO_UV values other than unset/1.

Tested by Devin — session

@github-code-quality

github-code-quality Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: Python

Python / code-coverage/pytest-fast

The overall coverage in commit c3bd1c0 in the devin/1785969891-fix... branch is 68%. The coverage in commit d9f652f in the main branch is 65%.

Show a code coverage summary of the most impacted files.
File main d9f652f devin/1785969891-fix... c3bd1c0 +/-
airbyte/mcp/_tool_utils.py 72% 84% +12%
airbyte/mcp/registry.py 53% 70% +17%
airbyte/mcp/server.py 69% 88% +19%
airbyte/mcp/_arg_resolvers.py 13% 44% +31%
airbyte/mcp/int...c_history_ui.py 0% 36% +36%
airbyte/mcp/int...hared_models.py 0% 81% +81%
airbyte/cloud/models.py 0% 91% +91%
airbyte/mcp/int..._registry_ui.py 0% 92% +92%
airbyte/mcp/int...nc_status_ui.py 0% 97% +97%
airbyte/mcp/_guards.py 0% 100% +100%

Python / code-coverage/pytest-no-creds

The overall coverage in commit c3bd1c0 in the devin/1785969891-fix... branch is 68%. The coverage in commit d9f652f in the main branch is 65%.

Show a code coverage summary of the most impacted files.
File main d9f652f devin/1785969891-fix... c3bd1c0 +/-
airbyte/mcp/_tool_utils.py 72% 84% +12%
airbyte/mcp/registry.py 53% 70% +17%
airbyte/mcp/server.py 69% 88% +19%
airbyte/mcp/_arg_resolvers.py 13% 44% +31%
airbyte/mcp/int...c_history_ui.py 0% 36% +36%
airbyte/mcp/int...hared_models.py 0% 81% +81%
airbyte/cloud/models.py 0% 91% +91%
airbyte/mcp/int..._registry_ui.py 0% 92% +92%
airbyte/mcp/int...nc_status_ui.py 0% 97% +97%
airbyte/mcp/_guards.py 0% 100% +100%

Python / code-coverage/pytest

The overall coverage in commit c3bd1c0 in the devin/1785969891-fix... branch is 73%. The coverage in commit d9f652f in the main branch is 71%.

Show a code coverage summary of the most impacted files.
File main d9f652f devin/1785969891-fix... c3bd1c0 +/-
airbyte/mcp/_tool_utils.py 72% 84% +12%
airbyte/mcp/registry.py 53% 70% +17%
airbyte/mcp/server.py 69% 88% +19%
airbyte/mcp/_arg_resolvers.py 13% 44% +31%
airbyte/mcp/int...c_history_ui.py 0% 36% +36%
airbyte/mcp/int...hared_models.py 0% 81% +81%
airbyte/mcp/int..._registry_ui.py 0% 92% +92%
airbyte/cloud/models.py 0% 93% +93%
airbyte/mcp/int...nc_status_ui.py 0% 97% +97%
airbyte/mcp/_guards.py 0% 100% +100%

Updated August 05, 2026 23:18 UTC

@aaronsteers
Aaron ("AJ") Steers (aaronsteers) merged commit a51e0a0 into main Aug 5, 2026
24 checks passed
@aaronsteers
Aaron ("AJ") Steers (aaronsteers) deleted the devin/1785969891-fix-no-uv-inversion branch August 5, 2026 23:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants