Hello World¶
We will use the test plugin, to show how to create a plugin for unidown.
Basics¶
First of all we subclass from unidown.plugin.a_plugin.APlugin
, to have all essential variables and functions for free.
from unidown.plugin import APlugin
class Plugin(APlugin):
Next part is to add basic information about the plugin like name, version and server host.
class Plugin(APlugin):
_INFO = PluginInfo('test', '0.1.0', 'raw.githubusercontent.com')
Next we will hook into the options loading to set default options if nothing was passed.
class Plugin(APlugin):
_INFO = PluginInfo('test', '0.1.0', 'raw.githubusercontent.com')
def _load_default_options(self):
super(Plugin, self)._load_default_options()
if 'username' not in self._options:
self._options['username'] = ''
Now as the username is in the options for sure we can just get it safely.
class Plugin(APlugin):
_INFO = PluginInfo('test', '0.1.0', 'raw.githubusercontent.com')
def __init__(self, settings: Settings, options: Dict[str, Any] = None):
super().__init__(settings, options)
self._username: str = self._options['username']
def _load_default_options(self):
super(Plugin, self)._load_default_options()
if 'username' not in self._options:
self._options['username'] = ''
To get an overall update time for the complete data set, create the _create_last_update_time
method.
If the time generated by this function is older compared to the savestate it will run the individual link generating, if not it will skip the rest.
class Plugin(APlugin):
_INFO = PluginInfo('test', '0.1.0', 'raw.githubusercontent.com')
def __init__(self, settings: Settings, options: Dict[str, Any] = None):
super().__init__(settings, options)
self._username: str = self._options['username']
def _create_last_update_time(self) -> datetime:
self.download_as_file('/IceflowRE/unidown/main/tests/last_update_time.txt', self._temp_dir, 'last_update_time.txt')
with self._temp_dir.joinpath('last_update_time.txt').open(encoding='utf8') as reader:
return datetime.strptime(reader.read(), LinkItem.TIME_FORMAT)
def _load_default_options(self):
super(Plugin, self)._load_default_options()
if 'username' not in self._options:
self._options['username'] = ''
So if the generate update time is newer, the application continues to _create_download_links
.
In the example we just download a json with preconfigured values and create the LinkItemDict
from it.
class Plugin(APlugin):
_INFO = PluginInfo('test', '0.1.0', 'raw.githubusercontent.com')
def __init__(self, settings: Settings, options: Dict[str, Any] = None):
super().__init__(settings, options)
self._username: str = self._options['username']
def _create_last_update_time(self) -> datetime:
self.download_as_file('/IceflowRE/unidown/main/tests/last_update_time.txt', self._temp_dir, 'last_update_time.txt')
with self._temp_dir.joinpath('last_update_time.txt').open(encoding='utf8') as reader:
return datetime.strptime(reader.read(), LinkItem.TIME_FORMAT)
def _create_download_data(self) -> LinkItemDict:
self.download_as_file('/IceflowRE/unidown/main/tests/item_dict.json', self._temp_dir, 'item_dict.json')
with self._temp_dir.joinpath('item_dict.json').open(encoding='utf8') as reader:
data = json.loads(reader.read())
result = LinkItemDict()
for link, item in data.items():
result[link] = LinkItem(item['name'], datetime.strptime(item['time'], LinkItem.TIME_FORMAT))
return result
def _load_default_options(self):
super(Plugin, self)._load_default_options()
if 'username' not in self._options:
self._options['username'] = ''
Final step includes that we create a python package out of the generate file.
unidown_test/
├── __init__.py
├── plugin.py «the plugin file»
└── setup.py
The most important part is the entry point, otherwise unidown cannot recognize it.
'unidown.plugin': "test = unidown_test.plugin:Plugin"
Where as test
is the name of the plugin and after that the import path the plugin class.
from setuptools import find_packages, setup
setup(
name="unidown_test",
version="0.1.0",
description="Test plugin for unidown.",
author="Iceflower S",
author_email="iceflower@gmx.de",
license='MIT',
packages=find_packages(include=['unidown_test', 'unidown_test.*']),
python_requires='>=3.7',
install_requires=[
'unidown',
],
entry_points={
'unidown.plugin': "test = unidown_test.plugin:Plugin"
},
)
Advanced¶
The advanced part will show how to use a custom savestate.
First of all we have to create the custom savestate. It is required to subclass from unidown.plugin.savestate.SaveState
.
from unidown.plugin.savestate import SaveState
class MySaveState(SaveState):
In our example we want to permanently store a username.
class MySaveState(SaveState):
def __init__(self, plugin_info: PluginInfo, last_update: datetime, link_items: LinkItemDict, username: str = ''):
super().__init__(plugin_info, last_update, link_items)
self.username: str = username
Furthermore to get it loaded from a custom json file we have to override from_json
, the same goes with saving with to_json
.
class MySaveState(SaveState):
def __init__(self, plugin_info: PluginInfo, last_update: datetime, link_items: LinkItemDict, username: str = ''):
super().__init__(plugin_info, last_update, link_items)
self.username: str = username
@classmethod
def from_json(cls, data: dict) -> SaveState:
savestate = super(MySaveState, cls).from_json(data)
if 'username' in data:
savestate.username = data['username']
return savestate
def to_json(self) -> dict:
data = super().to_json()
data['username'] = self.username
return data
Additionally it’s required to provide an own upgrade
method, in case the format changes and as the super method may erase your own set variables while upgrading.
class MySaveState(SaveState):
def __init__(self, plugin_info: PluginInfo, last_update: datetime, link_items: LinkItemDict, username: str = ''):
super().__init__(plugin_info, last_update, link_items)
self.username: str = username
@classmethod
def from_json(cls, data: dict) -> SaveState:
savestate = super(MySaveState, cls).from_json(data)
if 'username' in data:
savestate.username = data['username']
return savestate
def to_json(self) -> dict:
data = super().to_json()
data['username'] = self.username
return data
def upgrade(self) -> SaveState:
new_savestate = super(MySaveState, self).upgrade()
new_savestate.username = self.username
return new_savestate
The next step is to register your own custom savestate in the plugin, so it will be used, by setting _SAVESTATE_CLS
.
from unidown_test.savestate import MySaveState
class Plugin(APlugin):
_INFO = PluginInfo('test', '0.1.0', 'raw.githubusercontent.com')
_SAVESTATE_CLS = MySaveState
To get the username loaded into your plugin, after the savestate was loaded override load_savestate
.
from unidown_test.savestate import MySaveState
class Plugin(APlugin):
_INFO = PluginInfo('test', '0.1.0', 'raw.githubusercontent.com')
_SAVESTATE_CLS = MySaveState
# ... all other stuff in between
def load_savestate(self):
super(Plugin, self).load_savestate()
# do not override set username by options
if self._username == '':
self._username = self.savestate.username
The last step is to hook into updating the savestate. To get the current username saved into a new savestate.
from unidown_test.savestate import MySaveState
class Plugin(APlugin):
_INFO = PluginInfo('test', '0.1.0', 'raw.githubusercontent.com')
_SAVESTATE_CLS = MySaveState
# ... all other stuff in between
def load_savestate(self):
super(Plugin, self).load_savestate()
# do not override set username by options
if self._username == '':
self._username = self.savestate.username
def update_savestate(self, new_items: LinkItemDict):
super(Plugin, self).update_savestate(new_items)
self._savestate.username = self._username