# Path: geomdl/exceptions.py
# class GeomdlException(Exception):
#     """ Custom exception for controlling geometric errors.
# 
#     The error details can be retrieved by querying ``data`` class member. The following snippet illustrates a sample
#     usage of this exception.
# 
#     .. code-example: python
# 
#         from geomdl import exceptions
# 
#         DEBUG = True
# 
#         # Catch the exception
#         try:
#             # Do something which can raise this exception
#         except GeomdlException as e:
#             print(e)
#             if DEBUG:
#                 print(e.data)
#             # Stop execution of the function
#             return
#     """
#     def __init__(self, msg, data=None):
#         super(GeomdlException, self).__init__(ERROR_PREFIX + msg)
#         self.data = data
# 
# Path: geomdl/_utilities.py
# def export(fn):
#     """ Export decorator
# 
#     Please refer to the following SO article for details: https://stackoverflow.com/a/35710527
#     """
#     mod = sys.modules[fn.__module__]
#     if hasattr(mod, '__all__'):
#         mod.__all__.append(fn.__name__)
#     else:
#         mod.__all__ = [fn.__name__]
#     return fn
# 
# def add_metaclass(metaclass):
#     """ Class decorator for creating a class with a metaclass.
# 
#     Taken from ``six`` library version 1.12.0. Copyright (c) 2010-2018 Benjamin Peterson.
#     ``six`` is licensed under the terms of MIT License.
# 
#     Please refer to the following GitHub repository for details: https://github.com/benjaminp/six
# 
#     :param metaclass: metaclass
#     """
#     def wrapper(cls):
#         orig_vars = cls.__dict__.copy()
#         slots = orig_vars.get('__slots__')
#         if slots is not None:
#             if isinstance(slots, str):
#                 slots = [slots]
#             for slots_var in slots:
#                 orig_vars.pop(slots_var)
#         orig_vars.pop('__dict__', None)
#         orig_vars.pop('__weakref__', None)
#         if hasattr(cls, '__qualname__'):
#             orig_vars['__qualname__'] = cls.__qualname__
#         return metaclass(cls.__name__, cls.__bases__, orig_vars)
#     return wrapper


import abc
import copy
from functools import reduce
from .exceptions import GeomdlException
from ._utilities import export, add_metaclass
        :param dkey: str
        """
        # Find the index
        idx = self.find_index(*args)
        # Return the attached data
        try:
            return self._pt_data[dkey][idx]
        except IndexError:
            return None
        except KeyError:
            return None

    def set_ptdata(self, adct, *args):
        """ Attaches the data to the control point.

        :param adct: attachment dictionary
        :param adct: dict
        """
        # Find the index
        idx = self.find_index(*args)
        # Attach the data to the control point
        try:
            for k, val in adct.items():
                if k in self._pt_data:
                    if isinstance(val, (list, tuple)):
                        for j, v in enumerate(val):
                            self._pt_data[k][idx][j] = v
                    else:
                        self._pt_data[k][idx] = val
                else:

# Path: geomdl/exceptions.py
# class GeomdlException(Exception):
#     """ Custom exception for controlling geometric errors.
# 
#     The error details can be retrieved by querying ``data`` class member. The following snippet illustrates a sample
#     usage of this exception.
# 
#     .. code-example: python
# 
#         from geomdl import exceptions
# 
#         DEBUG = True
# 
#         # Catch the exception
#         try:
#             # Do something which can raise this exception
#         except GeomdlException as e:
#             print(e)
#             if DEBUG:
#                 print(e.data)
#             # Stop execution of the function
#             return
#     """
#     def __init__(self, msg, data=None):
#         super(GeomdlException, self).__init__(ERROR_PREFIX + msg)
#         self.data = data
# 
# Path: geomdl/_utilities.py
# def export(fn):
#     """ Export decorator
# 
#     Please refer to the following SO article for details: https://stackoverflow.com/a/35710527
#     """
#     mod = sys.modules[fn.__module__]
#     if hasattr(mod, '__all__'):
#         mod.__all__.append(fn.__name__)
#     else:
#         mod.__all__ = [fn.__name__]
#     return fn
# 
# def add_metaclass(metaclass):
#     """ Class decorator for creating a class with a metaclass.
# 
#     Taken from ``six`` library version 1.12.0. Copyright (c) 2010-2018 Benjamin Peterson.
#     ``six`` is licensed under the terms of MIT License.
# 
#     Please refer to the following GitHub repository for details: https://github.com/benjaminp/six
# 
#     :param metaclass: metaclass
#     """
#     def wrapper(cls):
#         orig_vars = cls.__dict__.copy()
#         slots = orig_vars.get('__slots__')
#         if slots is not None:
#             if isinstance(slots, str):
#                 slots = [slots]
#             for slots_var in slots:
#                 orig_vars.pop(slots_var)
#         orig_vars.pop('__dict__', None)
#         orig_vars.pop('__weakref__', None)
#         if hasattr(cls, '__qualname__'):
#             orig_vars['__qualname__'] = cls.__qualname__
#         return metaclass(cls.__name__, cls.__bases__, orig_vars)
#     return wrapper


# Path: geomdl/control_points.py
import abc
import copy
from functools import reduce
from .exceptions import GeomdlException
from ._utilities import export, add_metaclass

        :param dkey: str
        """
        # Find the index
        idx = self.find_index(*args)
        # Return the attached data
        try:
            return self._pt_data[dkey][idx]
        except IndexError:
            return None
        except KeyError:
            return None

    def set_ptdata(self, adct, *args):
        """ Attaches the data to the control point.

        :param adct: attachment dictionary
        :param adct: dict
        """
        # Find the index
        idx = self.find_index(*args)
        # Attach the data to the control point
        try:
            for k, val in adct.items():
                if k in self._pt_data:
                    if isinstance(val, (list, tuple)):
                        for j, v in enumerate(val):
                            self._pt_data[k][idx][j] = v
                    else:
                        self._pt_data[k][idx] = val
                else:

                    raise GeomdlException("Invalid key: " + str(k))