This commit is contained in:
Tim Van Baak 2022-08-21 08:15:17 -07:00
parent f6fed08e26
commit e801f15066
5 changed files with 178 additions and 0 deletions

View File

@ -0,0 +1,69 @@
Providers are modules that export:
CONFIG = {
"config key": "optional | required",
...
}
update(config, state) -> list[items]
And optionally:
action_NAME(config, state, item) -> None
on_create(config, state, item) -> None
on_delete(config, state, item) -> None
Sources are folders in the data directory with:
config: user-modified configuration values, drawn from the provider
state: provider-modified data
*.item: feed items
config reserved keys:
"provider": the provider the source uses
"name": given to sources by default, individuates sources from same provider
GET /config
Edit subfeed configs
GET /config/[feedname]
Edit config values for feedname
GET /feed/[feedname]
Feed view for feedname
<!-- GET /items
Get item JSON
?include=[tags]
?exclude=[tags]
?limit=100 -->
CLI:
intake create [provider] [--config KEY VALUE] [-c KEY VALUE] ...
load the provider
verify that the provider's config is satisfied
create the source and set the config values
intake update [source] [--reset]
load the source's config and state
use config.provider to load the provider
verify the source config against the provider config
call provider.update(config, state) to get current items
merge new items into current items
if --reset, new items overwrite everything, including active
intake deactivate [source] [--tag TAG] [--title TITLE]
load each item in the source and deactivate it
intake add [--id ID] [--title TITLE] [--link LINK] [--time TIME] [--author AUTHOR] [--body BODY] [--tags TAGS] [--ttl TTL] [--ttd TTD] [--tts TTS]
create the item and add it to the default source
intake feed [--json]
Dump active item feed to stdout
intake action [source] [item] [action]
load config, state, item
verify item supports this action
load config.provider
verify config
verify provider supports this action
action_[action](config, state, item)

21
providers/echo.py Normal file
View File

@ -0,0 +1,21 @@
from intake import BaseSettings, Setting
class Settings(BaseSettings):
message = Setting(default="Hello, world!")
def update(config, state):
pass
def on_create(config, state, item):
pass
def on_delete(config, state, item):
pass
def action_tick(config, state, item):
pass

View File

@ -15,6 +15,40 @@ from intake.provider import (
verify_settings,
verify_update,
)
from intake.source import initialize_source
def command_create(args):
"""Create a source."""
parser = argparse.ArgumentParser(
prog="intake create",
description=command_create.__doc__)
parser.add_argument("provider",
help="Provider to create the source from",
metavar="provider")
parser.add_argument("--setting", "-s",
help="Define a provider setting",
nargs=2,
action="append",
metavar="key value",
dest="settings",
default=[])
parser.add_argument("--data",
help="Data folder path",
metavar="path",
type=os.path.abspath)
parser.add_argument("--path",
nargs="+",
help="Additional paths to add to INTAKEPATH",
metavar="path",
type=os.path.abspath,
default=[])
args = parser.parse_args()
ret = 0
settings = {key: value for key, value in args.settings}
initialize_source(args.data, args.path, **settings)
def command_test(args):

View File

@ -45,6 +45,10 @@ class BaseSettings:
raise SettingMissingError(missing)
def issetting(obj):
return isinstance(obj, Setting)
class chdir:
"""
A context manager that changes the working directory inside the context.

50
server/intake/source.py Normal file
View File

@ -0,0 +1,50 @@
import inspect
import json
import os
from intake.provider import (
load_provider,
issetting,
SettingMissingError,
verify_settings,
)
def initialize_source(data_path, search_paths, **setting_kvs):
"""
Create a source's data folder and store its settings.
"""
# Verify the base required settings
if "name" not in setting_kvs:
raise KeyError("Missing name in settings")
if "provider" not in setting_kvs:
raise KeyError("Missing provider in settings")
# Check if the directory exists already
source_name = setting_kvs.get("name")
source_path = os.path.join(data_path, source_name)
if os.path.exists(source_path):
raise FileExistsError(source_path)
# Load the provider
provider_name = setting_kvs.get("provider")
provider = load_provider(search_paths, provider_name)
if not provider:
raise FileNotFoundError(provider_name)
# Verify that the provider has settings
verify_settings(provider)
# Check that all the required settings are populated
settings = inspect.getmembers(provider.Settings, issetting)
for name, setting in settings:
if setting.required and name not in setting_kvs:
raise SettingMissingError()
# Create the directory
os.mkdir(source_path)
# Create the settings file
setting_json = {}
for name, setting in settings:
setting_json[name] = setting_kvs.get(name, setting.default)
with open(os.path.join(source_path, ".settings"), 'w') as f:
json.dump(setting_json, f, indent=2)
# Create the state file
with open(os.path.join(source_path, ".state"), 'w') as f:
json.dump({}, f, indent=2)