Commit 331ffc9e authored by Alp Deniz Ogut's avatar Alp Deniz Ogut
Browse files

Indicate possibility of direct username-password use

parent aa3f3dd5
Showing with 6 additions and 2 deletions
+6 -2
......@@ -206,6 +206,7 @@ nb_path: "nbs/plugin.pluginbase.ipynb"
<span class="n">auth</span><span class="o">.</span><span class="n">isTest</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">token</span> <span class="o">=</span> <span class="n">auth</span><span class="o">.</span><span class="n">authenticate</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">api</span> <span class="o">=</span> <span class="n">MyAPIClient</span><span class="p">(</span><span class="n">token</span><span class="p">)</span>
<span class="c1"># or use account.identifier and account.secret directly e.g. MyAPIClient(username=account.identifier, password=account.secret)</span>
<span class="k">def</span> <span class="nf">add_to_schema</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">add_to_schema</span><span class="p">(</span><span class="n">MyItem</span><span class="p">(</span><span class="s2">&quot;my name&quot;</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
......@@ -251,7 +252,7 @@ nb_path: "nbs/plugin.pluginbase.ipynb"
<div class="output_markdown rendered_html output_subarea ">
<h4 id="run_plugin" class="doc_header"><code>run_plugin</code><a href="https://gitlab.memri.io/memri/pymemri/tree/prod/pymemri/plugin/pluginbase.py#L211" class="source_link" style="float:right">[source]</a></h4><blockquote><p><code>run_plugin</code>(<strong><code>pod_full_address</code></strong>:<code>Param object at 0x7f35d470dd90&gt;</code>=<em><code>'http://localhost:3030'</code></em>, <strong><code>plugin_run_id</code></strong>:<code>Param object at 0x7f35d470ddc0&gt;</code>=<em><code>None</code></em>, <strong><code>database_key</code></strong>:<code>Param object at 0x7f35d470dcd0&gt;</code>=<em><code>None</code></em>, <strong><code>owner_key</code></strong>:<code>Param object at 0x7f35d470dc70&gt;</code>=<em><code>None</code></em>, <strong><code>read_args_from_env</code></strong>:<code>Param object at 0x7f35d470dd60&gt;</code>=<em><code>False</code></em>, <strong><code>config_file</code></strong>:<code>Param object at 0x7f35d470dd30&gt;</code>=<em><code>None</code></em>)</p>
<h4 id="run_plugin" class="doc_header"><code>run_plugin</code><a href="https://gitlab.memri.io/memri/pymemri/tree/prod/pymemri/plugin/pluginbase.py#L212" class="source_link" style="float:right">[source]</a></h4><blockquote><p><code>run_plugin</code>(<strong><code>pod_full_address</code></strong>:<code>Param object at 0x7f05ba55ee20&gt;</code>=<em><code>'http://localhost:3030'</code></em>, <strong><code>plugin_run_id</code></strong>:<code>Param object at 0x7f05ba55eb20&gt;</code>=<em><code>None</code></em>, <strong><code>database_key</code></strong>:<code>Param object at 0x7f05ba55ed60&gt;</code>=<em><code>None</code></em>, <strong><code>owner_key</code></strong>:<code>Param object at 0x7f05ba55ed00&gt;</code>=<em><code>None</code></em>, <strong><code>read_args_from_env</code></strong>:<code>Param object at 0x7f05ba55edf0&gt;</code>=<em><code>False</code></em>, <strong><code>config_file</code></strong>:<code>Param object at 0x7f05ba55edc0&gt;</code>=<em><code>None</code></em>)</p>
</blockquote>
</div>
......@@ -353,7 +354,7 @@ logging in with account myusername and password mypassword
<div class="output_markdown rendered_html output_subarea ">
<h4 id="simulate_run_plugin_from_frontend" class="doc_header"><code>simulate_run_plugin_from_frontend</code><a href="https://gitlab.memri.io/memri/pymemri/tree/prod/pymemri/plugin/pluginbase.py#L243" class="source_link" style="float:right">[source]</a></h4><blockquote><p><code>simulate_run_plugin_from_frontend</code>(<strong><code>pod_full_address</code></strong>:"The pod full address"=<em><code>'http://localhost:3030'</code></em>, <strong><code>database_key</code></strong>:"Database key of the pod"=<em><code>None</code></em>, <strong><code>owner_key</code></strong>:"Owner key of the pod"=<em><code>None</code></em>, <strong><code>container</code></strong>:"Pod container to run frod"=<em><code>None</code></em>, <strong><code>plugin_path</code></strong>:"Plugin path"=<em><code>None</code></em>, <strong><code>settings_file</code></strong>:"Plugin settings (json)"=<em><code>None</code></em>, <strong><code>config_file</code></strong>:"config file for the PluginRun"=<em><code>None</code></em>, <strong><code>account_id</code></strong>:"Account id to be used inside the plugin"=<em><code>None</code></em>)</p>
<h4 id="simulate_run_plugin_from_frontend" class="doc_header"><code>simulate_run_plugin_from_frontend</code><a href="https://gitlab.memri.io/memri/pymemri/tree/prod/pymemri/plugin/pluginbase.py#L244" class="source_link" style="float:right">[source]</a></h4><blockquote><p><code>simulate_run_plugin_from_frontend</code>(<strong><code>pod_full_address</code></strong>:"The pod full address"=<em><code>'http://localhost:3030'</code></em>, <strong><code>database_key</code></strong>:"Database key of the pod"=<em><code>None</code></em>, <strong><code>owner_key</code></strong>:"Owner key of the pod"=<em><code>None</code></em>, <strong><code>container</code></strong>:"Pod container to run frod"=<em><code>None</code></em>, <strong><code>plugin_path</code></strong>:"Plugin path"=<em><code>None</code></em>, <strong><code>settings_file</code></strong>:"Plugin settings (json)"=<em><code>None</code></em>, <strong><code>config_file</code></strong>:"config file for the PluginRun"=<em><code>None</code></em>, <strong><code>account_id</code></strong>:"Account id to be used inside the plugin"=<em><code>None</code></em>)</p>
</blockquote>
</div>
......
%% Cell type:code id: tags:
``` python
%load_ext autoreload
%autoreload 2
# default_exp plugin.pluginbase
```
%% Cell type:code id: tags:
``` python
# export
from pymemri.data.schema import *
from pymemri.pod.client import *
from pymemri.imports import *
from pymemri.pod.utils import *
from os import environ
from abc import ABCMeta
import abc
import json
import importlib
import string
import time
from enum import Enum
from fastscript import *
import os
from pymemri.plugin.schema import Account, PluginRun
from pymemri.data.basic import *
```
%% Cell type:code id: tags:
``` python
# hide
from nbdev.showdoc import *
```
%% Cell type:markdown id: tags:
# Plugins
%% Cell type:markdown id: tags:
PluginBase is the plugin class that the simplest plugin inherits.
Inheriting class should implement:
- run() that implements the logic of the plugin
- add_to_schema() for plugin specific item types
%% Cell type:code id: tags:
``` python
# export
POD_FULL_ADDRESS_ENV = 'POD_FULL_ADDRESS'
POD_TARGET_ITEM_ENV = 'POD_TARGET_ITEM'
POD_OWNER_KEY_ENV = 'POD_OWNER'
POD_AUTH_JSON_ENV = 'POD_AUTH_JSON'
```
%% Cell type:code id: tags:
``` python
# export
# hide
class PluginBase(metaclass=ABCMeta):
"""Base class for plugins"""
def __init__(self, client=None, pluginRun=None, name=None, repository=None, icon=None,
query=None, bundleImage=None, runDestination=None, pluginClass=None, **kwargs):
if pluginClass is None: pluginClass=self.__class__.__name__
super().__init__(**kwargs)
self.client = client
self.pluginRun = pluginRun
self.name = name
self.repository = repository
self.icon = icon
self.query = query
self.bundleImage = bundleImage
self.runDestination = runDestination
self.pluginClass = pluginClass
@abc.abstractmethod
def run(self):
raise NotImplementedError()
@abc.abstractmethod
def add_to_schema(self):
raise NotImplementedError()
```
%% Cell type:markdown id: tags:
## Creating a plugin
%% Cell type:markdown id: tags:
The memri [pod](https://gitlab.memri.io/memri/pod) uses a plugin system to add features to the backend memri backend. Plugins can import your data (importers), change your data (indexers), or call other serivces. Users can define their own plugins to add new behaviour to their memri app. Let's use the following plugin as an example of how we can start plugins.
%% Cell type:code id: tags:
``` python
class MySimplePlugin(PluginBase):
""""""
def __init__(self, **kwargs):
super().__init__(**kwargs)
def run(self):
print("running")
items = self.client.search({'type': 'MyItem'})
for item in items:
if item.age > 65:
item.name = f"Sr. {item.name}"
if item.age <= 18:
item.name = f"Jr. {item.name}"
def add_to_schema(self):
self.client.add_to_schema(MyItem("my name", 10))
```
%% Cell type:markdown id: tags:
## More Complex Plugin Examples (with authentication)
%% Cell type:code id: tags:
``` python
# export
# hide
from pymemri.plugin.authenticators.oauth import ExampleOAuthAuthenticator
from pymemri.plugin.authenticators.password import PasswordAuthenticator
class MyAPIClient:
def __init__(self, accessToken):
self.access_token = accessToken
def get_data(self):
return [{'name': 'name_1', 'age': 21}, {'name': 'name_2', 'age': 22}]
class MyItem(Item):
properties = Item.properties + ["name", "age"]
edges = Item.edges
def __init__(self, name=None, age=None, **kwargs):
super().__init__(**kwargs)
self.name = name
self.age = age
class MyOAuthPlugin(PluginBase):
""""""
def __init__(self, **kwargs):
super().__init__(**kwargs)
def run(self):
print("running")
self.login()
items = self.api.get_data()
for item in items:
self.client.create(MyItem(name=item['name'], age=item['age']))
def login(self):
auth = ExampleOAuthAuthenticator(self.client, self.pluginRun)
auth.isTest = True
auth.authenticate()
self.api = MyAPIClient(self.pluginRun.account[0].secret)
def add_to_schema(self):
self.client.add_to_schema(MyItem("my name", 10))
class MyPasswordPlugin(PluginBase):
""""""
def __init__(self, **kwargs):
super().__init__(**kwargs)
def run(self):
print("running")
self.login()
items = self.api.get_data()
for item in items:
self.client.create(MyItem(name=item['name'], age=item['age']))
def login(self):
auth = PasswordAuthenticator(self.client, self.pluginRun)
auth.isTest = True
token = auth.authenticate()
self.api = MyAPIClient(token)
# or use account.identifier and account.secret directly e.g. MyAPIClient(username=account.identifier, password=account.secret)
def add_to_schema(self):
self.client.add_to_schema(MyItem("my name", 10))
```
%% Cell type:code id: tags:
``` python
# hide
MyOAuthPlugin()
MyPasswordPlugin()
```
%% Output
MyPlugin (#None)
%% Cell type:markdown id: tags:
```python
class ExampleOAuthAuthenticator(OAuthAuthenticator):
def get_oauth_url(self):
return "https://example.com/oauth"
def get_tokens_from_code(self, code):
return {
'access_token': 'dummy_access_token_with_' + code,
'refresh_token': 'dummy_refresh_token'
}
def refresh_tokens(self, refreshToken):
return {
'access_token': 'refreshed_dummy_access_token',
'refresh_token': 'refreshed_dummy_refresh_token'
}
def get_api_instance(self):
return MyAPIClient(self.pluginRun.account[0].secret)
class ExamplePasswordAuthenticator(PasswordAuthenticator):
SERVICE_URL = "https://example.com/login"
def get_token(self, username, password):
result = requests.post(self.SERVICE_URL, {'username': username, 'password': password})
if result.status_code == 200:
try:
res = result.json()
return res['session_token']
except:
pass
```
%% Cell type:markdown id: tags:
```python
class MyAPIClient:
def __init__(self, accessToken):
self.access_token = accessToken
def get_data(self):
return [{'name': 'name_1', 'age': 21}, {'name': 'name_2', 'age': 22}]
class MyItem(Item):
properties = Item.properties + ["name", "age"]
edges = Item.edges
def __init__(self, name=None, age=None, **kwargs):
super().__init__(**kwargs)
self.name = name
self.age = age
class MyOAuthPlugin(PluginBase):
""""""
def __init__(self, **kwargs):
super().__init__(**kwargs)
def run(self):
print("running")
self.login()
items = self.api.get_data()
for item in items:
self.client.create(MyItem(name=item['name'], age=item['age']))
def login(self):
auth = ExampleOAuthAuthenticator(self.client, self.pluginRun)
# auth.isTest = True # for testing
auth.authenticate()
self.api = MyAPIClient(self.pluginRun.account[0].secret)
def add_to_schema(self):
self.client.add_to_schema(MyItem("my name", 10))
class MyPasswordPlugin(PluginBase):
""""""
def __init__(self, **kwargs):
super().__init__(**kwargs)
def run(self):
print("running")
self.login()
items = self.api.get_data()
for item in items:
self.client.create(MyItem(name=item['name'], age=item['age']))
def login(self):
auth = PasswordAuthenticator(self.client, self.pluginRun)
auth.isTest = True
token = auth.authenticate()
self.api = MyAPIClient(token)
# or use account.identifier and account.secret directly e.g. MyAPIClient(username=account.identifier, password=account.secret)
def add_to_schema(self):
self.client.add_to_schema(MyItem("my name", 10))
```
%% Cell type:markdown id: tags:
Memri plugins need to define at least 2 methods: `.run()` and `.add_to_schema()`. `.run()` defines the logic of the plugin. `.add_to_schema()` defines the schema for the plugin in the pod. Note that currently, `add_to_schema` requires all item to **have all properties defined that are used in the plugin**. In the future, we might replace add_to_schema, to be done automatically, based on a declarative schema defined in the plugin.
%% Cell type:markdown id: tags:
## Helper classes -
%% Cell type:code id: tags:
``` python
# hide
# export
def get_plugin_cls(plugin_module, plugin_name):
try:
module = importlib.import_module(plugin_module)
plugin_cls = getattr(module, plugin_name)
return plugin_cls
except (ImportError, AttributeError):
raise ImportError(f"Unknown plugin: {plugin_module}.{plugin_name}")
def run_plugin_from_run_id(run_id, client):
"""
Args:
run_id (int): id of the PluginRun
client (PodClient): client containing PluginRun
return_plugin (bool): Returns created plugin instance for testing purposes.
"""
run = client.get(run_id)
plugin_cls = get_plugin_cls(run.pluginModule, run.pluginName)
plugin = plugin_cls(client=client, pluginRun=run)
plugin.add_to_schema()
# TODO handle plugin status before run
plugin.run()
return plugin
```
%% Cell type:markdown id: tags:
### Test Plugin Runtime
%% Cell type:code id: tags:
``` python
# hide
from pymemri.pod.client import PodClient
from pymemri.plugin.schema import Account
from pymemri.plugin.pluginbase import PluginRun, run_plugin_from_run_id
client = PodClient()
# Create a dummy account to use for authentication within the plugin
account = Account(service="my_plugin_service", identifier="username", secret="password")
account.update(client)
# Create a run to enable plugin runtime
run = PluginRun("pymemri", "pymemri.plugin.pluginbase", "MyOAuthPlugin")
run.add_edge('account', account)
client.create(run)
plugin = run_plugin_from_run_id(run.id, client)
# check if authentication worked
assert plugin.pluginRun.account[0].identifier == "username"
assert plugin.pluginRun.account[0].secret == "dummy_access_token"
# check if items are saved
items = client.search({'type': 'MyItem'})
assert len(items) > 0
assert 'name_1' in [item.name for item in items]
# set a state
plugin.pluginRun.state = "test state"
plugin.pluginRun.update(client)
plugin.pluginRun.reload(client)
assert plugin.pluginRun.state == "test state"
```
%% Cell type:markdown id: tags:
## Run from id test -
%% Cell type:code id: tags:
``` python
```
%% Cell type:code id: tags:
``` python
# hide
# skip
client = PodClient()
run = PluginRun("pymemri", "pymemri.plugin.pluginbase", "MyPasswordPlugin", state="not started")
account = Account(identifier="login", secret="password")
run.add_edge("account", account)
assert client.add_to_schema(PluginRun("", "", "", "", ""))
assert client.create(run)
assert client.create(account)
assert client.create_edge(run.get_edges("account")[0])
run = client.get(run.id)
run_plugin_from_run_id(run.id, client);
```
%% Output
running
logging in with account login and password password
%% Cell type:code id: tags:
``` python
# export
# hide
def _parse_env():
env = os.environ
print("Reading `run_plugin()` parameters from environment variables")
try:
pod_full_address = env.get(POD_FULL_ADDRESS_ENV, DEFAULT_POD_ADDRESS)
plugin_run_json = json.loads(str(env[POD_TARGET_ITEM_ENV]))
print(plugin_run_json)
plugin_run_id = plugin_run_json["id"]
owner_key = env.get(POD_OWNER_KEY_ENV)
pod_auth_json = json.loads(str(env.get(POD_AUTH_JSON_ENV)))
return pod_full_address, plugin_run_id, pod_auth_json, owner_key
except KeyError as e:
raise Exception('Missing parameter: {}'.format(e)) from None
```
%% Cell type:markdown id: tags:
## Running your plugin using the CLI
%% Cell type:markdown id: tags:
Plugins can be started using the pymemri `run_plugin` or `simulate_run_plugin_from_frontend` CLI. With `run_plugin` the plugin is invoked directly by spawning a new python process, while `simulate_run_plugin_from_frontend` requests the pod to spawn a new process, docker container, or kubernetes container, which in calls `run_plugin` (for more info see `simulate_run_plugin_from_frontend`. When using `run_plugin`, you can either pass your run arguments as parameters, or set them as environment variables. If both are set, the CLI will use the passed arguments.
%% Cell type:code id: tags:
``` python
# export
# hide
@call_parse
def store_keys(path:Param("path to store the keys", str)=DEFAULT_POD_KEY_PATH,
database_key:Param("Database key of the pod", str)=None,
owner_key:Param("Owner key of the pod", str)=None):
if database_key is None: database_key = PodClient.generate_random_key()
if owner_key is None: owner_key = PodClient.generate_random_key()
obj = {"database_key": database_key,
"owner_key": owner_key}
Path(path).parent.mkdir(parents=True, exist_ok=True)
if path.exists():
timestr = time.strftime("%Y%m%d-%H%M%S")
path.rename(POD_KEYS_FULL_FOLDER / f"keys-{timestr}.json")
write_json(obj, path)
```
%% Cell type:code id: tags:
``` python
# hide
store_keys()
```
%% Cell type:code id: tags:
``` python
# export
# hide
def parse_config(file, remove_container=False):
json_dict = read_json(file)
account = Account.from_json(json_dict["account"])
del json_dict["account"]
settings = json.dumps(json_dict["settings"])
del json_dict["settings"]
run = PluginRun.from_json(json_dict)
run.settings = settings
run.add_edge("account", account)
if remove_container:
run.containerImage = "none"
return run
def create_run_expanded(client, run):
client.create(run)
accounts = run.account
if accounts:
account=accounts[0]
client.create(account)
client.create_edge(run.get_edges("account")[0])
```
%% Cell type:code id: tags:
``` python
# export
@call_parse
def run_plugin(pod_full_address:Param("The pod full address", str)=DEFAULT_POD_ADDRESS,
plugin_run_id:Param("Run id of the plugin to be executed", str)=None,
database_key:Param("Database key of the pod", str)=None,
owner_key:Param("Owner key of the pod", str)=None,
read_args_from_env:Param("Read the args from the environment", bool)=False,
config_file:Param("config file for the PluginRun", str)=None):
if read_args_from_env:
pod_full_address, plugin_run_id, pod_auth_json, owner_key = _parse_env()
database_key=None
else:
if database_key is None: database_key = read_pod_key("database_key")
if owner_key is None: owner_key = read_pod_key("owner_key")
pod_auth_json = None
client = PodClient(url=pod_full_address, database_key=database_key, owner_key=owner_key,
auth_json=pod_auth_json)
if config_file is not None:
run = parse_config(config_file, remove_container=True)
create_run_expanded(client, run)
plugin_run_id=run.id
print(f"pod_full_address={pod_full_address}\nowner_key={owner_key}\n")
run_plugin_from_run_id(run_id=plugin_run_id, client=client)
```
%% Cell type:markdown id: tags:
To start a plugin on your local machine, you can use the CLI. This will create a client for you, and run the code defined in `<myplugin>.run()`
%% Cell type:code id: tags:
``` python
run_plugin(config_file="../example_config.json")
```
%% Output
reading database_key from /Users/koen/.pymemri/pod_keys/keys.json
reading owner_key from /Users/koen/.pymemri/pod_keys/keys.json
pod_full_address=http://localhost:3030
owner_key=8677996173299944016776856689234978705539171358808241281853139489
running
logging in with account myusername and password mypassword
%% Cell type:markdown id: tags:
> Note: The data that is created here should be in the pod in order for this to work
%% Cell type:markdown id: tags:
## Run from pod
%% Cell type:markdown id: tags:
In production, we start plugins by making an API call to the pod, which in turn creates an environment for the plugin and starts it using docker containers, kubernetes containers or a shell script. We can start this process using the `simulate_run_plugin_from_frontend` CLI. **Note that when using docker, provided container name should be "installed" within the Pod environemnt (e.g. `docker build -t pymemri .` for this repo) in order to start it.**
%% Cell type:markdown id: tags:
![running a plugin](images/running_a_plugin.svg)
%% Cell type:code id: tags:
``` python
# export
from fastcore.script import call_parse, Param
import os
@call_parse
def simulate_run_plugin_from_frontend(pod_full_address:Param("The pod full address", str)=DEFAULT_POD_ADDRESS,
database_key:Param("Database key of the pod", str)=None,
owner_key:Param("Owner key of the pod", str)=None,
container:Param("Pod container to run frod", str)=None,
plugin_path:Param("Plugin path", str)=None,
settings_file:Param("Plugin settings (json)", str)=None,
config_file:Param("config file for the PluginRun", str)=None,
account_id:Param("Account id to be used inside the plugin", str)=None):
# TODO remove container, plugin_module, plugin_name and move to Plugin item.
# Open question: This presumes Plugin item is already in pod before simulate_run_plugin_from_frontend is called.
if database_key is None: database_key = read_pod_key("database_key")
if owner_key is None: owner_key = read_pod_key("owner_key")
params = [pod_full_address, database_key, owner_key]
if (None in params):
raise ValueError(f"Defined some params to run indexer, but not all")
client = PodClient(url=pod_full_address, database_key=database_key, owner_key=owner_key)
for name, val in [("pod_full_address", pod_full_address), ("owner_key", owner_key)]:
print(f"{name}={val}")
# if settings_file is not None:
# with open(settings_file, 'r') as f:
# settings = f.read()
# else:
# settings = None
if config_file is not None:
run = parse_config(config_file)
create_run_expanded(client, run)
else:
if container is None:
container = plugin_path.split(".", 1)[0]
print(f"Inferred '{container}' as plugin container name")
plugin_module, plugin_name = plugin_path.rsplit(".", 1)
run = PluginRun(container, plugin_module, plugin_name)
if account_id is not None:
account = client.get(account_id)
run.add_edge('account', account)
print(f"Using existing {account}")
client.create(run)
print(f"\ncalling the `create` api on {pod_full_address} to make your Pod start "
f"a plugin with id {run.id}.")
print(f"*Check the pod log/console for debug output.*")
return run
```
%% Cell type:code id: tags:
``` python
client = PodClient()
```
%% Cell type:code id: tags:
``` python
!simulate_run_plugin_from_frontend --config_file="../example_config.json"
```
%% Output
reading database_key from /Users/koen/.pymemri/pod_keys/keys.json
reading owner_key from /Users/koen/.pymemri/pod_keys/keys.json
pod_full_address=http://localhost:3030
owner_key=8677996173299944016776856689234978705539171358808241281853139489
calling the `create` api on http://localhost:3030 to make your Pod start a plugin with id 4DfDBbcdcbABcf822Fc7DC5d5b3C3BDc.
*Check the pod log/console for debug output.*
%% Cell type:code id: tags:
``` python
# hide
# !simulate_run_plugin_from_frontend --plugin_path="pymemri.plugin.pluginbase.MyOAuthPlugin"
```
%% Cell type:markdown id: tags:
## Appendix -
%% Cell type:code id: tags:
``` python
# hide
# client.start_plugin("pymemri", run.id)
```
%% Cell type:code id: tags:
``` python
# hide
# class StartPlugin(Item):
# properties = Item.properties + ["container", "targetItemId"]
# edges = Item.edges
# def __init__(self, container=None, targetItemId=None, **kwargs):
# super().__init__(**kwargs)
# self.container = container
# self.targetItemId = targetItemId
```
%% Cell type:code id: tags:
``` python
# hide
# class PluginSettings(Item):
# def __init__(self, settings_dict):
# self.settings_dict=settings_dict
# def __getattr__(self, k):
# if k in self.settings_dict:
# return self.settings_dict[k]
# @classmethod
# def from_string(cls, s):
# objs = json.loads(s)
# cls(objs)
```
%% Cell type:code id: tags:
``` python
# hide
# # export
# def generate_test_env(client, indexer_run):
# payload = json.dumps({DATABASE_KEY_ENV: client.database_key, OWNER_KEY_ENV: client.owner_key})
# return {POD_FULL_ADDRESS_ENV: DEFAULT_POD_ADDRESS,
# POD_TARGET_ITEM: indexer_run.id,
# POD_SERVICE_PAYLOAD_ENV: payload}
```
%% Cell type:code id: tags:
``` python
# hide
# run_plugin(env=generate_test_env(client, run))
```
%% Cell type:markdown id: tags:
# Export -
%% Cell type:code id: tags:
``` python
# hide
from nbdev.export import *
notebook2script()
```
%% Output
Converted basic.ipynb.
Converted data.photo.ipynb.
Converted importers.Importer.ipynb.
Converted importers.util.ipynb.
Converted index.ipynb.
Converted indexers.indexer.ipynb.
Converted itembase.ipynb.
Converted plugin.pluginbase.ipynb.
Converted pod.client.ipynb.
%% Cell type:code id: tags:
``` python
```
......
......@@ -118,6 +118,7 @@ class MyPasswordPlugin(PluginBase):
auth.isTest = True
token = auth.authenticate()
self.api = MyAPIClient(token)
# or use account.identifier and account.secret directly e.g. MyAPIClient(username=account.identifier, password=account.secret)
def add_to_schema(self):
self.client.add_to_schema(MyItem("my name", 10))
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment