Skip to content

build(typing): migrate from pyrefly to ty for type checking#1054

Open
Aaron ("AJ") Steers (aaronsteers) wants to merge 4 commits into
mainfrom
devin/1783307935-migrate-to-ty
Open

build(typing): migrate from pyrefly to ty for type checking#1054
Aaron ("AJ") Steers (aaronsteers) wants to merge 4 commits into
mainfrom
devin/1783307935-migrate-to-ty

Conversation

@aaronsteers

@aaronsteers Aaron ("AJ") Steers (aaronsteers) commented Jul 6, 2026

Copy link
Copy Markdown
Member

Summary

Migrates the type checker from pyrefly to ty (Astral's renamed/successor project).

Config: pyrefly.tomlty.toml with equivalent settings mapped to ty's schema:

  • project-includes[src] include
  • project-excludes[src] exclude
  • ignore-missing-imports = ["*"][analysis] allowed-unresolved-imports = ["**"]

Ignore comments: All 42 # pyrefly: ignore[rule] comments converted to # ty: ignore[rule] with mapped rule names (e.g. bad-returninvalid-return-type, missing-attributeunresolved-attribute, unexpected-keywordunknown-argument).

Pre-existing diagnostics: ty finds ~209 warnings that pyrefly didn't flag. These are demoted to warn severity in ty.toml with error-on-warning = false so CI passes. They can be fixed incrementally.

Dev dep: pyrefly>=0.38.0,<0.39.0ty>=0.0.56

CI: Workflow step renamed from "Run Pyrefly Check" → "Run ty Check" (uv run ty check).

Poe task: check task updated from pyrefly checkty check.

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

Summary by CodeRabbit

  • Chores
    • Switched project type-checking and linting from one checker to another, including the main CI workflow and local developer tooling.
    • Updated configuration and test coverage to run the new type-check command.
    • Refreshed several type-ignore annotations so checks stay clean under the new tool.

Co-Authored-By: AJ Steers <aj@airbyte.io>
@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

@devin-ai-integration devin-ai-integration Bot marked this pull request as ready for review July 6, 2026 03:25
@github-actions

github-actions Bot commented Jul 6, 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/1783307935-migrate-to-ty' pyairbyte --help

# Install PyAirbyte from this branch for development:
pip install 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1783307935-migrate-to-ty'

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.

Comment thread airbyte/_connector_base.py Fixed
Comment thread airbyte/_connector_base.py Fixed

@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 found 2 potential issues.

Open in Devin Review

Comment thread pyproject.toml
"faker>=21.0.0,<22.0",
"freezegun>=1.4.0,<2.0",
"pyrefly>=0.38.0,<0.39.0",
"ty>=0.0.56",

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.

🔴 Type-checker lint test will always fail because the tool it invokes was removed from dependencies

The type-checker dependency is replaced ("ty>=0.0.56" at pyproject.toml:62) without updating the test that invokes the old tool (tests/lint_tests/test_mypy.py:13), so running pytest tests/lint_tests/ will always fail with a missing-command error.

Impact: The lint test suite is broken and will fail in CI or local runs.

Incomplete pyrefly-to-ty migration leaves test calling removed tool

The PR removes pyrefly from dev dependencies and replaces it with ty everywhere in the source code and CI workflow. However, tests/lint_tests/test_mypy.py:12-13 still runs:

check_result = subprocess.run(
    ["uv", "run", "pyrefly", "check"],
    ...
)

Since pyrefly is no longer in the dependency group, uv run pyrefly check will fail (command not found), causing the test assertion at tests/lint_tests/test_mypy.py:19 to always fail.

The fix should update this test to call ["uv", "run", "ty", "check"] and update the error messages accordingly.

Prompt for agents
The PR replaces pyrefly with ty in pyproject.toml dev dependencies, but tests/lint_tests/test_mypy.py still invokes `uv run pyrefly check` on line 13. This test will always fail now because pyrefly is no longer installed. The file needs to be updated to call `uv run ty check` instead, and the error messages on lines 18-22 should reference ty rather than pyrefly. The test function name (test_mypy_typing) is also misleading and could be renamed to something like test_ty_typing or test_type_checking.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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.

Fixed in 417968f — updated the test to call uv run ty check and renamed the function to test_type_checking.

Comment thread ty.toml
Comment on lines +19 to +33
[rules]
# Pre-existing issues inherited from pyrefly migration.
# Demoted to warn so CI passes; fix incrementally.
invalid-argument-type = "warn"
unknown-argument = "warn"
missing-argument = "warn"
unresolved-attribute = "warn"
invalid-assignment = "warn"
call-non-callable = "warn"
invalid-return-type = "warn"
invalid-method-override = "warn"
no-matching-overload = "warn"

[terminal]
error-on-warning = false

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.

🔍 Type checker configured to never block CI on type errors

The ty.toml configuration at lines 19-33 demotes 9 rule categories to "warn" and sets error-on-warning = false. This means the CI step (uv run ty check) will always pass regardless of type errors in those categories. While the comment explains this is intentional for incremental migration, it effectively means the type-checking CI gate provides no enforcement for the most common type errors (invalid-argument-type, unresolved-attribute, invalid-return-type, etc.). The inline # ty: ignore[...] comments throughout the codebase are also redundant since those rules are already demoted to non-blocking warnings.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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.

Intentional for the migration — the inline # ty: ignore[...] comments aren't redundant because they'll be needed when these rules are promoted back to "error" level during incremental cleanup. Keeping them now avoids a second pass through the codebase later.

Co-Authored-By: AJ Steers <aj@airbyte.io>
Copilot AI review requested due to automatic review settings July 6, 2026 03:28
@aaronsteers Aaron ("AJ") Steers (aaronsteers) removed the request for review from Copilot July 6, 2026 03:28
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@devin-ai-integration[bot], you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f6f39f9e-e288-4de3-a33a-f5ed96338151

📥 Commits

Reviewing files that changed from the base of the PR and between 417968f and 72f4652.

📒 Files selected for processing (17)
  • airbyte/_connector_base.py
  • airbyte/_message_iterators.py
  • airbyte/_processors/sql/postgres.py
  • airbyte/_processors/sql/snowflake.py
  • airbyte/_util/api_util.py
  • airbyte/_util/meta.py
  • airbyte/_util/name_normalizers.py
  • airbyte/caches/motherduck.py
  • airbyte/cli/pyab.py
  • airbyte/cloud/sync_results.py
  • airbyte/mcp/local.py
  • airbyte/progress.py
  • airbyte/secrets/google_gsm.py
  • airbyte/shared/sql_processor.py
  • airbyte/sources/base.py
  • airbyte/types.py
  • ty.toml
📝 Walkthrough

Walkthrough

This PR switches the project’s type-checking setup from pyrefly to ty. It adds ty configuration, updates CI and project tooling to run ty, and changes inline suppression comments across source files to ty-specific codes.

Changes

Type checker migration (pyrefly → ty)

Layer / File(s) Summary
Tooling config and CI switch to ty
ty.toml, pyrefly.toml, pyproject.toml, .github/workflows/python_lint.yml, tests/lint_tests/test_mypy.py
Adds ty.toml, removes pyrefly.toml, updates dependency/task/config references in pyproject.toml, changes the CI type-check step to ty check, and replaces the type-checking test with a ty-based command.
Core connector and message handling suppression updates
airbyte/_connector_base.py, airbyte/_message_iterators.py, airbyte/cli/pyab.py, airbyte/_util/meta.py, airbyte/mcp/local.py
Updates inline suppression comments around connector spec output, message iteration, CLI app construction, notebook metadata import handling, and stream preview resolution from pyrefly codes to ty codes.
SQL processors, caches, and datasets suppression updates
airbyte/_processors/sql/postgres.py, airbyte/_processors/sql/snowflake.py, airbyte/_util/name_normalizers.py, airbyte/caches/_utils/_cache_to_dest.py, airbyte/caches/base.py, airbyte/caches/motherduck.py, airbyte/datasets/_sql.py, airbyte/shared/sql_processor.py, airbyte/progress.py, airbyte/sources/base.py, airbyte/secrets/google_gsm.py, airbyte/types.py
Updates inline suppression comments in SQL processors, cache helpers, dataset initialization, shared SQL processing, progress tracking, source strategy iteration, secret handling, and SQL type conversion.
API utilities, state/catalog providers, and sync results suppression updates
airbyte/_util/api_util.py, airbyte/cloud/sync_results.py, airbyte/shared/catalog_providers.py, airbyte/shared/state_providers.py
Updates inline suppression comments in API utilities, sync-result formatting, catalog/state providers, and related return/attribute access sites from pyrefly to ty codes.

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

Possibly related PRs

  • airbytehq/PyAirbyte#1014: Both PRs touch airbyte/cli/pyab.py’s App(...) keyword suppressions during the same pyrefly-to-ty migration.
🚥 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 accurately summarizes the main change: migrating type checking from pyrefly to ty.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch devin/1783307935-migrate-to-ty

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.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (2)
ty.toml (2)

9-14: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant exclude entries?

Lines 10-11 (tests/integration_tests/fixtures/source-broken/**, tests/integration_tests/fixtures/source-test/**) are already subsumed by the blanket tests/** exclude on line 13. Was this intentional (e.g., ordering/precedence reasons), or can these be dropped for clarity, wdyt?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ty.toml` around lines 9 - 14, The exclude list in ty.toml has redundant
entries because tests/integration_tests/fixtures/source-broken/** and
tests/integration_tests/fixtures/source-test/** are already covered by tests/**.
Remove the narrower fixture paths from the exclude array unless there is a
specific precedence or override reason, and keep only the distinct exclusions
needed for clarity in the ty config.

17-17: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Very broad unresolved-import suppression.

allowed-unresolved-imports = ["**"] suppresses unresolved-import diagnostics for every module project-wide. This appears intended to preserve pyrefly's prior behavior per the PR objective, but it does mean ty won't catch genuinely missing/misspelled imports going forward. Worth scoping this down in a follow-up once the migration stabilizes, wdyt?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ty.toml` at line 17, The ty configuration currently suppresses
unresolved-import diagnostics for every import via the all-matching
allowed-unresolved-imports setting. Update the ty.toml setting to scope this
exception more narrowly, using a targeted pattern or list of known cases instead
of the global catch-all, so ty can still report real missing or misspelled
imports. Focus the change on the allowed-unresolved-imports entry in the ty
configuration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@ty.toml`:
- Around line 9-14: The exclude list in ty.toml has redundant entries because
tests/integration_tests/fixtures/source-broken/** and
tests/integration_tests/fixtures/source-test/** are already covered by tests/**.
Remove the narrower fixture paths from the exclude array unless there is a
specific precedence or override reason, and keep only the distinct exclusions
needed for clarity in the ty config.
- Line 17: The ty configuration currently suppresses unresolved-import
diagnostics for every import via the all-matching allowed-unresolved-imports
setting. Update the ty.toml setting to scope this exception more narrowly, using
a targeted pattern or list of known cases instead of the global catch-all, so ty
can still report real missing or misspelled imports. Focus the change on the
allowed-unresolved-imports entry in the ty configuration.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 495e3cc8-8234-42f6-8bdc-146050dd1069

📥 Commits

Reviewing files that changed from the base of the PR and between 15ca9ab and 20fe043.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (25)
  • .github/workflows/python_lint.yml
  • airbyte/_connector_base.py
  • airbyte/_message_iterators.py
  • airbyte/_processors/sql/postgres.py
  • airbyte/_processors/sql/snowflake.py
  • airbyte/_util/api_util.py
  • airbyte/_util/meta.py
  • airbyte/_util/name_normalizers.py
  • airbyte/caches/_utils/_cache_to_dest.py
  • airbyte/caches/base.py
  • airbyte/caches/motherduck.py
  • airbyte/cli/pyab.py
  • airbyte/cloud/sync_results.py
  • airbyte/datasets/_sql.py
  • airbyte/mcp/local.py
  • airbyte/progress.py
  • airbyte/secrets/google_gsm.py
  • airbyte/shared/catalog_providers.py
  • airbyte/shared/sql_processor.py
  • airbyte/shared/state_providers.py
  • airbyte/sources/base.py
  • airbyte/types.py
  • pyproject.toml
  • pyrefly.toml
  • ty.toml
💤 Files with no reviewable changes (1)
  • pyrefly.toml

@github-code-quality

github-code-quality Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: Python

Python / code-coverage/pytest-fast

The overall coverage in the branch is 67%. The coverage in the branch is 65%.

Show a code coverage summary of the most impacted files.
File d9f652f 72f4652 +/-
airbyte/_util/api_util.py 36% 37% +1%
airbyte/registry.py 70% 72% +2%
airbyte/mcp/_tool_utils.py 72% 77% +5%
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/int...ive/__init__.py 0% 100% +100%
airbyte/mcp/int...tive/_prefab.py 0% 100% +100%

Python / code-coverage/pytest-no-creds

The overall coverage in the branch is 67%. The coverage in the branch is 65%.

Show a code coverage summary of the most impacted files.
File d9f652f 72f4652 +/-
airbyte/_util/api_util.py 36% 37% +1%
airbyte/registry.py 70% 72% +2%
airbyte/mcp/_tool_utils.py 72% 77% +5%
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/int...ive/__init__.py 0% 100% +100%
airbyte/mcp/int...tive/_prefab.py 0% 100% +100%

Python / code-coverage/pytest

The overall coverage in the branch is 72%. The coverage in the branch is 71%.

Show a code coverage summary of the most impacted files.
File d9f652f 72f4652 +/-
airbyte/registry.py 70% 72% +2%
airbyte/mcp/_tool_utils.py 72% 77% +5%
airbyte/mcp/server.py 69% 76% +7%
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/int...ive/__init__.py 0% 100% +100%
airbyte/mcp/int...tive/_prefab.py 0% 100% +100%

Updated July 06, 2026 04:02 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

…omments

Co-Authored-By: AJ Steers <aj@airbyte.io>
Copilot AI review requested due to automatic review settings July 6, 2026 03:36
@aaronsteers Aaron ("AJ") Steers (aaronsteers) removed the request for review from Copilot July 6, 2026 03:36
Co-Authored-By: AJ Steers <aj@airbyte.io>
Copilot AI review requested due to automatic review settings July 6, 2026 03:37
@aaronsteers Aaron ("AJ") Steers (aaronsteers) removed the request for review from Copilot July 6, 2026 03:37

if output_file:
output_file.write_text(content) # pyrefly: ignore[unbound-name]
output_file.write_text(content)
return

syntax_highlighted = Syntax(content, format) # pyrefly: ignore[unbound-name]
syntax_highlighted = Syntax(content, format)
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