Source code for attributes
#
##
## SPDX-FileCopyrightText: © 2007-2023 Benedict Verhegghe <bverheg@gmail.com>
## SPDX-License-Identifier: GPL-3.0-or-later
##
## This file is part of pyFormex 3.4 (Thu Nov 16 18:07:39 CET 2023)
## pyFormex is a tool for generating, manipulating and transforming 3D
## geometrical models by sequences of mathematical operations.
## Home page: https://pyformex.org
## Project page: https://savannah.nongnu.org/projects/pyformex/
## Development: https://gitlab.com/bverheg/pyformex
## Distributed under the GNU General Public License version 3 or later.
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see http://www.gnu.org/licenses/.
##
"""Attributes
This module defines a general class for adding extra attributes to
other objects without cluttering the name space.
"""
from pyformex.mydict import Dict
[docs]class Attributes(Dict):
"""A general class for holding attributes.
This class is a versatile :term:`mapping` class for objects that need
a customizable set of attributes, while avoiding a wildly expanding
name space.
The class derives from :class:`Dict` and therefore has key lookup
via normal dict key mechanism or via attribute syntax or via
function call. It also provides a default_factory to lookup missing
keys.
The difference with the :class:`Dict` class are:
- The function call can also be used to populate or update the
contents of the Mapping.
- By default, a default_factory is set returning None for any
missing key.
- Giving an attribute the value None removes it from the Mapping.
Parameters
----------
default_factory: callable, optional
If provided, missing keys will be looked up by a call to the
default_factory.
args, kargs: other positional and keyword arguments
Any other arguments are passed to the dict initialization.
Notes
-----
While setting a single item to None will remove the item from the
Attributes, None values can be entered using the update() method.
The parameter order is different from previous implementation of
this class. This was done for consistency with the Dict and CDict
classes.
Examples
--------
>>> A = Attributes()
>>> A
Attributes({})
>>> A(color='red',alpha=0.7,ontop=True)
>>> A
Attributes({'color': 'red', 'alpha': 0.7, 'ontop': True})
>>> A['alpha'] = 0.8
>>> A.color = 'blue'
>>> A.ontop = None # remove 'ontop'
>>> A
Attributes({'color': 'blue', 'alpha': 0.8})
>>> A = Attributes({'alpha': 0.8, 'color': 'blue'})
>>> A.ontop is None
True
Create another Attributes with A as default, override color:
>>> B = Attributes(default_factory=A, color='green')
>>> B
Attributes({'color': 'green'})
>>> B.color, B.alpha # alpha found in A
('green', 0.8)
>>> A.clear()
>>> A
Attributes({})
>>> A['alpha'], A.alpha, A('alpha') # all mechanisms still working
(None, None, None)
>>> B['alpha'], B.alpha, B('alpha')
(None, None, None)
>>> B(color=None,alpha=1.0) # remove and change in 1 operation
>>> B
Attributes({'alpha': 1.0})
>>> B.update(color=None) # update can be used to enter None values.
>>> B
Attributes({'alpha': 1.0, 'color': None})
>>> B['alpha'] = None
>>> B
Attributes({'color': None})
"""
def __init__(self, default_factory=Dict.returnNone, *args, **kargs):
if default_factory is None or callable(default_factory):
pass
elif len(args) == 0:
args = [default_factory]
default_factory = Dict.returnNone
Dict.__init__(self, default_factory, *args, **kargs)
# with args: key lookup
# with kargs: set values
def __call__(self, *args, **kargs):
if len(args) > 0:
# This is required to make the default_factory work
return self[args[0]]
else:
for k in kargs:
setattr(self, k, kargs[k])
# Remove items when value is set to None
def __setitem__(self, key, value):
if value is None:
if key in self:
del self[key]
else:
Dict.__setitem__(self, key, value)
__setattr__ = __setitem__
# End