Source code for pypath.core.attrs
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# This file is part of the `pypath` python module
#
# Copyright 2014-2023
# EMBL, EMBL-EBI, Uniklinik RWTH Aachen, Heidelberg University
#
# Authors: see the file `README.rst`
# Contact: Dénes Türei (turei.denes@gmail.com)
#
# Distributed under the GPLv3 License.
# See accompanying file LICENSE.txt or copy at
# https://www.gnu.org/licenses/gpl-3.0.html
#
# Website: https://pypath.omnipathdb.org/
#
from future.utils import iteritems
import json
import itertools
import pypath.share.common as common
[docs]
class AttributeHandler(object):
"""
Base class for other classes which carry custom attributes (data) in a
dedicated dict under the `attrs` attribute.
"""
__slots__ = [
'attrs',
]
[docs]
def __init__(self, attrs = None, **kwargs):
self.attrs = self._add_kwargs(attrs, **kwargs)
[docs]
def update_attrs(self, attrs = None, **kwargs):
"""
Updates the attributes stored here. The attributes with identical
keys are merged using the :py:func:`pypath.share.common.combine_attrs`
function.
The new attributes can be provided three ways: an object with an
attribute called `attrs`; a dictionary of attributes; or the
attributes as keyword arguments.
"""
if hasattr(attrs, 'attrs'):
attrs = attrs.attrs
self._update_attrs(attrs, **kwargs)
def _update_attrs(self, attrs = None, **kwargs):
attrs = self._add_kwargs(attrs, **kwargs)
for key, val in iteritems(attrs):
if key in self.attrs:
self.attrs[key] = common.combine_attrs((self.attrs[key], val))
else:
self.attrs[key] = val
@staticmethod
def _add_kwargs(attrs = None, **kwargs):
attrs = attrs or {}
attrs.update(kwargs)
return attrs
def __iadd__(self, other):
self.update_attrs(other)
return self
def __add__(self, other):
new = self.__copy__()
new.update_attrs(other.attrs)
return new
def __copy__(self):
return self.__class__(self.attrs.copy())
def __iter__(self):
return iteritems(self.attrs)
[docs]
def serialize(self, **kwargs):
"""
Generates a JSON string with the full contents of the attributes,
without any whitespace or line break.
Returns
(str): The attributes JSON serialized.
"""
return self._serialize(self.attrs, **kwargs)
@classmethod
def _serialize(
cls,
attrs,
top_key_prefix = False,
prefix_sep = '_',
**kwargs
):
if not attrs:
return ''
param = {
'indent': None,
'separators': (',', ':'),
}
param.update(kwargs)
default = param.pop('default', lambda x: x)
param['default'] = (
lambda x:
# sets are not serializable by the json module
# hence we always convert them to lists
list(x)
if isinstance(x, set) else
# additional defaults included here
default
)
if top_key_prefix:
attrs = dict(
item
for top_key, val in iteritems(attrs)
for item in cls._add_prefix(val, top_key, sep = prefix_sep)
)
return json.dumps(attrs, **param)
@staticmethod
def _add_prefix(d, prefix, sep = '_'):
d = d if isinstance(d, dict) else d.attrs
for key, val in iteritems(d):
yield (
'%s%s%s' % (prefix, sep, key),
val
)
def __str__(self):
return self.serialize()
def __len__(self):
return len(self.attrs)
def __contains__(self, other):
return other in self.attrs
def __getitem__(self, other):
return self.attrs[other] if other in self.attrs else None