diff --git a/annotator/auth.py b/annotator/auth.py index f9f56ee..9020213 100644 --- a/annotator/auth.py +++ b/annotator/auth.py @@ -13,8 +13,8 @@ def __init__(self, key): class User(object): - def __init__(self, id, consumer, is_admin): - self.id = id + def __init__(self, userid, consumer, is_admin): + self.id = userid self.consumer = consumer self.is_admin = is_admin @@ -108,7 +108,7 @@ def encode_token(token, secret): def decode_token(token, secret='', ttl=DEFAULT_TTL, verify=True): try: - if not type(token) is bytes: + if not isinstance(token, bytes): if six.PY3: token = bytes(token, 'utf-8') else: diff --git a/annotator/document.py b/annotator/document.py index 967c1b2..ef68147 100644 --- a/annotator/document.py +++ b/annotator/document.py @@ -55,7 +55,7 @@ def _get_all_by_uris(cls, uris): # index, so ignore this sort instruction if # 'updated' appears unmapped due to an empty # index. - 'ignore_unmapped': True,}}]} + 'ignore_unmapped': True}}]} res = cls.es.conn.search(index=cls.es.index, doc_type=cls.__type__, diff --git a/annotator/elasticsearch.py b/annotator/elasticsearch.py index 7131168..415fe77 100644 --- a/annotator/elasticsearch.py +++ b/annotator/elasticsearch.py @@ -1,7 +1,5 @@ from __future__ import absolute_import -import csv -import json import logging import datetime @@ -10,26 +8,26 @@ import elasticsearch from six import iteritems from six.moves.urllib.parse import urlparse -from annotator.atoi import atoi log = logging.getLogger(__name__) RESULTS_MAX_SIZE = 200 RESULTS_DEFAULT_SIZE = 20 + class ElasticSearch(object): """ Thin wrapper around an ElasticSearch connection to make connection handling more convenient. - Settings for the ES host and index name etcetera can still be changed in the - corresponding attributes before the connection (self.conn) is used. + Settings for the ES host and index name etcetera can still be changed in + the corresponding attributes before the connection (self.conn) is used. """ def __init__(self, - host = 'http://127.0.0.1:9200', - index = 'annotator', - authorization_enabled = False): + host='http://127.0.0.1:9200', + index='annotator', + authorization_enabled=False): self.host = host self.index = index self.authorization_enabled = authorization_enabled @@ -41,7 +39,7 @@ def _connect(self): parsed = urlparse(host) connargs = { - 'host': parsed.hostname, + 'host': parsed.hostname, } username = parsed.username @@ -89,7 +87,7 @@ class _Model(dict): @classmethod def create_all(cls): - log.info("Creating index '%s'." % cls.es.index) + log.info("Creating index '%s'.", cls.es.index) conn = cls.es.conn try: conn.indices.create(cls.es.index) @@ -100,7 +98,7 @@ def create_all(cls): or e.error.startswith('InvalidIndexNameException')): log.fatal("Failed to create an Elasticsearch index") raise - log.warn("Index creation failed as index appears to already exist.") + log.warn("Index creation failed: index appears to already exist.") mapping = cls.get_mapping() conn.indices.put_mapping(index=cls.es.index, doc_type=cls.__type__, @@ -130,13 +128,13 @@ def drop_all(cls): # It would be lovely if this were called 'get', but the dict semantics # already define that method name. @classmethod - def fetch(cls, id): + def fetch(cls, docid): doc = cls.es.conn.get(index=cls.es.index, doc_type=cls.__type__, ignore=404, - id=id) + id=docid) if doc.get('found', True): - return cls(doc['_source'], id=id) + return cls(doc['_source'], id=docid) @classmethod def _build_query(cls, query=None, offset=None, limit=None, sort=None, order=None): @@ -189,7 +187,7 @@ def search_raw(cls, query=None, params=None, raw_result=False): def count(cls, **kwargs): """Like search, but only count the number of matches.""" kwargs.setdefault('params', {}) - kwargs['params'].update({'search_type':'count'}) + kwargs['params'].update({'search_type': 'count'}) res = cls.search(raw_result=True, **kwargs) return res['hits']['total'] diff --git a/annotator/store.py b/annotator/store.py index 1e5d64f..f47769a 100644 --- a/annotator/store.py +++ b/annotator/store.py @@ -14,6 +14,7 @@ """ from __future__ import absolute_import +import csv import json from elasticsearch.exceptions import TransportError @@ -25,6 +26,7 @@ from annotator.atoi import atoi from annotator.annotation import Annotation +from annotator.elasticsearch import RESULTS_MAX_SIZE store = Blueprint('store', __name__) @@ -90,7 +92,7 @@ def root(): 'read': { 'method': 'GET', 'url': url_for('.read_annotation', - id=':id', + docid=':id', _external=True), 'desc': "Get an existing annotation" }, @@ -99,7 +101,7 @@ def root(): 'url': url_for( '.update_annotation', - id=':id', + docid=':id', _external=True), 'query': { 'refresh': { @@ -113,7 +115,7 @@ def root(): 'delete': { 'method': 'DELETE', 'url': url_for('.delete_annotation', - id=':id', + docid=':id', _external=True), 'desc': "Delete an annotation" } @@ -173,7 +175,7 @@ def create_annotation(): refresh = request.args.get('refresh') != 'false' annotation.save(refresh=refresh) - location = url_for('.read_annotation', id=annotation['id']) + location = url_for('.read_annotation', docid=annotation['id']) return jsonify(annotation), 201, {'Location': location} else: @@ -182,9 +184,9 @@ def create_annotation(): # READ -@store.route('/annotations/') -def read_annotation(id): - annotation = g.annotation_class.fetch(id) +@store.route('/annotations/') +def read_annotation(docid): + annotation = g.annotation_class.fetch(docid) if not annotation: return jsonify('Annotation not found!', status=404) @@ -196,9 +198,9 @@ def read_annotation(id): # UPDATE -@store.route('/annotations/', methods=['POST', 'PUT']) -def update_annotation(id): - annotation = g.annotation_class.fetch(id) +@store.route('/annotations/', methods=['POST', 'PUT']) +def update_annotation(docid): + annotation = g.annotation_class.fetch(docid) if not annotation: return jsonify('Annotation not found! No update performed.', status=404) @@ -209,7 +211,7 @@ def update_annotation(id): if request.json is not None: updated = _filter_input(request.json, UPDATE_FILTER_FIELDS) - updated['id'] = id # use id from URL, regardless of what arrives in + updated['id'] = docid # use id from URL, regardless of what arrives in # JSON payload changing_permissions = ( @@ -238,9 +240,9 @@ def update_annotation(id): # DELETE -@store.route('/annotations/', methods=['DELETE']) -def delete_annotation(id): - annotation = g.annotation_class.fetch(id) +@store.route('/annotations/', methods=['DELETE']) +def delete_annotation(docid): + annotation = g.annotation_class.fetch(docid) if not annotation: return jsonify('Annotation not found. No delete performed.', diff --git a/reindex.py b/reindex.py index 79bc358..0011ab0 100755 --- a/reindex.py +++ b/reindex.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -import sys import argparse from elasticsearch import Elasticsearch @@ -12,7 +11,8 @@ WARNING: Documents that are created while reindexing may be lost! """ -def main(argv): + +def main(): argparser = argparse.ArgumentParser(description=description) argparser.add_argument('old_index', help="Index to read from") argparser.add_argument('new_index', help="Index to write to") @@ -39,4 +39,4 @@ def main(argv): reindexer.alias(new_index, alias) if __name__ == '__main__': - main(sys.argv) + main() diff --git a/run.py b/run.py index 3af8aad..5dc9dbd 100755 --- a/run.py +++ b/run.py @@ -34,12 +34,13 @@ here = os.path.dirname(__file__) -def main(): + +def main(argv): app = Flask(__name__) cfg_file = 'annotator.cfg' - if len(sys.argv) == 2: - cfg_file = sys.argv[1] + if len(argv) == 2: + cfg_file = argv[1] cfg_path = os.path.join(here, cfg_file) @@ -47,7 +48,8 @@ def main(): app.config.from_pyfile(cfg_path) except IOError: print("Could not find config file %s" % cfg_path, file=sys.stderr) - print("Perhaps you need to copy annotator.cfg.example to annotator.cfg", file=sys.stderr) + print("Perhaps copy annotator.cfg.example to annotator.cfg", + file=sys.stderr) sys.exit(1) if app.config.get('ELASTICSEARCH_HOST') is not None: @@ -69,10 +71,11 @@ def main(): date = time.strftime('%Y-%m-%d') log.fatal("Elasticsearch index mapping is incorrect! Please " "reindex it. You can use reindex.py for this, e.g. " - "python reindex.py --host {0} {1} {1}-{2}".format( - es.host, - es.index, - date)) + "python reindex.py --host %s %s %s-%s", + es.host, + es.index, + es.index, + date) raise @app.before_request @@ -108,4 +111,4 @@ def before_request(): app.run(host=host, port=port) if __name__ == '__main__': - main() + main(sys.argv) diff --git a/tests/helpers.py b/tests/helpers.py index e1c728a..f3a6361 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -5,8 +5,8 @@ def __init__(self, key='mockconsumer'): self.ttl = 86400 class MockUser(object): - def __init__(self, id='alice', consumer=None): - self.id = id + def __init__(self, userid='alice', consumer=None): + self.id = userid self.consumer = MockConsumer(consumer if consumer is not None else 'mockconsumer') self.is_admin = False diff --git a/tests/test_store.py b/tests/test_store.py index 28d13a7..648947b 100644 --- a/tests/test_store.py +++ b/tests/test_store.py @@ -264,7 +264,6 @@ def test_update_ignore_auth_in_payload(self): assert_equal(upd['user'], self.user.id, "annotation 'user' field should not be futzable by API") assert_equal(upd['consumer'], self.user.consumer.key, "annotation 'consumer' field should not be futzable by API") - def test_delete(self): kwargs = dict(text=u"Bar", id='456') ann = self._create_annotation(**kwargs)