Generic formatting system using objtools

This commit is contained in:
Lucidiot 2019-09-23 21:07:34 +02:00
parent a03a4b3f42
commit 78884ede5a
Signed by: lucidiot
GPG Key ID: 3358C1CA6906FB8D
4 changed files with 109 additions and 10 deletions

View File

@ -1,3 +1,4 @@
click>=6.7
objtools>=0.1.0
requests>=2.22
twtxt>=1.2.2

View File

@ -30,7 +30,7 @@ setup(
'dev': dev_requirements,
},
license='GNU General Public License 3',
description="API client",
description="API client for twtxt registries",
long_description=open('README.rst').read(),
long_description_content_type='text/x-rst',
keywords="twtxt twitter registry twtxt-registry client",

View File

@ -1,23 +1,31 @@
#!/usr/bin/env python3
from urllib.parse import urlsplit, urlunsplit
import click
from objtools.collections import Namespace
from twtxt.config import Config
from twtxt_registry_client import RegistryClient
from twtxt_registry_client import RegistryClient, output
import click
@click.group(name='twtxt-registry')
@click.argument('registry_url', required=True)
@click.version_option()
@click.option('-k', '--insecure', is_flag=True)
@click.option('-f', '--format',
type=click.Choice(output.registry.keys()),
default='raw')
@click.pass_context
def cli(ctx, registry_url, insecure):
def cli(ctx, registry_url, insecure, format):
ctx.obj = Namespace()
scheme, netloc, path, query, fragment = urlsplit(registry_url)
if not scheme:
scheme = 'https'
if not netloc and path:
netloc, _, path = path.partition('/')
registry_url = urlunsplit((scheme, netloc, path, query, fragment))
ctx.obj = RegistryClient(registry_url, insecure=insecure)
ctx.obj.client = RegistryClient(registry_url, insecure=insecure)
ctx.obj.formatter = output.registry[format]()
@cli.command()
@ -45,21 +53,27 @@ def register(ctx, nickname, url):
nickname = nickname or config.nick
url = url or config.twturl
click.echo(ctx.obj.register(nickname, url).text)
click.echo(ctx.obj.formatter.format_response(
ctx.obj.client.register(nickname, url)
))
@cli.command()
@click.option('-q', '--query')
@click.pass_context
def users(ctx, query):
click.echo(ctx.obj.list_users(q=query).text)
click.echo(ctx.obj.formatter.format_users(
ctx.obj.client.list_users(q=query)
))
@cli.command()
@click.option('-q', '--query')
@click.pass_context
def tweets(ctx, query):
click.echo(ctx.obj.list_tweets(q=query).text)
click.echo(ctx.obj.formatter.format_tweets(
ctx.obj.client.list_tweets(q=query)
))
@cli.command()
@ -89,14 +103,18 @@ def mentions(ctx, name_or_url):
)
url = config.twturl
click.echo(ctx.obj.list_mentions(url).text)
click.echo(ctx.obj.formatter.format_tweets(
ctx.obj.client.list_mentions(url)
))
@cli.command()
@click.argument('name', required=True)
@click.pass_context
def tag(ctx, name):
click.echo(ctx.obj.list_tag_tweets(name).text)
click.echo(ctx.obj.formatter.format_tweets(
ctx.obj.client.list_tag_tweets(name)
))
if __name__ == '__main__':

View File

@ -0,0 +1,80 @@
from abc import ABCMeta, abstractmethod
from objtools.registry import ClassRegistry
import json
class FormatterRegistry(ClassRegistry):
def check_value(self, value):
assert issubclass(value, Formatter), 'Can only register formatters'
registry = FormatterRegistry()
class FormatterMetaclass(registry.metaclass, ABCMeta):
pass
class Formatter(metaclass=FormatterMetaclass, register=False):
@abstractmethod
def format_response(self, resp):
pass
@abstractmethod
def format_tweets(self, resp):
pass
@abstractmethod
def format_users(self, resp):
pass
class RawFormatter(Formatter, key='raw'):
def format_response(self, resp):
return resp.text
def format_tweets(self, resp):
return resp.text
def format_users(self, resp):
return resp.text
class JSONFormatter(Formatter, key='json'):
def format_response(self, resp):
return json.dumps({
'status_code': resp.status_code,
'url': resp.url,
'body': resp.text,
})
def format_tweets(self, resp):
if not resp.ok:
return self.format_response(resp)
output = []
for tweet in resp.text.splitlines():
nick, url, timestamp, message = tweet.split('\t', maxsplit=3)
output.append({
'nick': nick,
'url': url,
'timestamp': timestamp,
'message': message,
})
return json.dumps(output)
def format_users(self, resp):
if not resp.ok:
return self.format_response(resp)
output = []
for user in resp.text.splitlines():
nick, url, timestamp = user.split('\t', maxsplit=2)
output.append({
'nick': nick,
'url': url,
'timestamp': timestamp,
})
return json.dumps(output)