Summary
EnvironmentConfig emits a DeprecationWarning for the memory and storage fields every time it is constructed, even when the caller uses the new memory_mb / storage_mb fields exclusively. The warning originates from Harbor's own handle_deprecated_fields validator, which accesses self.memory and self.storage to check for None — and Pydantic 2 emits a DeprecationWarning on attribute access for any field declared with Field(deprecated=...).
Net effect: any project that runs its test suite under python -W error::DeprecationWarning fails immediately on a clean Harbor 0.7.1 install, even with no use of deprecated fields anywhere in the code or task tomls.
Versions
- Harbor: 0.7.1
- Pydantic: 2.12.5
- Python: 3.14.3
Minimal repro
import warnings
warnings.simplefilter("error", DeprecationWarning)
from harbor.models.task.config import EnvironmentConfig
EnvironmentConfig(docker_image="alpine")
Result:
DeprecationWarning: Use 'memory_mb' instead. This field will be removed in a future version.
File ".../harbor/models/task/config.py", line 202, in handle_deprecated_fields
if self.memory is not None:
No deprecated field was set by the caller. The warning fires purely because the validator reads self.memory.
Root cause
harbor/models/task/config.py:
# line 165
memory: str | None = Field(
default=None,
deprecated="Use 'memory_mb' instead. This field will be removed in a future version.",
exclude=True,
)
storage: str | None = Field(
default=None,
deprecated="Use 'storage_mb' instead. This field will be removed in a future version.",
exclude=True,
)
# line 200
@model_validator(mode="after")
def handle_deprecated_fields(self) -> "EnvironmentConfig":
if self.memory is not None: # ← Pydantic raises DeprecationWarning here
...
if self.storage is not None: # ← and here
...
return self
Pydantic 2 wires Field(deprecated=...) such that any attribute read goes through a property that emits the warning. The if self.memory is not None: check inside the validator is itself an attribute access and therefore triggers it — regardless of whether the caller ever provided memory.
Expected behavior
Constructing EnvironmentConfig with only the supported fields (e.g. docker_image="alpine" or memory_mb=512) should not emit any DeprecationWarning. The warning should fire only when the caller actually provided memory= or storage=.
Proposed fix
Read the attribute via __dict__ (or self.model_dump(include={"memory", "storage"})) to bypass the Pydantic deprecation property, or check self.model_fields_set first:
@model_validator(mode="after")
def handle_deprecated_fields(self) -> "EnvironmentConfig":
# Bypass Field(deprecated=...) attribute property to avoid emitting
# our own DeprecationWarning when the caller didn't set the field.
memory = self.__dict__.get("memory")
if memory is not None:
warnings.warn(
"The 'memory' field is deprecated. Use 'memory_mb' instead.",
DeprecationWarning,
stacklevel=2,
)
self.memory_mb = self._parse_size_to_mb(memory)
self.__dict__["memory"] = None
storage = self.__dict__.get("storage")
if storage is not None:
warnings.warn(
"The 'storage' field is deprecated. Use 'storage_mb' instead.",
DeprecationWarning,
stacklevel=2,
)
self.storage_mb = self._parse_size_to_mb(storage)
self.__dict__["storage"] = None
return self
Equivalent alternative using model_fields_set:
if "memory" in self.model_fields_set:
memory = self.__dict__.get("memory")
...
Impact
Downstream projects that run -W error::DeprecationWarning for regression hygiene (catching real deprecations before they bite during dependency upgrades) cannot do so against Harbor 0.7.1 without filtering this specific warning. The workaround is fine short-term but adds noise to project configs.
Summary
EnvironmentConfigemits aDeprecationWarningfor thememoryandstoragefields every time it is constructed, even when the caller uses the newmemory_mb/storage_mbfields exclusively. The warning originates from Harbor's ownhandle_deprecated_fieldsvalidator, which accessesself.memoryandself.storageto check forNone— and Pydantic 2 emits aDeprecationWarningon attribute access for any field declared withField(deprecated=...).Net effect: any project that runs its test suite under
python -W error::DeprecationWarningfails immediately on a clean Harbor 0.7.1 install, even with no use of deprecated fields anywhere in the code or task tomls.Versions
Minimal repro
Result:
No deprecated field was set by the caller. The warning fires purely because the validator reads
self.memory.Root cause
harbor/models/task/config.py:Pydantic 2 wires
Field(deprecated=...)such that any attribute read goes through a property that emits the warning. Theif self.memory is not None:check inside the validator is itself an attribute access and therefore triggers it — regardless of whether the caller ever providedmemory.Expected behavior
Constructing
EnvironmentConfigwith only the supported fields (e.g.docker_image="alpine"ormemory_mb=512) should not emit anyDeprecationWarning. The warning should fire only when the caller actually providedmemory=orstorage=.Proposed fix
Read the attribute via
__dict__(orself.model_dump(include={"memory", "storage"})) to bypass the Pydantic deprecation property, or checkself.model_fields_setfirst:Equivalent alternative using
model_fields_set:Impact
Downstream projects that run
-W error::DeprecationWarningfor regression hygiene (catching real deprecations before they bite during dependency upgrades) cannot do so against Harbor 0.7.1 without filtering this specific warning. The workaround is fine short-term but adds noise to project configs.