meerschaum.connectors.Connector

Define the parent Connector class.

  1#! /usr/bin/env python
  2# -*- coding: utf-8 -*-
  3# vim:fenc=utf-8
  4
  5"""
  6Define the parent `Connector` class.
  7"""
  8
  9from __future__ import annotations
 10import abc
 11import copy
 12from meerschaum.utils.typing import Iterable, Optional, Any, Union, List, Dict
 13
 14class InvalidAttributesError(Exception):
 15    """
 16    Raised when the incorrect attributes are set in the Connector.
 17    """
 18
 19class Connector(metaclass=abc.ABCMeta):
 20    """
 21    The base connector class to hold connection attributes,
 22    """
 23    def __init__(
 24            self,
 25            type: Optional[str] = None,
 26            label: Optional[str] = None,
 27            **kw: Any
 28        ):
 29        """
 30        Parameters
 31        ----------
 32        type: str
 33            The `type` of the connector (e.g. `sql`, `api`, `plugin`).
 34
 35        label: str
 36            The `label` for the connector.
 37
 38        Run `mrsm edit config` and to edit connectors in the YAML file:
 39
 40        ```
 41        meerschaum:
 42            connections:
 43                {type}:
 44                    {label}:
 45                        ### attributes go here
 46        ```
 47
 48        """
 49        self._original_dict = copy.deepcopy(self.__dict__)
 50        self._set_attributes(type=type, label=label, **kw)
 51        self.verify_attributes(getattr(self, 'REQUIRED_ATTRIBUTES', None))
 52
 53    def _reset_attributes(self):
 54        self.__dict__ = self._original_dict
 55
 56    def _set_attributes(
 57            self,
 58            *args,
 59            inherit_default: bool = True,
 60            **kw: Any
 61        ):
 62        from meerschaum.config.static import STATIC_CONFIG
 63        from meerschaum.utils.warnings import error
 64
 65        self._attributes = {}
 66
 67        default_label = STATIC_CONFIG['connectors']['default_label']
 68
 69        ### NOTE: Support the legacy method of explicitly passing the type.
 70        label = kw.get('label', None)
 71        if label is None:
 72            if len(args) == 2:
 73                label = args[1]
 74            elif len(args) == 0:
 75                label = None
 76            else:
 77                label = args[0]
 78
 79        if label == 'default':
 80            error(
 81                f"Label cannot be 'default'. Did you mean '{default_label}'?",
 82                InvalidAttributesError,
 83            )
 84        self.__dict__['label'] = label
 85
 86        from meerschaum.config import get_config
 87        conn_configs = copy.deepcopy(get_config('meerschaum', 'connectors'))
 88        connector_config = copy.deepcopy(get_config('system', 'connectors'))
 89
 90        ### inherit attributes from 'default' if exists
 91        if inherit_default:
 92            inherit_from = 'default'
 93            if self.type in conn_configs and inherit_from in conn_configs[self.type]:
 94                _inherit_dict = copy.deepcopy(conn_configs[self.type][inherit_from])
 95                self._attributes.update(_inherit_dict)
 96
 97        ### load user config into self._attributes
 98        if self.type in conn_configs and self.label in conn_configs[self.type]:
 99            self._attributes.update(conn_configs[self.type][self.label])
100
101        ### load system config into self._sys_config
102        ### (deep copy so future Connectors don't inherit changes)
103        if self.type in connector_config:
104            self._sys_config = copy.deepcopy(connector_config[self.type])
105
106        ### add additional arguments or override configuration
107        self._attributes.update(kw)
108
109        ### finally, update __dict__ with _attributes.
110        self.__dict__.update(self._attributes)
111
112
113    def verify_attributes(
114            self,
115            required_attributes: Optional[List[str]] = None,
116            debug: bool = False
117        ) -> None:
118        """
119        Ensure that the required attributes have been met.
120        
121        The Connector base class checks the minimum requirements.
122        Child classes may enforce additional requirements.
123
124        Parameters
125        ----------
126        required_attributes: Optional[List[str]], default None
127            Attributes to be verified. If `None`, default to `['label']`.
128
129        debug: bool, default False
130            Verbosity toggle.
131
132        Returns
133        -------
134        Don't return anything.
135
136        Raises
137        ------
138        An error if any of the required attributes are missing.
139        """
140        from meerschaum.utils.warnings import error, warn
141        from meerschaum.utils.debug import dprint
142        from meerschaum.utils.misc import items_str
143        if required_attributes is None:
144            required_attributes = ['label']
145        missing_attributes = set()
146        for a in required_attributes:
147            if a not in self.__dict__:
148                missing_attributes.add(a)
149        if len(missing_attributes) > 0:
150            error(
151                (
152                    f"Missing {items_str(list(missing_attributes))} "
153                    + f"for connector '{self.type}:{self.label}'."
154                ),
155                InvalidAttributesError,
156                silent = True,
157                stack = False
158            )
159
160
161    def __str__(self):
162        """
163        When cast to a string, return type:label.
164        """
165        return f"{self.type}:{self.label}"
166
167    def __repr__(self):
168        """
169        Represent the connector as type:label.
170        """
171        return str(self)
172
173    @property
174    def meta(self) -> Dict[str, Any]:
175        """
176        Return the keys needed to reconstruct this Connector.
177        """
178        _meta = {
179            key: value
180            for key, value in self.__dict__.items()
181            if not str(key).startswith('_')
182        }
183        _meta.update({
184            'type': self.type,
185            'label': self.label,
186        })
187        return _meta
188
189
190    @property
191    def type(self) -> str:
192        """
193        Return the type for this connector.
194        """
195        _type = self.__dict__.get('type', None)
196        if _type is None:
197            import re
198            _type = re.sub(r'connector$', '', self.__class__.__name__.lower())
199            self.__dict__['type'] = _type
200        return _type
201
202
203    @property
204    def label(self) -> str:
205        """
206        Return the label for this connector.
207        """
208        _label = self.__dict__.get('label', None)
209        if _label is None:
210            from meerschaum.config.static import STATIC_CONFIG
211            _label = STATIC_CONFIG['connectors']['default_label']
212            self.__dict__['label'] = _label
213        return _label
class InvalidAttributesError(builtins.Exception):
15class InvalidAttributesError(Exception):
16    """
17    Raised when the incorrect attributes are set in the Connector.
18    """

Raised when the incorrect attributes are set in the Connector.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
class Connector:
 20class Connector(metaclass=abc.ABCMeta):
 21    """
 22    The base connector class to hold connection attributes,
 23    """
 24    def __init__(
 25            self,
 26            type: Optional[str] = None,
 27            label: Optional[str] = None,
 28            **kw: Any
 29        ):
 30        """
 31        Parameters
 32        ----------
 33        type: str
 34            The `type` of the connector (e.g. `sql`, `api`, `plugin`).
 35
 36        label: str
 37            The `label` for the connector.
 38
 39        Run `mrsm edit config` and to edit connectors in the YAML file:
 40
 41        ```
 42        meerschaum:
 43            connections:
 44                {type}:
 45                    {label}:
 46                        ### attributes go here
 47        ```
 48
 49        """
 50        self._original_dict = copy.deepcopy(self.__dict__)
 51        self._set_attributes(type=type, label=label, **kw)
 52        self.verify_attributes(getattr(self, 'REQUIRED_ATTRIBUTES', None))
 53
 54    def _reset_attributes(self):
 55        self.__dict__ = self._original_dict
 56
 57    def _set_attributes(
 58            self,
 59            *args,
 60            inherit_default: bool = True,
 61            **kw: Any
 62        ):
 63        from meerschaum.config.static import STATIC_CONFIG
 64        from meerschaum.utils.warnings import error
 65
 66        self._attributes = {}
 67
 68        default_label = STATIC_CONFIG['connectors']['default_label']
 69
 70        ### NOTE: Support the legacy method of explicitly passing the type.
 71        label = kw.get('label', None)
 72        if label is None:
 73            if len(args) == 2:
 74                label = args[1]
 75            elif len(args) == 0:
 76                label = None
 77            else:
 78                label = args[0]
 79
 80        if label == 'default':
 81            error(
 82                f"Label cannot be 'default'. Did you mean '{default_label}'?",
 83                InvalidAttributesError,
 84            )
 85        self.__dict__['label'] = label
 86
 87        from meerschaum.config import get_config
 88        conn_configs = copy.deepcopy(get_config('meerschaum', 'connectors'))
 89        connector_config = copy.deepcopy(get_config('system', 'connectors'))
 90
 91        ### inherit attributes from 'default' if exists
 92        if inherit_default:
 93            inherit_from = 'default'
 94            if self.type in conn_configs and inherit_from in conn_configs[self.type]:
 95                _inherit_dict = copy.deepcopy(conn_configs[self.type][inherit_from])
 96                self._attributes.update(_inherit_dict)
 97
 98        ### load user config into self._attributes
 99        if self.type in conn_configs and self.label in conn_configs[self.type]:
100            self._attributes.update(conn_configs[self.type][self.label])
101
102        ### load system config into self._sys_config
103        ### (deep copy so future Connectors don't inherit changes)
104        if self.type in connector_config:
105            self._sys_config = copy.deepcopy(connector_config[self.type])
106
107        ### add additional arguments or override configuration
108        self._attributes.update(kw)
109
110        ### finally, update __dict__ with _attributes.
111        self.__dict__.update(self._attributes)
112
113
114    def verify_attributes(
115            self,
116            required_attributes: Optional[List[str]] = None,
117            debug: bool = False
118        ) -> None:
119        """
120        Ensure that the required attributes have been met.
121        
122        The Connector base class checks the minimum requirements.
123        Child classes may enforce additional requirements.
124
125        Parameters
126        ----------
127        required_attributes: Optional[List[str]], default None
128            Attributes to be verified. If `None`, default to `['label']`.
129
130        debug: bool, default False
131            Verbosity toggle.
132
133        Returns
134        -------
135        Don't return anything.
136
137        Raises
138        ------
139        An error if any of the required attributes are missing.
140        """
141        from meerschaum.utils.warnings import error, warn
142        from meerschaum.utils.debug import dprint
143        from meerschaum.utils.misc import items_str
144        if required_attributes is None:
145            required_attributes = ['label']
146        missing_attributes = set()
147        for a in required_attributes:
148            if a not in self.__dict__:
149                missing_attributes.add(a)
150        if len(missing_attributes) > 0:
151            error(
152                (
153                    f"Missing {items_str(list(missing_attributes))} "
154                    + f"for connector '{self.type}:{self.label}'."
155                ),
156                InvalidAttributesError,
157                silent = True,
158                stack = False
159            )
160
161
162    def __str__(self):
163        """
164        When cast to a string, return type:label.
165        """
166        return f"{self.type}:{self.label}"
167
168    def __repr__(self):
169        """
170        Represent the connector as type:label.
171        """
172        return str(self)
173
174    @property
175    def meta(self) -> Dict[str, Any]:
176        """
177        Return the keys needed to reconstruct this Connector.
178        """
179        _meta = {
180            key: value
181            for key, value in self.__dict__.items()
182            if not str(key).startswith('_')
183        }
184        _meta.update({
185            'type': self.type,
186            'label': self.label,
187        })
188        return _meta
189
190
191    @property
192    def type(self) -> str:
193        """
194        Return the type for this connector.
195        """
196        _type = self.__dict__.get('type', None)
197        if _type is None:
198            import re
199            _type = re.sub(r'connector$', '', self.__class__.__name__.lower())
200            self.__dict__['type'] = _type
201        return _type
202
203
204    @property
205    def label(self) -> str:
206        """
207        Return the label for this connector.
208        """
209        _label = self.__dict__.get('label', None)
210        if _label is None:
211            from meerschaum.config.static import STATIC_CONFIG
212            _label = STATIC_CONFIG['connectors']['default_label']
213            self.__dict__['label'] = _label
214        return _label

The base connector class to hold connection attributes,

Connector(type: Optional[str] = None, label: Optional[str] = None, **kw: Any)
24    def __init__(
25            self,
26            type: Optional[str] = None,
27            label: Optional[str] = None,
28            **kw: Any
29        ):
30        """
31        Parameters
32        ----------
33        type: str
34            The `type` of the connector (e.g. `sql`, `api`, `plugin`).
35
36        label: str
37            The `label` for the connector.
38
39        Run `mrsm edit config` and to edit connectors in the YAML file:
40
41        ```
42        meerschaum:
43            connections:
44                {type}:
45                    {label}:
46                        ### attributes go here
47        ```
48
49        """
50        self._original_dict = copy.deepcopy(self.__dict__)
51        self._set_attributes(type=type, label=label, **kw)
52        self.verify_attributes(getattr(self, 'REQUIRED_ATTRIBUTES', None))
Parameters
  • type (str): The type of the connector (e.g. sql, api, plugin).
  • label (str): The label for the connector.
  • Run mrsm edit config and to edit connectors in the YAML file:
  • ```
  • meerschaum:: connections: {type}: {label}: ### attributes go here
  • ```
def verify_attributes( self, required_attributes: Optional[List[str]] = None, debug: bool = False) -> None:
114    def verify_attributes(
115            self,
116            required_attributes: Optional[List[str]] = None,
117            debug: bool = False
118        ) -> None:
119        """
120        Ensure that the required attributes have been met.
121        
122        The Connector base class checks the minimum requirements.
123        Child classes may enforce additional requirements.
124
125        Parameters
126        ----------
127        required_attributes: Optional[List[str]], default None
128            Attributes to be verified. If `None`, default to `['label']`.
129
130        debug: bool, default False
131            Verbosity toggle.
132
133        Returns
134        -------
135        Don't return anything.
136
137        Raises
138        ------
139        An error if any of the required attributes are missing.
140        """
141        from meerschaum.utils.warnings import error, warn
142        from meerschaum.utils.debug import dprint
143        from meerschaum.utils.misc import items_str
144        if required_attributes is None:
145            required_attributes = ['label']
146        missing_attributes = set()
147        for a in required_attributes:
148            if a not in self.__dict__:
149                missing_attributes.add(a)
150        if len(missing_attributes) > 0:
151            error(
152                (
153                    f"Missing {items_str(list(missing_attributes))} "
154                    + f"for connector '{self.type}:{self.label}'."
155                ),
156                InvalidAttributesError,
157                silent = True,
158                stack = False
159            )

Ensure that the required attributes have been met.

The Connector base class checks the minimum requirements. Child classes may enforce additional requirements.

Parameters
  • required_attributes (Optional[List[str]], default None): Attributes to be verified. If None, default to ['label'].
  • debug (bool, default False): Verbosity toggle.
Returns
  • Don't return anything.
Raises
  • An error if any of the required attributes are missing.
meta: Dict[str, Any]

Return the keys needed to reconstruct this Connector.

type: str

Return the type for this connector.

label: str

Return the label for this connector.