shahar1 commented on code in PR #66979:
URL: https://github.com/apache/airflow/pull/66979#discussion_r3246231727


##########
pyproject.toml:
##########
@@ -653,6 +653,7 @@ extend-select = [
     "B004", # Checks for use of hasattr(x, "__call__") and replaces it with 
callable(x)
     "B006", # Checks for uses of mutable objects as function argument defaults.
     "B007", # Checks for unused variables in the loop
+    "B008", # Do not perform function call in argument defaults (use 
extend-immutable-calls for FastAPI DI)

Review Comment:
   Verified locally with `ruff 0.15.12`: B008 does **not** flag function-call 
defaults when the parameter has a type annotation. `def f(x = 
conf.getboolean(...))` is caught; `def f(x: bool = conf.getboolean(...))` is 
**not**. The remaining `deferrable: bool = conf.getboolean(...)` defaults in 
providers and `authorization: str = Header(...)` defaults in 
`providers/edge3/.../auth.py` are all annotated, so they slip past the rule and 
CI passes (current run: 
https://github.com/apache/airflow/actions/runs/25902711928).
   
   The annotated-call gap is a real footgun in ruff's implementation that's 
worth a follow-up — but it doesn't block enabling the rule for the un-annotated 
violations this PR already fixes.
   
   ---
   Drafted-by: Claude Code (Opus 4.7); reviewed by @shahar1 before posting



##########
providers/google/src/airflow/providers/google/cloud/hooks/vertex_ai/ray.py:
##########
@@ -115,7 +115,7 @@ def create_ray_cluster(
         """
         aiplatform.init(project=project_id, location=location, 
credentials=self.get_credentials())
         cluster_path = vertex_ray.create_ray_cluster(
-            head_node_type=head_node_type,
+            head_node_type=head_node_type or resources.Resources(),

Review Comment:
   Fixed in 7f41000182 — switched to `head_node_type if head_node_type is not 
None else resources.Resources()` to match the operator's behavior and avoid 
silently replacing explicit falsy values.
   
   ---
   Drafted-by: Claude Code (Opus 4.7); reviewed by @shahar1 before posting



##########
task-sdk/src/airflow/sdk/bases/sensor.py:
##########
@@ -128,6 +128,8 @@ def __init__(
         super().__init__(**kwargs)
         self.poke_interval = 
self._coerce_poke_interval(poke_interval).total_seconds()
         self.soft_fail = soft_fail
+        if timeout is None:
+            timeout = conf.getfloat("sensors", "default_timeout")

Review Comment:
   Added in 7f41000182 — 
`TestBaseSensor.test_sensor_timeout_default_read_from_conf_at_instantiation` 
constructs `DummySensor` with no `timeout` under `conf_vars({("sensors", 
"default_timeout"): "12345"})` and asserts the value is picked up at 
instantiation. Two config values are tested to confirm the read happens 
per-call, not at import time.
   
   ---
   Drafted-by: Claude Code (Opus 4.7); reviewed by @shahar1 before posting



##########
task-sdk/src/airflow/sdk/definitions/operator_resources.py:
##########
@@ -125,15 +125,15 @@ class Resources:
 
     def __init__(
         self,
-        cpus=conf.getint("operators", "default_cpus"),
-        ram=conf.getint("operators", "default_ram"),
-        disk=conf.getint("operators", "default_disk"),
-        gpus=conf.getint("operators", "default_gpus"),
+        cpus=None,
+        ram=None,
+        disk=None,
+        gpus=None,
     ):
-        self.cpus = CpuResource(cpus)
-        self.ram = RamResource(ram)
-        self.disk = DiskResource(disk)
-        self.gpus = GpuResource(gpus)
+        self.cpus = CpuResource(cpus if cpus is not None else 
conf.getint("operators", "default_cpus"))
+        self.ram = RamResource(ram if ram is not None else 
conf.getint("operators", "default_ram"))
+        self.disk = DiskResource(disk if disk is not None else 
conf.getint("operators", "default_disk"))
+        self.gpus = GpuResource(gpus if gpus is not None else 
conf.getint("operators", "default_gpus"))

Review Comment:
   Added in 7f41000182:
   
   - `TestResources.test_defaults_read_from_conf_at_instantiation` — confirms 
`Resources()` with no args reads 
`operators.default_cpus|default_ram|default_disk|default_gpus` at construction 
time.
   - `TestResources.test_falsy_zero_values_are_preserved` — confirms explicit 
`0` for any field is not replaced by the config default (only `None` falls back 
to config).
   
   ---
   Drafted-by: Claude Code (Opus 4.7); reviewed by @shahar1 before posting



##########
providers/google/src/airflow/providers/google/cloud/transfers/s3_to_gcs.py:
##########
@@ -178,7 +178,11 @@ def __init__(
         self.verify = verify
         self.gzip = gzip
         self.google_impersonation_chain = google_impersonation_chain
-        self.deferrable = deferrable
+        self.deferrable = (
+            deferrable
+            if deferrable is not None
+            else conf.getboolean("operators", "default_deferrable", 
fallback=False)
+        )

Review Comment:
   Added in 7f41000182:
   
   - `test_deferrable_default_read_from_conf_at_instantiation` — 
`S3ToGCSOperator` without an explicit `deferrable` reads 
`operators.default_deferrable` at construction time (both `True` and `False` 
config values verified).
   - `test_deferrable_explicit_false_overrides_truthy_conf` — passing 
`deferrable=False` while the config says `True` keeps the explicit value, 
confirming only `None` falls back to config.
   
   ---
   Drafted-by: Claude Code (Opus 4.7); reviewed by @shahar1 before posting



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to