Source code for javaproperties.propclass

from collections.abc import Mapping as MappingABC
from typing import (
    Any,
    BinaryIO,
    Dict,
    IO,
    Iterable,
    Iterator,
    Mapping,
    MutableMapping,
    Optional,
    Set,
    TextIO,
    Tuple,
    TypeVar,
    Union,
)
from .reading import load
from .writing import dump
from .xmlprops import dump_xml, load_xml

T = TypeVar("T")


[docs]class Properties(MutableMapping[str, str]): """ A port of |java8properties|_ that tries to match its behavior as much as is Pythonically possible. `Properties` behaves like a normal `~collections.abc.MutableMapping` class (i.e., you can do ``props[key] = value`` and so forth), except that it may only be used to store `str` values. Two `Properties` instances compare equal iff both their key-value pairs and :attr:`defaults` attributes are equal. When comparing a `Properties` instance to any other type of mapping, only the key-value pairs are considered. .. versionchanged:: 0.5.0 `Properties` instances can now compare equal to `dict`\\s and other mapping types :param data: A mapping or iterable of ``(key, value)`` pairs with which to initialize the `Properties` instance. All keys and values in ``data`` must be text strings. :type data: mapping or `None` :param Optional[Properties] defaults: a set of default properties that will be used as fallback for `getProperty` .. |java8properties| replace:: Java 8's ``java.util.Properties`` .. _java8properties: https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html """ def __init__( self, data: Union[None, Mapping[str, str], Iterable[Tuple[str, str]]] = None, defaults: Optional["Properties"] = None, ) -> None: self.data: Dict[str, str] = {} #: A `Properties` subobject used as fallback for `getProperty`. Only #: `getProperty`, `propertyNames`, `stringPropertyNames`, and `__eq__` #: use this attribute; all other methods (including the standard #: mapping methods) ignore it. self.defaults = defaults if data is not None: self.update(data) def __getitem__(self, key: str) -> str: return self.data[key] def __setitem__(self, key: str, value: str) -> None: self.data[key] = value def __delitem__(self, key: str) -> None: del self.data[key] def __iter__(self) -> Iterator[str]: return iter(self.data) def __len__(self) -> int: return len(self.data) def __repr__(self) -> str: return ( "{0.__module__}.{0.__name__}({1.data!r}, defaults={1.defaults!r})".format( type(self), self ) ) def __eq__(self, other: Any) -> bool: if isinstance(other, Properties): return self.data == other.data and self.defaults == other.defaults elif isinstance(other, MappingABC): return dict(self) == other else: return NotImplemented
[docs] def getProperty( self, key: str, defaultValue: Optional[T] = None ) -> Union[str, T, None]: """ Fetch the value associated with the key ``key`` in the `Properties` instance. If the key is not present, `defaults` is checked, and then *its* `defaults`, etc., until either a value for ``key`` is found or the next `defaults` is `None`, in which case `defaultValue` is returned. :param str key: the key to look up the value of :param Any defaultValue: the value to return if ``key`` is not found in the `Properties` instance :rtype: str (if ``key`` was found) """ try: return self[key] except KeyError: if self.defaults is not None: return self.defaults.getProperty(key, defaultValue) else: return defaultValue
[docs] def load(self, inStream: IO) -> None: """ Update the `Properties` instance with the entries in a ``.properties`` file or file-like object. ``inStream`` may be either a text or binary filehandle, with or without universal newlines enabled. If it is a binary filehandle, its contents are decoded as Latin-1. .. versionchanged:: 0.5.0 Invalid ``\\uXXXX`` escape sequences will now cause an `InvalidUEscapeError` to be raised :param IO inStream: the file from which to read the ``.properties`` document :return: `None` :raises InvalidUEscapeError: if an invalid ``\\uXXXX`` escape sequence occurs in the input """ self.data.update(load(inStream))
[docs] def propertyNames(self) -> Iterator[str]: r""" Returns a generator of all distinct keys in the `Properties` instance and its `defaults` (and its `defaults`\’s `defaults`, etc.) in unspecified order :rtype: Iterator[str] """ for k in self.data: yield k if self.defaults is not None: for k in self.defaults.propertyNames(): if k not in self.data: yield k
[docs] def setProperty(self, key: str, value: str) -> None: """Equivalent to ``self[key] = value``""" self[key] = value
[docs] def store(self, out: TextIO, comments: Optional[str] = None) -> None: """ Write the `Properties` instance's entries (in unspecified order) in ``.properties`` format to ``out``, including the current timestamp. :param TextIO out: A file-like object to write the properties to. It must have been opened as a text file with a Latin-1-compatible encoding. :param Optional[str] comments: If non-`None`, ``comments`` will be written to ``out`` as a comment before any other content :return: `None` """ dump(self.data, out, comments=comments)
[docs] def stringPropertyNames(self) -> Set[str]: r""" Returns a `set` of all keys in the `Properties` instance and its `defaults` (and its `defaults`\ ’s `defaults`, etc.) :rtype: Set[str] """ names = set(self.data) if self.defaults is not None: names.update(self.defaults.stringPropertyNames()) return names
[docs] def loadFromXML(self, inStream: IO) -> None: """ Update the `Properties` instance with the entries in the XML properties file ``inStream``. Beyond basic XML well-formedness, `loadFromXML` only checks that the root element is named ``properties`` and that all of its ``entry`` children have ``key`` attributes; no further validation is performed. :param IO inStream: the file from which to read the XML properties document :return: `None` :raises ValueError: if the root of the XML tree is not a ``<properties>`` tag or an ``<entry>`` element is missing a ``key`` attribute """ self.data.update(load_xml(inStream))
[docs] def storeToXML( self, out: BinaryIO, comment: Optional[str] = None, encoding: str = "UTF-8", ) -> None: """ Write the `Properties` instance's entries (in unspecified order) in XML properties format to ``out``. :param BinaryIO out: a file-like object to write the properties to :param Optional[str] comment: if non-`None`, ``comment`` will be output as a ``<comment>`` element before the ``<entry>`` elements :param str encoding: the name of the encoding to use for the XML document (also included in the XML declaration) :return: `None` """ dump_xml(self.data, out, comment=comment, encoding=encoding)
[docs] def copy(self) -> "Properties": """ .. versionadded:: 0.5.0 Create a shallow copy of the mapping. The copy's `defaults` attribute will be the same instance as the original's `defaults`. """ return type(self)(self.data, self.defaults)