Generic formatting system using objtools
This commit is contained in:
parent
a03a4b3f42
commit
78884ede5a
|
@ -1,3 +1,4 @@
|
|||
click>=6.7
|
||||
objtools>=0.1.0
|
||||
requests>=2.22
|
||||
twtxt>=1.2.2
|
||||
|
|
2
setup.py
2
setup.py
|
@ -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",
|
||||
|
|
|
@ -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__':
|
||||
|
|
|
@ -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)
|
Reference in New Issue