openc2lib.core.encoder
Encoder base functions and interface
This module provides base encoding functions to translate openc2lib objects into an intermediary representation.
1""" Encoder base functions and interface 2 3 This module provides base encoding functions to translate openc2lib objects into an intermediary 4 representation. 5""" 6 7import copy 8import aenum 9import enum 10import logging 11 12logger = logging.getLogger('openc2lib') 13""" Logging features 14 15 Most of logging from this modules are conceived for debugging only. 16""" 17 18_UNCODED = (bool, str, int, float) 19 20class Encoders(aenum.Enum): 21 """ List of available Encoders 22 23 This list can be used in `Transfer` protocols to select the correct class to decode an incoming OpenC2 Message 24 based on its metadata. The list is created as enumeration, which associate the name of the encoding 25 formats to the class that implements it. 26 """ 27 pass 28 29def register_encoder(cls): 30 """ Register an `Encoder` 31 32 This function is used to register a new `Encoder`. It can be used as a decorator to the class that 33 defines the new `Encoder`. 34 :param cls: The class definition that must be registered. The class internally holds its name. 35 :return: The same class passed as argument (used to create a decoratetor). 36 """ 37 aenum.extend_enum(Encoders, cls.getName(), cls) 38 return cls 39 40@register_encoder 41class Encoder: 42 """ Base `Encoder` 43 44 The Base `Encoder` provides a common interface that must be implemented by all implementations of 45 Encoding mechanisms. Each new `Encoder` should be derived from this class. 46 47 The Base Encoder translates openc2lib data types and structures 48 into dictionaries. This function can be used by derived class to have an intermediary representation 49 which strictly follows the OpenC2 formatting rules. The intermediary representation must then be 50 translated into the specific syntax used by the derived `Encoder` (e.g., json, xml, yaml). 51 52 Currently, this class is only designed to encode into text formats. 53 """ 54 encoder_type = 'dictionary' 55 56 @classmethod 57 def getName(cls): 58 """ Encoder name 59 60 This method MUST be implemented to return the name of the encoding format. The name should be 61 highly representative, possible using official terminology (e.g.: json, xml). 62 63 :return: The class name. 64 """ 65 return cls.encoder_type 66 67 @staticmethod 68 def encode(obj): 69 """ Encode an OpenC2 object 70 71 This method encodes an openc2lib object (namely, a data structure derived from `BaseType`). 72 It MUST be implemented by each derived class. It could be applied to any openc2lib object, 73 but the most common use is for `Message`, `Command`, or `Response`. 74 75 :param obj: An OpenC2 object derived from a `BaseType`. 76 :return: A string that contains the encoded object. 77 """ 78 return str(Encoder.todict(obj)) 79 80 @staticmethod 81 def decode(msgtype, msg): 82 """ Decode into OpenC2 object 83 84 This method decodes a text representation into an openc2lib object. The method throws an `Exception` 85 in case of unknown elements. 86 87 This method requires to specify the openc2lib class that implements the OpenC2 object described 88 by the text. This will commonly be either `Message`, `Command`, or `Response`. 89 90 :param msgtype: The class of an openc2lib object. 91 :param msg: Text-based representation of the OpenC2 object. 92 :return: An instance of an openc2lib object. 93 """ 94 return Encoder.fromdict(msgtype, msg) 95 96 @staticmethod 97 def __objtodict(obj): 98 if isinstance(obj, list): 99 return Encoder.__iteratelist(obj) 100 101 if isinstance(obj, dict): 102 return Encoder.__iteratedic(obj) 103 104 # Default: return a string representation of the object 105 return str(obj) 106 107 108 # This method 109 def __objfromdict(clstype, dic): 110 if isinstance(dic, dict): 111 return clstype(**dic) 112 if isinstance(dic, list): 113 lis = [] 114 for i in dic: 115 lis.append[Encoder.fromdict(clstype, i)] 116 return lis 117 if isinstance(dic, _UNCODED): 118 return clstype(dic) 119 raise ValueError("Unmanaged obj value: ", dic) 120 121 # Convert complex types to string by interatively invoking the todict function 122 @staticmethod 123 def __iteratedic(dic): 124 newdic = {} 125 for k,v in dic.items(): 126 if v is not None: 127 newdic[Encoder.todict(k)] = Encoder.todict(v) 128# if not isinstance(v, __UNCODED): 129# dic[k] = Encoder.todict(v) 130 return newdic 131 132 @staticmethod 133 def __iteratelist(lis): 134 objlist = [] 135 for i in lis: 136# if isinstance(i, __UNCODED): 137# objlist.append(i) 138# else: 139# print("append: ", i) 140# objlist.append( Encoder.todict(i) ) 141 objlist.append( Encoder.todict(i) ) 142 return objlist 143 144# NOT USED 145# They Python way: "try ... except ... " 146# @staticmethod 147# def hasmethod(obj, method): 148# return callable(hasattr(obj, method, None)) 149 150 151 @staticmethod 152 def todict(obj): 153 """ Convert object to dictionary 154 155 This is an internal method to convert an openc2lib object into a dictionary. The dictionary is 156 structured according to OpenC2 syntax. 157 158 This method should only be invoked by derived classes to get the intermediary representation 159 of openc2lib objects. It will likely be used in the implementation of the `decode` method. 160 :param obj: The openc2lib object to convert into a dictionary. 161 :return: A dictionary compliant with the OpenC2 syntax rules. 162 """ 163 try: 164 return obj.todict(Encoder) 165 except AttributeError: 166 return Encoder.__objtodict(obj) 167 168 169 @staticmethod 170 def fromdict(clstype, dic): 171 """ Create an object from dictionary 172 173 This is an internal method to create an openc2lib object from a dictionary. The dictionary 174 must be compliant with the OpenC2 syntax rules. Derived classes are expected to create this 175 intermediate representation and use this method in the `encode` method. It is necessary to 176 provide the class definition of the openc2lib object to be instantiated. 177 178 :param clstype: The class definition that must be used to instantiate the object. 179 :param dic: The dictionary with the OpenC2 description. 180 :return: An instance of `clstype` initialized with the data in the `dic`. 181 """ 182 logger.debug("Decondig: %s with %s", dic, clstype) 183 try: 184 logging.debug("Trying: %s", clstype.fromdict) 185 return clstype.fromdict(dic, Encoder) 186 except AttributeError: 187 logger.debug("Falling back: Encoder.objfromdict for %s", clstype) 188 return Encoder.__objfromdict(clstype, dic) 189
Logging features
Most of logging from this modules are conceived for debugging only.
21class Encoders(aenum.Enum): 22 """ List of available Encoders 23 24 This list can be used in `Transfer` protocols to select the correct class to decode an incoming OpenC2 Message 25 based on its metadata. The list is created as enumeration, which associate the name of the encoding 26 formats to the class that implements it. 27 """ 28 pass
List of available Encoders
This list can be used in Transfer protocols to select the correct class to decode an incoming OpenC2 Message
based on its metadata. The list is created as enumeration, which associate the name of the encoding
formats to the class that implements it.
Inherited Members
- aenum._enum.Enum
- name
- value
- values
30def register_encoder(cls): 31 """ Register an `Encoder` 32 33 This function is used to register a new `Encoder`. It can be used as a decorator to the class that 34 defines the new `Encoder`. 35 :param cls: The class definition that must be registered. The class internally holds its name. 36 :return: The same class passed as argument (used to create a decoratetor). 37 """ 38 aenum.extend_enum(Encoders, cls.getName(), cls) 39 return cls
Register an Encoder
This function is used to register a new Encoder. It can be used as a decorator to the class that
defines the new Encoder.
Parameters
- cls: The class definition that must be registered. The class internally holds its name.
Returns
The same class passed as argument (used to create a decoratetor).
41@register_encoder 42class Encoder: 43 """ Base `Encoder` 44 45 The Base `Encoder` provides a common interface that must be implemented by all implementations of 46 Encoding mechanisms. Each new `Encoder` should be derived from this class. 47 48 The Base Encoder translates openc2lib data types and structures 49 into dictionaries. This function can be used by derived class to have an intermediary representation 50 which strictly follows the OpenC2 formatting rules. The intermediary representation must then be 51 translated into the specific syntax used by the derived `Encoder` (e.g., json, xml, yaml). 52 53 Currently, this class is only designed to encode into text formats. 54 """ 55 encoder_type = 'dictionary' 56 57 @classmethod 58 def getName(cls): 59 """ Encoder name 60 61 This method MUST be implemented to return the name of the encoding format. The name should be 62 highly representative, possible using official terminology (e.g.: json, xml). 63 64 :return: The class name. 65 """ 66 return cls.encoder_type 67 68 @staticmethod 69 def encode(obj): 70 """ Encode an OpenC2 object 71 72 This method encodes an openc2lib object (namely, a data structure derived from `BaseType`). 73 It MUST be implemented by each derived class. It could be applied to any openc2lib object, 74 but the most common use is for `Message`, `Command`, or `Response`. 75 76 :param obj: An OpenC2 object derived from a `BaseType`. 77 :return: A string that contains the encoded object. 78 """ 79 return str(Encoder.todict(obj)) 80 81 @staticmethod 82 def decode(msgtype, msg): 83 """ Decode into OpenC2 object 84 85 This method decodes a text representation into an openc2lib object. The method throws an `Exception` 86 in case of unknown elements. 87 88 This method requires to specify the openc2lib class that implements the OpenC2 object described 89 by the text. This will commonly be either `Message`, `Command`, or `Response`. 90 91 :param msgtype: The class of an openc2lib object. 92 :param msg: Text-based representation of the OpenC2 object. 93 :return: An instance of an openc2lib object. 94 """ 95 return Encoder.fromdict(msgtype, msg) 96 97 @staticmethod 98 def __objtodict(obj): 99 if isinstance(obj, list): 100 return Encoder.__iteratelist(obj) 101 102 if isinstance(obj, dict): 103 return Encoder.__iteratedic(obj) 104 105 # Default: return a string representation of the object 106 return str(obj) 107 108 109 # This method 110 def __objfromdict(clstype, dic): 111 if isinstance(dic, dict): 112 return clstype(**dic) 113 if isinstance(dic, list): 114 lis = [] 115 for i in dic: 116 lis.append[Encoder.fromdict(clstype, i)] 117 return lis 118 if isinstance(dic, _UNCODED): 119 return clstype(dic) 120 raise ValueError("Unmanaged obj value: ", dic) 121 122 # Convert complex types to string by interatively invoking the todict function 123 @staticmethod 124 def __iteratedic(dic): 125 newdic = {} 126 for k,v in dic.items(): 127 if v is not None: 128 newdic[Encoder.todict(k)] = Encoder.todict(v) 129# if not isinstance(v, __UNCODED): 130# dic[k] = Encoder.todict(v) 131 return newdic 132 133 @staticmethod 134 def __iteratelist(lis): 135 objlist = [] 136 for i in lis: 137# if isinstance(i, __UNCODED): 138# objlist.append(i) 139# else: 140# print("append: ", i) 141# objlist.append( Encoder.todict(i) ) 142 objlist.append( Encoder.todict(i) ) 143 return objlist 144 145# NOT USED 146# They Python way: "try ... except ... " 147# @staticmethod 148# def hasmethod(obj, method): 149# return callable(hasattr(obj, method, None)) 150 151 152 @staticmethod 153 def todict(obj): 154 """ Convert object to dictionary 155 156 This is an internal method to convert an openc2lib object into a dictionary. The dictionary is 157 structured according to OpenC2 syntax. 158 159 This method should only be invoked by derived classes to get the intermediary representation 160 of openc2lib objects. It will likely be used in the implementation of the `decode` method. 161 :param obj: The openc2lib object to convert into a dictionary. 162 :return: A dictionary compliant with the OpenC2 syntax rules. 163 """ 164 try: 165 return obj.todict(Encoder) 166 except AttributeError: 167 return Encoder.__objtodict(obj) 168 169 170 @staticmethod 171 def fromdict(clstype, dic): 172 """ Create an object from dictionary 173 174 This is an internal method to create an openc2lib object from a dictionary. The dictionary 175 must be compliant with the OpenC2 syntax rules. Derived classes are expected to create this 176 intermediate representation and use this method in the `encode` method. It is necessary to 177 provide the class definition of the openc2lib object to be instantiated. 178 179 :param clstype: The class definition that must be used to instantiate the object. 180 :param dic: The dictionary with the OpenC2 description. 181 :return: An instance of `clstype` initialized with the data in the `dic`. 182 """ 183 logger.debug("Decondig: %s with %s", dic, clstype) 184 try: 185 logging.debug("Trying: %s", clstype.fromdict) 186 return clstype.fromdict(dic, Encoder) 187 except AttributeError: 188 logger.debug("Falling back: Encoder.objfromdict for %s", clstype) 189 return Encoder.__objfromdict(clstype, dic)
Base Encoder
The Base Encoder provides a common interface that must be implemented by all implementations of
Encoding mechanisms. Each new Encoder should be derived from this class.
The Base Encoder translates openc2lib data types and structures
into dictionaries. This function can be used by derived class to have an intermediary representation
which strictly follows the OpenC2 formatting rules. The intermediary representation must then be
translated into the specific syntax used by the derived Encoder (e.g., json, xml, yaml).
Currently, this class is only designed to encode into text formats.
57 @classmethod 58 def getName(cls): 59 """ Encoder name 60 61 This method MUST be implemented to return the name of the encoding format. The name should be 62 highly representative, possible using official terminology (e.g.: json, xml). 63 64 :return: The class name. 65 """ 66 return cls.encoder_type
Encoder name
This method MUST be implemented to return the name of the encoding format. The name should be highly representative, possible using official terminology (e.g.: json, xml).
Returns
The class name.
68 @staticmethod 69 def encode(obj): 70 """ Encode an OpenC2 object 71 72 This method encodes an openc2lib object (namely, a data structure derived from `BaseType`). 73 It MUST be implemented by each derived class. It could be applied to any openc2lib object, 74 but the most common use is for `Message`, `Command`, or `Response`. 75 76 :param obj: An OpenC2 object derived from a `BaseType`. 77 :return: A string that contains the encoded object. 78 """ 79 return str(Encoder.todict(obj))
Encode an OpenC2 object
This method encodes an openc2lib object (namely, a data structure derived from BaseType).
It MUST be implemented by each derived class. It could be applied to any openc2lib object,
but the most common use is for Message, Command, or Response.
Parameters
- obj: An OpenC2 object derived from a
BaseType.
Returns
A string that contains the encoded object.
81 @staticmethod 82 def decode(msgtype, msg): 83 """ Decode into OpenC2 object 84 85 This method decodes a text representation into an openc2lib object. The method throws an `Exception` 86 in case of unknown elements. 87 88 This method requires to specify the openc2lib class that implements the OpenC2 object described 89 by the text. This will commonly be either `Message`, `Command`, or `Response`. 90 91 :param msgtype: The class of an openc2lib object. 92 :param msg: Text-based representation of the OpenC2 object. 93 :return: An instance of an openc2lib object. 94 """ 95 return Encoder.fromdict(msgtype, msg)
Decode into OpenC2 object
This method decodes a text representation into an openc2lib object. The method throws an Exception
in case of unknown elements.
This method requires to specify the openc2lib class that implements the OpenC2 object described
by the text. This will commonly be either Message, Command, or Response.
Parameters
- msgtype: The class of an openc2lib object.
- msg: Text-based representation of the OpenC2 object.
Returns
An instance of an openc2lib object.
152 @staticmethod 153 def todict(obj): 154 """ Convert object to dictionary 155 156 This is an internal method to convert an openc2lib object into a dictionary. The dictionary is 157 structured according to OpenC2 syntax. 158 159 This method should only be invoked by derived classes to get the intermediary representation 160 of openc2lib objects. It will likely be used in the implementation of the `decode` method. 161 :param obj: The openc2lib object to convert into a dictionary. 162 :return: A dictionary compliant with the OpenC2 syntax rules. 163 """ 164 try: 165 return obj.todict(Encoder) 166 except AttributeError: 167 return Encoder.__objtodict(obj)
Convert object to dictionary
This is an internal method to convert an openc2lib object into a dictionary. The dictionary is structured according to OpenC2 syntax.
This method should only be invoked by derived classes to get the intermediary representation
of openc2lib objects. It will likely be used in the implementation of the decode method.
Parameters
- obj: The openc2lib object to convert into a dictionary.
Returns
A dictionary compliant with the OpenC2 syntax rules.
170 @staticmethod 171 def fromdict(clstype, dic): 172 """ Create an object from dictionary 173 174 This is an internal method to create an openc2lib object from a dictionary. The dictionary 175 must be compliant with the OpenC2 syntax rules. Derived classes are expected to create this 176 intermediate representation and use this method in the `encode` method. It is necessary to 177 provide the class definition of the openc2lib object to be instantiated. 178 179 :param clstype: The class definition that must be used to instantiate the object. 180 :param dic: The dictionary with the OpenC2 description. 181 :return: An instance of `clstype` initialized with the data in the `dic`. 182 """ 183 logger.debug("Decondig: %s with %s", dic, clstype) 184 try: 185 logging.debug("Trying: %s", clstype.fromdict) 186 return clstype.fromdict(dic, Encoder) 187 except AttributeError: 188 logger.debug("Falling back: Encoder.objfromdict for %s", clstype) 189 return Encoder.__objfromdict(clstype, dic)
Create an object from dictionary
This is an internal method to create an openc2lib object from a dictionary. The dictionary
must be compliant with the OpenC2 syntax rules. Derived classes are expected to create this
intermediate representation and use this method in the encode method. It is necessary to
provide the class definition of the openc2lib object to be instantiated.
Parameters
- clstype: The class definition that must be used to instantiate the object.
- dic: The dictionary with the OpenC2 description.
Returns
An instance of
clstypeinitialized with the data in thedic.