Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/python_lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ jobs:
run: uv sync --group dev

# Job-specific step(s):
- name: Run Pyrefly Check
run: uv run pyrefly check
- name: Run ty Check
run: uv run ty check

public-api-import-guard:
name: Public API Import Guard
Expand Down
16 changes: 8 additions & 8 deletions airbyte/_connector_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,10 @@
content = json.dumps(self.config_spec, indent=2)

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

Check failure

Code scanning / CodeQL

Potentially uninitialized local variable Error

Local variable 'content' may be used before it is initialized.
return

syntax_highlighted = Syntax(content, format) # pyrefly: ignore[unbound-name]
syntax_highlighted = Syntax(content, format)

Check failure

Code scanning / CodeQL

Potentially uninitialized local variable Error

Local variable 'content' may be used before it is initialized.
rich.print(syntax_highlighted, file=sys.stderr if stderr else None)

@property
Expand Down Expand Up @@ -405,32 +405,32 @@
AirbyteConnectorFailedError: If a TRACE message of type ERROR is emitted.
"""
if message.type == Type.LOG:
self._print_info_message(message.log.message) # pyrefly: ignore[missing-attribute]
self._print_info_message(message.log.message) # ty: ignore[unresolved-attribute]
return

if (
message.type == Type.TRACE
and message.trace.type == TraceType.ERROR # pyrefly: ignore[missing-attribute]
and message.trace.type == TraceType.ERROR # ty: ignore[unresolved-attribute]
):
self._print_error_message(
message.trace.error.message # pyrefly: ignore[missing-attribute]
message.trace.error.message # ty: ignore[unresolved-attribute]
)
if raise_on_error:
raise exc.AirbyteConnectorFailedError(
connector_name=self.name,
message=message.trace.error.message, # pyrefly: ignore[missing-attribute]
message=message.trace.error.message, # ty: ignore[unresolved-attribute]
log_text=self._last_log_messages,
)
return

if (
message.type == Type.CONTROL
and message.control.type # pyrefly: ignore[missing-attribute]
and message.control.type # ty: ignore[unresolved-attribute]
== OrchestratorType.CONNECTOR_CONFIG
and self.config_change_callback is not None
):
self.config_change_callback(
message.control.connectorConfig.config # pyrefly: ignore[missing-attribute]
message.control.connectorConfig.config # ty: ignore[unresolved-attribute]
)
return

Expand Down
6 changes: 2 additions & 4 deletions airbyte/_message_iterators.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,7 @@ def generator() -> Generator[AirbyteMessage, None, None]:
if current_file_buffer is None:
try:
current_file = next(file_iterator)
current_file_buffer = file_opener(
current_file # pyrefly: ignore[bad-argument-type]
)
current_file_buffer = file_opener(current_file)
except StopIteration:
# No more files to read; Exit the loop
break
Expand All @@ -194,7 +192,7 @@ def generator() -> Generator[AirbyteMessage, None, None]:

try:
# Let Pydantic handle the JSON decoding from the raw string
yield ( # pyrefly: ignore[invalid-yield]
yield ( # ty: ignore[invalid-yield]
AirbyteMessage.model_validate_json(next_line),
current_file,
)
Expand Down
2 changes: 1 addition & 1 deletion airbyte/_processors/sql/postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,5 @@ class PostgresSqlProcessor(SqlProcessorBase):
file_writer_class = JsonlWriter
sql_config: PostgresConfig

normalizer = PostgresNormalizer # pyrefly: ignore[bad-override]
normalizer = PostgresNormalizer
"""A Postgres-specific name normalizer for table and column name normalization."""
4 changes: 1 addition & 3 deletions airbyte/_processors/sql/snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,7 @@ class SnowflakeSqlProcessor(SqlProcessorBase):
"""A Snowflake implementation of the cache."""

file_writer_class = JsonlWriter
type_converter_class: type[SnowflakeTypeConverter] = ( # pyrefly: ignore[bad-override]
SnowflakeTypeConverter
)
type_converter_class: type[SnowflakeTypeConverter] = SnowflakeTypeConverter
supports_merge_insert = True
sql_config: SnowflakeConfig

Expand Down
6 changes: 3 additions & 3 deletions airbyte/_util/api_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -1318,9 +1318,9 @@ def get_destination(
}

if destination_type in destination_mapping and raw_configuration is not None:
response.destination_response.configuration = destination_mapping[
destination_type # pyrefly: ignore[index-error]
](**raw_configuration)
response.destination_response.configuration = destination_mapping[destination_type](
**raw_configuration
)
return response.destination_response

raise AirbyteMissingResourceError(
Expand Down
2 changes: 1 addition & 1 deletion airbyte/_util/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def get_notebook_name() -> str | None:
@lru_cache
def get_vscode_notebook_name() -> str | None:
with suppress(Exception):
import IPython # noqa: PLC0415 # pyrefly: ignore[missing-import]
import IPython # noqa: PLC0415

return Path(
IPython.extract_module_locals()[1]["__vsc_ipynb_file__"],
Expand Down
2 changes: 1 addition & 1 deletion airbyte/_util/name_normalizers.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class LowerCaseNormalizer(NameNormalizerBase):

@staticmethod
@functools.cache
def normalize(name: str) -> str: # pyrefly: ignore[bad-override] # pyrefly decorator issue
def normalize(name: str) -> str:
"""Return the normalized name.

- All non-alphanumeric characters are replaced with underscores.
Expand Down
2 changes: 1 addition & 1 deletion airbyte/caches/_utils/_cache_to_dest.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def snowflake_cache_to_destination_configuration(
role=cache.role,
username=cache.username,
credentials=UsernameAndPassword(
password=cache.password, # pyrefly: ignore[bad-argument-type]
password=cache.password, # ty: ignore[invalid-argument-type]
),
)

Expand Down
2 changes: 1 addition & 1 deletion airbyte/caches/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ def _write_airbyte_message_stream(
state_writer=state_writer,
)
cache_processor.process_airbyte_messages(
messages=stdin, # pyrefly: ignore[bad-argument-type]
messages=stdin, # ty: ignore[invalid-argument-type]
write_strategy=write_strategy,
progress_tracker=progress_tracker,
)
Expand Down
2 changes: 1 addition & 1 deletion airbyte/caches/motherduck.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class MotherDuckConfig(DuckDBConfig):

database: str = Field()
api_key: SecretString = Field()
db_path: str = Field(default="md:") # pyrefly: ignore[bad-override]
db_path: str = Field(default="md:")
_paired_destination_name: str = "destination-motherduck"

@overrides
Expand Down
8 changes: 4 additions & 4 deletions airbyte/cli/pyab.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,10 @@ def _resolve_destination_job(


cli = App(
name="pyab", # pyrefly: ignore[unexpected-keyword]
help="PyAirbyte CLI.", # pyrefly: ignore[unexpected-keyword]
help_format="plaintext", # pyrefly: ignore[unexpected-keyword]
version_flags=[], # pyrefly: ignore[unexpected-keyword]
name="pyab",
help="PyAirbyte CLI.",
help_format="plaintext",
version_flags=[],
)


Expand Down
6 changes: 2 additions & 4 deletions airbyte/cloud/sync_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,7 @@ def get_full_log_text(self) -> str:
timestamp = event.get("timestamp", "")
level = event.get("level", "INFO")
message = event.get("message", "")
log_lines.append(
f"[{timestamp}] {level}: {message}" # pyrefly: ignore[bad-argument-type]
)
log_lines.append(f"[{timestamp}] {level}: {message}")
result = "\n".join(log_lines)
elif "logLines" in logs_data:
log_lines = logs_data["logLines"]
Expand Down Expand Up @@ -478,7 +476,7 @@ def stream_names(self) -> list[str]:
@property
def streams(
self,
) -> _SyncResultStreams: # pyrefly: ignore[unknown-name]
) -> _SyncResultStreams:
"""Return a mapping of stream names to `airbyte.CachedDataset` objects.

This is a convenience wrapper around the `stream_names`
Expand Down
2 changes: 1 addition & 1 deletion airbyte/datasets/_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def __init__(
# Coalesce False to None
stream_configuration = stream_configuration or None

super().__init__(stream_metadata=stream_configuration) # pyrefly: ignore[bad-argument-type]
super().__init__(stream_metadata=stream_configuration) # ty: ignore[invalid-argument-type]

@property
def stream_name(self) -> str:
Expand Down
4 changes: 1 addition & 3 deletions airbyte/mcp/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,9 +559,7 @@ def get_stream_previews(
)
source.set_config(config_dict)

streams_param: list[str] | Literal["*"] | None = resolve_list_of_strings(
streams
) # pyrefly: ignore[no-matching-overload]
streams_param: list[str] | Literal["*"] | None = resolve_list_of_strings(streams)
if streams_param and len(streams_param) == 1 and streams_param[0] == "*":
streams_param = "*"

Expand Down
8 changes: 4 additions & 4 deletions airbyte/progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,11 +321,11 @@ def tally_pending_writes(

update_period = 1 # Reset the update period to 1 before start.

for count, message in enumerate( # pyrefly: ignore[bad-assignment]
messages, # pyrefly: ignore[bad-argument-type]
for count, message in enumerate(
messages,
start=1,
):
yield message # pyrefly: ignore[invalid-yield]
yield message # ty: ignore[invalid-yield]
if isinstance(message, str):
# This is a string message, not an AirbyteMessage.
# For now at least, we don't need to pay the cost of parsing it.
Expand Down Expand Up @@ -585,7 +585,7 @@ def _log_read_metrics(self) -> None:
perf_metrics["stream_metrics"] = stream_metrics
log_dict["performance_metrics"] = perf_metrics

self._file_logger.info(json.dumps(log_dict)) # pyrefly: ignore[missing-attribute]
self._file_logger.info(json.dumps(log_dict))

perf_logger: BoundLogger = logs.get_global_stats_logger()
perf_logger.info(**log_dict)
Expand Down
2 changes: 1 addition & 1 deletion airbyte/secrets/google_gsm.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class GSMSecretHandle(SecretHandle):
labels.
"""

parent: GoogleGSMSecretManager # pyrefly: ignore[bad-override]
parent: GoogleGSMSecretManager

def _get_gsm_secret_object(self) -> secretmanager.Secret:
"""Get the `Secret` object from GSM."""
Expand Down
6 changes: 3 additions & 3 deletions airbyte/shared/catalog_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def __init__(
"""
self._catalog: ConfiguredAirbyteCatalog = self.validate_catalog(
configured_catalog
) # pyrefly: ignore[bad-assignment]
) # ty: ignore[invalid-assignment]

@staticmethod
def validate_catalog(catalog: ConfiguredAirbyteCatalog) -> None:
Expand All @@ -66,7 +66,7 @@ def validate_catalog(catalog: ConfiguredAirbyteCatalog) -> None:
if stream.sync_id is None:
stream.sync_id = 1 # This should ideally increment monotonically with each sync.

return catalog # pyrefly: ignore[bad-return]
return catalog # ty: ignore[invalid-return-type]

@property
def configured_catalog(self) -> ConfiguredAirbyteCatalog:
Expand Down Expand Up @@ -178,7 +178,7 @@ def get_cursor_key(
"""Return the cursor key for the given stream."""
return self.get_configured_stream_info(
stream_name
).cursor_field # pyrefly: ignore[bad-return]
).cursor_field # ty: ignore[invalid-return-type]

def resolve_write_method(
self,
Expand Down
11 changes: 4 additions & 7 deletions airbyte/shared/sql_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,9 @@ def __init__(
] = defaultdict(list, {})

self._setup()
self.file_writer = (
file_writer
or self.file_writer_class( # pyrefly: ignore[bad-instantiation]
cache_dir=cast("Path", temp_dir),
cleanup=temp_file_cleanup,
)
self.file_writer = file_writer or self.file_writer_class(
cache_dir=cast("Path", temp_dir),
cleanup=temp_file_cleanup,
)
self.type_converter = self.type_converter_class()
self._cached_table_definitions: dict[str, sqlalchemy.Table] = {}
Expand Down Expand Up @@ -315,7 +312,7 @@ def process_airbyte_messages(
This method assumes that the catalog is already registered with the processor.
"""
if not isinstance(write_strategy, WriteStrategy):
raise exc.AirbyteInternalError( # pyrefly: ignore[missing-attribute]
raise exc.AirbyteInternalError(
message="Invalid `write_strategy` argument. Expected instance of WriteStrategy.",
context={"write_strategy": write_strategy},
)
Expand Down
8 changes: 4 additions & 4 deletions airbyte/shared/state_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def state_message_artifacts(
if result is None:
raise exc.PyAirbyteInternalError(message="No state artifacts were declared.")

return result # pyrefly: ignore[bad-return]
return result # ty: ignore[invalid-return-type]

@property
def known_stream_names(
Expand Down Expand Up @@ -101,13 +101,13 @@ def get_stream_state(
"""Return the state message for the specified stream name."""
for state_message in self.state_message_artifacts:
if (
state_message.stream.stream_descriptor.name # pyrefly: ignore[missing-attribute]
state_message.stream.stream_descriptor.name # ty: ignore[unresolved-attribute]
== stream_name
):
return state_message # pyrefly: ignore[bad-return]
return state_message # ty: ignore[invalid-return-type]

if not_found != "raise":
return not_found # pyrefly: ignore[bad-return]
return not_found # ty: ignore[invalid-return-type]

raise exc.AirbyteStateNotFoundError(
message="State message not found.",
Expand Down
5 changes: 1 addition & 4 deletions airbyte/sources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -949,10 +949,7 @@ def _read_to_cache( # noqa: PLR0913 # Too many arguments
message="Invalid strategy",
context={
"write_strategy": write_strategy,
"available_strategies": [
s.value
for s in WriteStrategy # pyrefly: ignore[not-iterable]
],
"available_strategies": [s.value for s in WriteStrategy],
},
) from None

Expand Down
1 change: 0 additions & 1 deletion airbyte/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ def to_sql_type( # noqa: PLR0911 # Too many return statements
except SQLTypeConversionError:
print(f"Could not determine airbyte type from JSON schema: {json_schema_property_def}")
except KeyError:
# pyrefly: ignore[unbound-name]
print(f"Could not find SQL type for airbyte type: {airbyte_type}")
else:
# No exceptions were raised, so we can return the SQL type.
Expand Down
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ dev = [
"docker>=7.1.0,<8.0",
"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.

"pandas-stubs>=2.1.4.231218",
"pdoc>=16.0.0,<17.0",
"poethepoet>=0.26.1,<0.32.0",
Expand Down Expand Up @@ -140,11 +140,11 @@ filterwarnings = [ # syntax: "action:message_regex:category:module:line"
# [tool.ruff]
# Ruff moved to dedicated config file: `.ruff.toml`

# [tool.pyrefly]
# Pyrefly moved to dedicated config file: `pyrefly.toml`
# [tool.ty]
# ty moved to dedicated config file: `ty.toml`

[tool.mypy]
# Disable all mypy checks for this project since we use pyrefly instead
# Disable all mypy checks for this project since we use ty instead
ignore_errors = true

[tool.pyright]
Expand All @@ -162,7 +162,7 @@ coverage-report = { shell = "coverage report" }
coverage-html = { shell = "coverage html -d htmlcov && open htmlcov/index.html" }
coverage-reset = { shell = "coverage erase" }

check = { shell = "ruff check . && pyrefly check && pytest --collect-only -qq" }
check = { shell = "ruff check . && ty check && pytest --collect-only -qq" }

docs-generate = {env = {PDOC_ALLOW_EXEC = "1"}, cmd = "python -m docs.generate run"}
docs-preview = {shell = "poe docs-generate && open docs/generated/index.html"}
Expand Down
16 changes: 0 additions & 16 deletions pyrefly.toml

This file was deleted.

Loading
Loading