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