blob: 26e8d0a16655db3248dde592b0b4952353cf1b56 [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 typing import Optional, Any, Type, Union, Generic, TypeVar
from dataclasses import dataclass
@dataclass(frozen=True)
class Description:
"""Configuration option description."""
text: str
@staticmethod
def builder() -> 'DescriptionBuilder':
"""Create a description builder."""
return DescriptionBuilder()
class DescriptionBuilder:
"""Builder for Description objects."""
def __init__(self):
self._text = ""
def text(self, text: str) -> 'DescriptionBuilder':
"""Set the description text."""
self._text = text
return self
def build(self) -> Description:
"""Build the Description object."""
return Description(text=self._text)
T = TypeVar('T')
class ConfigOption(Generic[T]):
"""
A ConfigOption describes a configuration parameter. It encapsulates the configuration
key, deprecated older versions of the key, and an optional default value for the configuration
parameter.
ConfigOptions are built via the ConfigOptions class. Once created, a config
option is immutable.
"""
EMPTY_DESCRIPTION = Description(text="")
def __init__(self,
key: str,
clazz: Type,
description: Optional[Description] = None,
default_value: Any = None):
"""
Creates a new config option with fallback keys.
Args:
key: The current key for that config option
clazz: Type of the ConfigOption value
description: Description for that option
default_value: The default value for this option
"""
if not key:
raise ValueError("Key must not be null.")
self._key = key
self._clazz = clazz
self._description = description or self.EMPTY_DESCRIPTION
self._default_value = default_value
def key(self) -> str:
"""Gets the configuration key."""
return self._key
def get_clazz(self) -> Type:
"""Gets the type class of this config option."""
return self._clazz
def description(self) -> Description:
"""Returns the description of this option."""
return self._description
def has_default_value(self) -> bool:
"""Checks if this option has a default value."""
return self._default_value is not None
def default_value(self) -> Any:
"""Returns the default value, or None if there is no default value."""
return self._default_value
def with_description(self, description: Union[str, Description]) -> 'ConfigOption':
"""
Creates a new config option, using this option's key and default value, and adding the given
description. The given description is used when generation the configuration documentation.
Args:
description: The description for this option.
Returns:
A new config option, with given description.
"""
if isinstance(description, str):
desc = Description.builder().text(description).build()
else:
desc = description
return ConfigOption(
key=self._key,
clazz=self._clazz,
description=desc,
default_value=self._default_value,
)
def __eq__(self, other) -> bool:
"""Check equality with another ConfigOption."""
if not isinstance(other, ConfigOption):
return False
return (self._key == other._key and
self._default_value == other._default_value)
def __hash__(self) -> int:
"""Calculate hash code."""
return hash((self._key, self._default_value))
def __str__(self) -> str:
"""String representation of the config option."""
return f"key: '{self._key}'; default_value: {self._default_value}"