11import ctypes
22import sys
33from pathlib import Path
4- from typing import List
4+ from typing import List , Sequence , OrderedDict
55from zipfile import ZipFile
66
7- import attr
8- from attr import attrib
7+ from attr import define , field
98from strictyaml import Map
109from strictyaml import MapPattern
1110from strictyaml import Optional
2120 "author" : Str (),
2221 "email" : Str (),
2322 "id" : Str (),
23+ "sdk_version" : Str (),
24+ "python_version" : Str (),
2425 Optional ("extras" ): MapPattern (Str (), Str ()),
2526 }
2627)
2728
2829
29- @attr . s
30- class PluginInfo ( object ) :
30+ @define
31+ class PluginInfo :
3132 """
3233 Class that holds all information related to the plugin with some auxiliary methods
3334 """
3435
35- yaml_location = attrib (type = Path )
36- hooks_available = attrib (validator = attr .validators .optional (attr .validators .instance_of (dict )))
37-
38- author = attrib (type = str , init = False )
39- description = attrib (type = str , default = "Could not find a description" , init = False )
40- email = attrib (type = str , init = False )
41- hooks_implemented = attrib (type = list , init = False )
42- caption = attrib (type = str , init = False )
43- shared_lib_name = attrib (type = str , init = False )
44- shared_lib_path = attrib (type = Path , init = False )
45- version = attrib (type = str , init = False )
46- extras = attrib (attr .Factory (dict ), init = False )
47-
48- def __attrs_post_init__ (self ):
36+ yaml_location : Path
37+ hooks_available : dict | None = None
38+
39+ description : str = ""
40+ author : str = ""
41+ email : str = ""
42+ hooks_implemented : Sequence [str ] = []
43+ caption : str = ""
44+ shared_lib_name : str = ""
45+ shared_lib_path : Path = field (init = False )
46+ version : str = ""
47+ sdk_version : str = ""
48+ python_version : str = ""
49+ extras : dict = {}
50+ id : str = ""
51+
52+ def __attrs_post_init__ (self ) -> None :
4953 plugin_config_file_content = self ._load_yaml_file (
5054 self .yaml_location .read_text (encoding = "utf-8" )
5155 )
5256
5357 name = plugin_config_file_content ["id" ]
5458 shared_lib_name = f"{ name } .dll" if sys .platform == "win32" else f"lib{ name } .so"
5559
56- object .__setattr__ (self , "shared_lib_name" , shared_lib_name )
57- object .__setattr__ (
58- self , "shared_lib_path" , self .yaml_location .parents [1 ] / "artifacts" / shared_lib_name
59- )
60-
61- object .__setattr__ (self , "author" , plugin_config_file_content ["author" ])
62- object .__setattr__ (self , "caption" , plugin_config_file_content ["caption" ])
63- object .__setattr__ (self , "email" , plugin_config_file_content ["email" ])
64- object .__setattr__ (self , "version" , plugin_config_file_content ["version" ])
65- object .__setattr__ (self , "extras" , plugin_config_file_content .get ("extras" , {}))
60+ self .shared_lib_name = shared_lib_name
61+ self .shared_lib_path = self .yaml_location .parents [1 ] / "artifacts" / shared_lib_name
62+ self .author = plugin_config_file_content ["author" ]
63+ self .caption = plugin_config_file_content ["caption" ]
64+ self .email = plugin_config_file_content ["email" ]
65+ self .version = plugin_config_file_content ["version" ]
66+ self .sdk_version = plugin_config_file_content ["sdk_version" ]
67+ self .python_version = plugin_config_file_content ["python_version" ]
68+ self .extras = plugin_config_file_content .get ("extras" , {})
6669
6770 # The id bellow guarantee to me that the plugin_id to be used in the application was not changed by a config file.
68- object .__setattr__ (
69- self , "id" , self ._get_plugin_id_from_dll (plugin_config_file_content ["id" ])
70- )
71+ self .id = self ._get_plugin_id_from_dll (plugin_config_file_content ["id" ])
72+
73+ readme_file = self .yaml_location .parent / "README.md"
74+ self .description = readme_file .read_text (encoding = "utf-8" ) if readme_file .is_file () else "Could not find a description"
7175
7276 if not self .hooks_available is None :
73- object . __setattr__ ( self , " hooks_implemented" , self ._get_hooks_implemented () )
77+ self . hooks_implemented = self ._get_hooks_implemented ()
7478
75- readme_file = self .yaml_location .parent / "README.md"
76- if readme_file .exists ():
77- object .__setattr__ (self , "description" , readme_file .read_text ())
7879
7980 def _check_if_shared_lib_exists (self ):
8081 if not self .shared_lib_path .is_file ():
@@ -95,11 +96,14 @@ def _get_plugin_id_from_dll(self, plugin_id_from_plugin_yaml: str) -> str:
9596 raise RuntimeError (msg )
9697 return plugin_id_from_shared_lib
9798
98- def _get_hooks_implemented (self ) -> List [str ]:
99+ def _get_hooks_implemented (self ) -> Sequence [str ]:
99100 """
100101 Return a list of which hooks from "hooks_available" the shared library implements
101102 """
102103 self ._check_if_shared_lib_exists ()
104+ if self .hooks_available is None :
105+ return []
106+
103107 with load_shared_lib (str (self .shared_lib_path )) as plugin_dll :
104108 hooks_implemented = [
105109 hook_name
@@ -124,7 +128,7 @@ def is_implemented_on_plugin(cls, plugin_dll: ctypes.CDLL, hook_name: str) -> bo
124128 return True
125129
126130 @classmethod
127- def _load_yaml_file (cls , yaml_content ) :
131+ def _load_yaml_file (cls , yaml_content : str ) -> OrderedDict :
128132 import strictyaml
129133
130134 plugin_config_file_content = strictyaml .load (yaml_content , PLUGIN_CONFIG_SCHEMA ).data
@@ -139,7 +143,7 @@ def _load_yaml_file(cls, yaml_content):
139143 return plugin_config_file_content
140144
141145 @classmethod
142- def validate_plugin_file (cls , plugin_file_zip : ZipFile ):
146+ def validate_plugin_file (cls , plugin_file_zip : ZipFile ) -> None :
143147 """
144148 Check if the given plugin_file is valid,
145149 currently the only check that this method do is to verify if the id is available
0 commit comments