tmp
This commit is contained in:
parent
f6fed08e26
commit
e801f15066
69
README.md
69
README.md
|
@ -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)
|
|
@ -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
|
|
@ -15,6 +15,40 @@ from intake.provider import (
|
||||||
verify_settings,
|
verify_settings,
|
||||||
verify_update,
|
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):
|
def command_test(args):
|
||||||
|
|
|
@ -45,6 +45,10 @@ class BaseSettings:
|
||||||
raise SettingMissingError(missing)
|
raise SettingMissingError(missing)
|
||||||
|
|
||||||
|
|
||||||
|
def issetting(obj):
|
||||||
|
return isinstance(obj, Setting)
|
||||||
|
|
||||||
|
|
||||||
class chdir:
|
class chdir:
|
||||||
"""
|
"""
|
||||||
A context manager that changes the working directory inside the context.
|
A context manager that changes the working directory inside the context.
|
||||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue