aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBryan Newbold <bnewbold@robocracy.org>2018-04-23 17:36:22 -0700
committerBryan Newbold <bnewbold@robocracy.org>2018-04-23 17:36:22 -0700
commit5416a2570e7167ca2e62352dda10d2f371b994a7 (patch)
tree02439733d6b74dc6e83aaa49a314b49c5ece5a67
parent5bdd3f6e871599acb339aadc9b78cc12860f9759 (diff)
downloadfatcat-5416a2570e7167ca2e62352dda10d2f371b994a7.tar.gz
fatcat-5416a2570e7167ca2e62352dda10d2f371b994a7.zip
start work on api client
-rw-r--r--fatcat/api_client.py103
-rwxr-xr-xfatcat_client.py37
-rw-r--r--tests/api_client.py14
-rw-r--r--tests/fixtures.py64
-rw-r--r--tests/test_fixtures.py29
5 files changed, 215 insertions, 32 deletions
diff --git a/fatcat/api_client.py b/fatcat/api_client.py
new file mode 100644
index 00000000..12c70407
--- /dev/null
+++ b/fatcat/api_client.py
@@ -0,0 +1,103 @@
+
+import json
+import requests
+
+
+class FatCatApiClient:
+
+ def __init__(self, host_url):
+ self.host_url = host_url
+ self.session = requests.Session()
+
+
+ def get(self, path):
+ return self.session.get(self.host_url + path)
+
+
+ def post(self, path, data=None, headers=None):
+ hdrs = {"content-type": "application/json"}
+ if headers:
+ hdrs.update(headers)
+ #if type(data) == dict:
+ # data = json.dumps(data, indent=None).encode('utf-8')
+ return self.session.post(self.host_url + path, json=data, headers=hdrs)
+
+
+ def import_crossref_file(self, json_file):
+ with open(json_file, 'r') as file:
+ for line in file:
+ obj = json.loads(line)
+ self.import_crossref_dict(obj)
+
+
+ def new_edit_group(self):
+ rv = self.post('/v0/editgroup')
+ assert rv.status_code == 200
+ editgroup_id = rv.json()['id']
+ return editgroup_id
+
+
+ def import_crossref_dict(self, meta):
+
+ # creators
+ creators = []
+ for am in meta['author']:
+ c = dict(name="{} {}".format(am['given'], am['family']),
+ sortname="{}, {}".format(am['family'], am['given']),
+ orcid=None)
+ creators.append(c)
+
+ # container
+ container = dict(
+ issn=meta['ISSN'][0],
+ name=meta['container-title'][0],
+ #container_id=None,
+ #sortname=meta['short-container-title'][0])
+ publisher=meta['publisher'])
+ #rv = self.post('/v0/container', data=container)
+ #assert rv.status_code == 200
+ #container_id = rv.json()['id']
+
+ # references
+ refs = []
+ for i, rm in enumerate(meta.get('reference', [])):
+ ref = dict(
+ doi=rm.get("DOI", None),
+ index=i+1,
+ # TODO: how to generate a proper stub here from k/v metadata?
+ stub="| ".join(rm.values()))
+ refs.append(ref)
+
+ # work and release
+ title = meta['title'][0]
+ rv = self.post('/v0/work',
+ data=dict(title=title)) #work_type="book"
+ assert rv.status_code == 200
+ work_id = rv.json()['id']
+
+ rv = self.post('/v0/release', data=dict(
+ title=title,
+ work=work_id,
+ # XXX: creators=creators,
+ # XXX: refs=refs,
+ #container=container_id,
+ release_type=meta['type'],
+ doi=meta['DOI'],
+ date=meta['created']['date-time'],
+ license=meta.get('license', [dict(URL=None)])[0]['URL'] or None,
+ issue=meta.get('issue', None),
+ volume=meta.get('volume', None),
+ pages=meta.get('page', None),
+ extra=dict(crossref={
+ 'links': meta.get('link', []),
+ 'subject': meta['subject'],
+ 'type': meta['type'],
+ 'alternative-id': meta.get('alternative-id', [])})))
+ assert rv.status_code == 200
+ release_id = rv.json()['id']
+
+
+ def health(self):
+ rv = self.get("/health")
+ assert rv.status_code == 200
+ return rv.json()
diff --git a/fatcat_client.py b/fatcat_client.py
new file mode 100755
index 00000000..4b3e1cc7
--- /dev/null
+++ b/fatcat_client.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+
+import argparse
+from fatcat.api_client import FatCatApiClient
+
+def import_crossref(args):
+ fcc = FatCatApiClient(args.host_url)
+ fcc.import_crossref_file(args.json_file)
+
+def health(args):
+ fcc = FatCatApiClient(args.host_url)
+ print(fcc.health())
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--debug',
+ action='store_true',
+ help="enable debugging interface")
+ parser.add_argument('--host-url',
+ default="http://localhost:8040",
+ help="connect to this host/port")
+ subparsers = parser.add_subparsers()
+
+ sub_import_crossref = subparsers.add_parser('import-crossref',
+ aliases=['lc'])
+ sub_import_crossref.set_defaults(func=import_crossref)
+ sub_import_crossref.add_argument('json_file',
+ help="")
+
+ sub_health = subparsers.add_parser('health')
+ sub_health.set_defaults(func=health)
+
+ args = parser.parse_args()
+ args.func(args)
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/api_client.py b/tests/api_client.py
new file mode 100644
index 00000000..37e3da56
--- /dev/null
+++ b/tests/api_client.py
@@ -0,0 +1,14 @@
+
+import pytest
+import fatcat.api_client
+from fixtures import *
+
+
+def test_client_health(api_client):
+ assert api_client.health() != None
+
+
+def test_import_crossref(api_client):
+ api_client.import_crossref_file('tests/files/crossref-works.2018-01-21.badsample.json')
+
+ # TODO: use API to check that entities actually created...
diff --git a/tests/fixtures.py b/tests/fixtures.py
index 04b4314a..30358a5c 100644
--- a/tests/fixtures.py
+++ b/tests/fixtures.py
@@ -1,23 +1,52 @@
+import os
+import time
+import json
import pytest
+import signal
import fatcat
import fatcat.sql
from fatcat.models import *
@pytest.fixture
-def app():
+def full_app():
fatcat.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
fatcat.app.testing = True
- fatcat.app.debug = True
+ fatcat.app.debug = False
fatcat.db.session.remove()
fatcat.db.drop_all()
fatcat.db.create_all()
fatcat.sql.populate_db()
- return fatcat.app.test_client()
+ return fatcat.app
+
+@pytest.fixture
+def app(full_app):
+ return full_app.test_client()
@pytest.fixture
def rich_app(app):
+ enrichen_test_app(app)
+ return app
+
+
+@pytest.fixture(scope="function")
+def api_client(full_app):
+
+ pid = os.fork()
+ if pid == 0:
+ full_app.testing = False
+ full_app.run(host="localhost", port=8444, debug=False)
+ os._exit(0)
+
+ time.sleep(0.2)
+ yield fatcat.api_client.FatCatApiClient("http://localhost:8444")
+ os.kill(pid, signal.SIGKILL)
+
+
+## Helpers ##################################################################
+
+def enrichen_test_app(app):
rv = app.post('/v0/editgroup',
data=json.dumps(dict(
@@ -113,35 +142,6 @@ def rich_app(app):
headers={"content-type": "application/json"})
assert rv.status_code == 200
- return app
-
-def test_rich_app_fixture(rich_app):
- app = rich_app
-
- assert ChangelogEntry.query.count() == 1
-
- for cls in (WorkIdent, WorkRev, WorkEdit,
- ContainerIdent, ContainerRev, ContainerEdit,
- CreatorIdent, CreatorRev, CreatorEdit,
- FileIdent, FileRev, FileEdit):
- assert cls.query.count() == 1
- for cls in (ReleaseIdent, ReleaseRev, ReleaseEdit):
- assert cls.query.count() == 2
-
- for cls in (WorkIdent,
- ContainerIdent,
- CreatorIdent,
- FileIdent):
- assert cls.query.filter(cls.is_live==True).count() == 1
- assert ReleaseIdent.query.filter(ReleaseIdent.is_live==True).count() == 2
-
- # test that editor's active edit group is now invalid
- editor = Editor.query.first()
- assert editor.active_edit_group == None
-
-
-## Helpers ##################################################################
-
def check_entity_fields(e):
for key in ('rev', 'is_live', 'redirect_id'):
assert key in e
diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
new file mode 100644
index 00000000..2ced3bb5
--- /dev/null
+++ b/tests/test_fixtures.py
@@ -0,0 +1,29 @@
+
+import pytest
+import fatcat.api_client
+from fixtures import *
+
+
+def test_rich_app_fixture(rich_app):
+ app = rich_app
+
+ assert ChangelogEntry.query.count() == 1
+
+ for cls in (WorkIdent, WorkRev, WorkEdit,
+ ContainerIdent, ContainerRev, ContainerEdit,
+ CreatorIdent, CreatorRev, CreatorEdit,
+ FileIdent, FileRev, FileEdit):
+ assert cls.query.count() == 1
+ for cls in (ReleaseIdent, ReleaseRev, ReleaseEdit):
+ assert cls.query.count() == 2
+
+ for cls in (WorkIdent,
+ ContainerIdent,
+ CreatorIdent,
+ FileIdent):
+ assert cls.query.filter(cls.is_live==True).count() == 1
+ assert ReleaseIdent.query.filter(ReleaseIdent.is_live==True).count() == 2
+
+ # test that editor's active edit group is now invalid
+ editor = Editor.query.first()
+ assert editor.active_edit_group == None