Source code for qudi.core.meta

# -*- coding: utf-8 -*-
"""
Definition of various metaclasses

.. Copyright (c) 2021, the qudi developers. See the AUTHORS.md file at the top-level directory of this
.. distribution and on <https://github.com/Ulm-IQO/qudi-core/>
..
.. This file is part of qudi.
..
.. Qudi is free software: you can redistribute it and/or modify it under the terms of
.. the GNU Lesser General Public License as published by the Free Software Foundation,
.. either version 3 of the License, or (at your option) any later version.
..
.. Qudi 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 Lesser General Public License for more details.
..
.. You should have received a copy of the GNU Lesser General Public License along with qudi.
.. If not, see <https://www.gnu.org/licenses/>.
"""

__all__ = ('ABCQObjectMeta', 'ModuleMeta', 'QObjectMeta', 'QudiObjectMeta')

from abc import ABCMeta
from PySide2.QtCore import QObject
from qudi.core.statusvariable import StatusVar
from qudi.core.connector import Connector
from qudi.core.configoption import ConfigOption


QObjectMeta = type(QObject)


[docs] class ABCQObjectMeta(ABCMeta, QObjectMeta): """Metaclass for abstract QObject subclasses.""" def __new__(mcs, name, bases, attributes): cls = super(ABCQObjectMeta, mcs).__new__(mcs, name, bases, attributes) # Compute set of abstract method names abstracts = { attr_name for attr_name, attr in attributes.items() if getattr(attr, '__isabstractmethod__', False) } for base in bases: for attr_name in getattr(base, '__abstractmethods__', set()): attr = getattr(cls, attr_name, None) if getattr(attr, '__isabstractmethod__', False): abstracts.add(attr_name) cls.__abstractmethods__ = frozenset(abstracts) return cls
[docs] class QudiObjectMeta(ABCQObjectMeta): """General purpose metaclass for abstract QObject subclasses that include qudi meta objects (Connector, StatusVar, ConfigOption). Collects all meta objects in new "_meta" class variable for easier access. """ def __new__(mcs, name, bases, attributes): cls = super().__new__(mcs, name, bases, attributes) meta = dict() # Collect qudi module meta attributes (Connector, StatusVar, ConfigOption) and put them # in the class variable dict "_meta" for easy bookkeeping and access. connectors = dict() status_vars = dict() config_opt = dict() for attr_name in dir(cls): attr = getattr(cls, attr_name, None) if isinstance(attr, Connector): connectors[attr_name] = attr elif isinstance(attr, StatusVar): status_vars[attr_name] = attr elif isinstance(attr, ConfigOption): config_opt[attr_name] = attr meta.update( { 'connectors': connectors, 'status_variables': status_vars, 'config_options': config_opt, } ) setattr(cls, '_meta', meta) return cls
[docs] class ModuleMeta(QudiObjectMeta): """Metaclass for all qudi modules (GUI, logic and hardware)""" def __new__(mcs, name, bases, attributes): cls = super().__new__(mcs, name, bases, attributes) # Determine module base key and add to _meta dict if getattr(cls, '_meta', None): for base in cls.mro(): if base.__name__ == 'GuiBase': cls._meta['base'] = 'gui' break elif base.__name__ == 'LogicBase': cls._meta['base'] = 'logic' break elif base.__name__ == 'Base': cls._meta['base'] = 'hardware' break return cls