blob: e218f9f89b5f2af4f3935efcd7490554a70a3eea [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from functools import cached_property
from pydantic import BaseModel
class IcebergBaseModel(BaseModel):
"""
This class extends the Pydantic BaseModel to set default values by overriding them.
This is because we always want to set by_alias to True. In Python, the dash can't
be used in variable names, and this is used throughout the Iceberg spec.
The same goes for exclude_none, if a field is None we want to omit it from
serialization, for example, the doc attribute on the NestedField object.
Default non-null values will be serialized.
This is recommended by Pydantic:
https://pydantic-docs.helpmanual.io/usage/model_config/#change-behaviour-globally
"""
class Config:
keep_untouched = (cached_property,)
allow_population_by_field_name = True
frozen = True
def dict(self, exclude_none: bool = True, **kwargs):
return super().dict(exclude_none=exclude_none, **kwargs)
def json(self, exclude_none: bool = True, by_alias: bool = True, **kwargs):
# A small trick to exclude private properties. Properties are serialized by pydantic,
# regardless if they start with an underscore.
# This will look at the dict, and find the fields and exclude them
exclude = set.union(
{field for field in self.__dict__ if field.startswith("_") and not field == "__root__"}, kwargs.get("exclude", set())
)
return super().json(exclude_none=exclude_none, exclude=exclude, by_alias=by_alias, **kwargs)