Containers
ExtendedString, ExtendedDict, ExtendedList, ExtendedTuple, and ExtendedSet containers. ExtendedData is their common root and polymorphic constructor: callers can use one entrypoint while still receiving the concrete extended type for the incoming value.Tier 2 wraps Python data shapes with shape-specific ExtendedString, ExtendedDict, ExtendedList, ExtendedTuple, and ExtendedSet containers. ExtendedData is their common root and polymorphic constructor: callers can use one entrypoint while still receiving the concrete extended type for the incoming value.
Construction and mutation promote nested values, so method chains survive normal Python literals.
from extended_data import ExtendedData, ExtendedDict, ExtendedList, ExtendedString
payload = ExtendedDict({"service": {"name": "api"}, "tags": ["api", "api", ""]})
generic = ExtendedData(payload).merge({"service": {"enabled": True}})
print(payload["service"]["name"].upper_first())
print(generic.as_builtin()["service"]["enabled"])
print(payload["tags"].compact().deduplicate())
print(ExtendedString("HTTP Response Value").to_snake_case())Polymorphic ExtendedData
Use ExtendedData at file, API, workflow, and vendor boundaries where the payload may be a mapping today, a list tomorrow, or a scalar status value from a different provider. The constructor returns the concrete extended subtype when one applies, so normal Python collection behavior remains native rather than proxied.
from extended_data import ExtendedData, ExtendedDict, ExtendedList, ExtendedString
vendor = ExtendedData({"vendor": "google", "payload": {"names": ["alpha"]}})
vendor["enabled"] = "true"
assert type(vendor) is ExtendedDict
assert isinstance(vendor, ExtendedData)
assert vendor.shape == "mapping"
assert vendor.get("vendor").upper_first() == "Google"
assert vendor["payload"]["names"][0].upper_first() == "Alpha"
merged = vendor.merge({"payload": {"region": "us-east-1"}})
assert merged.as_builtin()["payload"]["region"] == "us-east-1"
assert type(ExtendedData([{"name": "api"}]).append({"name": "worker"})) is ExtendedList
assert type(ExtendedData("HTTP Response Value")) is ExtendedStringThe common root exposes broad shape predicates without forcing dict-only code paths:
assert ExtendedData("HTTP Response Value").is_string
assert ExtendedData([{"name": "api"}]).is_sequence
assert ExtendedData({"prod", "api"}).is_set
assert ExtendedData(42).is_scalar
assert ExtendedData().is_noneDownstream packages can subclass ExtendedData for additive facades without being collapsed by the root factory. Store the promoted payload with ExtendedData(value) and keep provider or runtime behavior on the subclass:
class ProviderData(ExtendedData):
def __init__(self, value, *, provider):
self.provider = provider
self._data = ExtendedData(value)
@property
def value(self):
return self._data
provider_data = ProviderData({"service": {"name": "api"}}, provider="vendor")
assert type(provider_data) is ProviderData
assert provider_data.shape == "mapping"
assert provider_data["service"]["name"].upper_first() == "Api"Facades that need to keep the same outer identity while changing shape should override cast() and replace their internal ExtendedData value.
It also provides shared data-boundary helpers:
decoded = ExtendedData.decode('{"service": {"name": "api"}}', suffix="json")
loaded = ExtendedData.read("config/service.yaml")
result = loaded.sync_to_file("build/service.json", encoding="json")
assert decoded["service"]["name"].upper_first() == "Api"
print(result.changed)Promotion and Lowering
from extended_data import extend_data, to_builtin
data = extend_data({"outer": {"inner": ["api"]}})
assert data["outer"]["inner"][0].upper_first() == "Api"
plain = to_builtin(data)
assert plain == {"outer": {"inner": ["api"]}}Tuples remain tuple-shaped when promoted and lowered. Sets stay set-shaped. Mapping keys are lowered before export so JSON, YAML, TOML, and HCL encoders can hand data to their underlying format libraries safely.
