From 129a585da24ffb07d70d82e4d371db58b47703c3 Mon Sep 17 00:00:00 2001 From: Adam-Hammo Date: Thu, 17 Sep 2020 12:51:12 +1000 Subject: [PATCH 1/3] Added async flag to init and user_agent header --- arlulaapi/__init__.py | 80 +++++++++++++++++++++++++++++-------------- setup.py | 28 +++++++-------- 2 files changed, 69 insertions(+), 39 deletions(-) diff --git a/arlulaapi/__init__.py b/arlulaapi/__init__.py index a3a2a72..32b459f 100644 --- a/arlulaapi/__init__.py +++ b/arlulaapi/__init__.py @@ -7,11 +7,19 @@ import os import math import pgeocode +import platform # warnings.filterwarnings("ignore") name = "arlulaapi" +sdk_version = "1.1.9" +py_version = sys.version.split(' ')[0] +os_version = platform.platform() +def_ua = "archive-sdk " + \ + sys.version.split(' ')[0] + " python " + py_version + " OS " + os_version # Object generator that converts returned JSON into a Python object + + class ArlulaObj(object): def __init__(self, d): for a, b in d.items(): @@ -25,10 +33,14 @@ def __repr__(self): return str(['{}: {}'.format(attr, value) for attr, value in self.__dict__.items()])[1:-1].replace('\'', '') # Exception when group searching + + def gsearch_exception(r, e): return("request failed") # Custom Exception Class + + class ArlulaSessionError(Exception): def __init__(self, value): self.value = value @@ -37,26 +49,34 @@ def __str__(self): return self.value # Custom Warning Class + + class ArlulaSessionWarning(Warning): pass # The ArlulaSession code # At some point, this should be separated into a diff file + + class ArlulaSession: - def __init__(self, key, secret): + def __init__(self, key, secret, allow_async=True, user_agent=def_ua): # Encode the key and secret def atob(x): return x.encode('utf-8') self.token = base64.b64encode(atob( key + ':' + secret)).decode('utf-8') self.header = { 'Authorization': "Basic "+self.token, + 'User-Agent': user_agent } self.baseURL = "https://api.arlula.com" self.max_cloud = 100 # Supplier max bounds on cloud values self.max_cloud_vals = {"landsat": 100, "SIIS": 100, "maxar": 100} self.validate_creds() + self.allow_async = allow_async + if self.allow_async: + import grequests # Enables use of `with` keyword def __enter__(self): @@ -72,17 +92,18 @@ def close(self): self.header = None def set_max_cloud(self, val): - if (val<0 or val > 100) : - raise ArlulaSessionError("Max cloud value must be between 0 and 100") + if (val < 0 or val > 100): + raise ArlulaSessionError( + "Max cloud value must be between 0 and 100") self.max_cloud = val def get_max_cloud(self): return self.max_cloud def filter(self, r): - if r['supplier']=="" : + if r['supplier'] == "": return False - return r['cloud']/self.max_cloud_vals.get(r["supplier"])*100<=self.max_cloud + return r['cloud']/self.max_cloud_vals.get(r["supplier"])*100 <= self.max_cloud def validate_creds(self): url = self.baseURL+"/api/test" @@ -103,12 +124,16 @@ def search(self, north=None, south=None, east=None, - west=None): + west=None, + params=None): url = self.baseURL+"/api/search" - querystring = {"start": start, "end": end, - "res": res, "lat": lat, "long": long, - "north": north, "south": south, "east": east, "west": west} + if params is None: + querystring = {"start": start, "end": end, + "res": res, "lat": lat, "long": long, + "north": north, "south": south, "east": east, "west": west} + else: + querystring = params querystring = {k: v for k, v in querystring.items() if v is not None or v == 0} @@ -124,26 +149,31 @@ def search(self, def gsearch(self, params): searches = [] - for p in params: - url = self.baseURL+"/api/search" + if self.allow_async: + for p in params: + url = self.baseURL+"/api/search" - querystring = {"start": p.get('start'), "end": p.get('end'), "res": p.get('res'), - "lat": p.get('lat'), "long": p.get('long'), "north": p.get('north'), - "south": p.get('south'), "east": p.get('east'), "west": p.get('west')} + querystring = {k: v for k, v in p.items() + if v is not None or v == 0} - querystring = {k: v for k, v in querystring.items() - if v is not None or v == 0} + headers = self.header - headers = self.header - - searches.append(grequests.get( - url, headers=headers, params=querystring)) + searches.append(grequests.get( + url, headers=headers, params=querystring)) - response = grequests.map(searches, exception_handler=gsearch_exception) - result = [] - for r in response: - result.append([ArlulaObj(x) for x in json.loads(r.text) if self.filter(x)]) - return result + response = grequests.map( + searches, exception_handler=gsearch_exception) + result = [] + for r in response: + result.append([ArlulaObj(x) + for x in json.loads(r.text) if self.filter(x)]) + return result + else: + # Non-async. Just calls 'search' sequentially + responses = [] + for p in params: + responses.append(self.search(params=p)) + return responses def get_order(self, id=""): diff --git a/setup.py b/setup.py index cf589fb..bedd2b0 100644 --- a/setup.py +++ b/setup.py @@ -4,20 +4,20 @@ long_description = fh.read() setuptools.setup( - name='arlulaapi', - version='1.1.9', - author="Adam Hamilton", - author_email="adamhammo99@gmail.com", - description="A package to facilitate access to the Arlula Imagery Marketplace API", - - long_description=long_description, - long_description_content_type="text/markdown", - url="https://github.com/Arlula/python-archive-sdk.git", - packages=["arlulaapi"], + name='arlulaapi', + version='1.1.9', + author="Adam Hamilton", + author_email="adamhammo99@gmail.com", + description="A package to facilitate access to the Arlula Imagery Marketplace API", + + long_description=long_description, + long_description_content_type="text/markdown", + url="https://github.com/Arlula/python-archive-sdk.git", + packages=["arlulaapi"], install_requires=['grequests', 'requests', 'pgeocode'], - classifiers=[ - "Programming Language :: Python :: 3", + classifiers=[ + "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", - ], - ) + ], +) From 89a529d0e2979adaf7142fe48089fc47717ca5cb Mon Sep 17 00:00:00 2001 From: Adam-Hammo Date: Thu, 17 Sep 2020 12:51:37 +1000 Subject: [PATCH 2/3] iterated version number --- arlulaapi/__init__.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arlulaapi/__init__.py b/arlulaapi/__init__.py index 32b459f..729c8d3 100644 --- a/arlulaapi/__init__.py +++ b/arlulaapi/__init__.py @@ -11,7 +11,7 @@ # warnings.filterwarnings("ignore") name = "arlulaapi" -sdk_version = "1.1.9" +sdk_version = "1.2.0" py_version = sys.version.split(' ')[0] os_version = platform.platform() def_ua = "archive-sdk " + \ diff --git a/setup.py b/setup.py index bedd2b0..86edf3f 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name='arlulaapi', - version='1.1.9', + version='1.2.0', author="Adam Hamilton", author_email="adamhammo99@gmail.com", description="A package to facilitate access to the Arlula Imagery Marketplace API", From fae0264aeda0f3471323a869682b03d3938649bf Mon Sep 17 00:00:00 2001 From: Adam-Hammo Date: Thu, 24 Sep 2020 09:00:54 +1000 Subject: [PATCH 3/3] added toggleable async, updated readme --- README.md | 20 +++++++++++++------- arlulaapi/__init__.py | 3 --- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index dd631ed..cce870f 100644 --- a/README.md +++ b/README.md @@ -16,15 +16,13 @@ Instantiate an ArlulaSession object using your API credentials as below. This wi ```python import arlulaapi -"""using the `with` keyword (recommended)""" -with arlulaapi.ArlulaSession(key, secret) as arlula_session : - # Call required methods - -"""explicitly defining the session""" +"""opening a session""" arlula_session = arlulaapi.ArlulaSession(key, secret) # Call required methods -# close() removes your key and secret from the session, if desired -arlula_session.close() + +"""using a context manager""" +with arlulaapi.ArlulaSession(key, secret) as arlula_session : + # Call required methods ``` ## Utilities @@ -158,3 +156,11 @@ res = arlula_session.search_postcode( print(res[2].location.name) # prints "Melbourne" search_result = res[2].data # Melbourne search result ``` + +## Advanced +**Turn off async features** + +Async features used in gsearch can be turned off when instantiating a session. This will avoid importing gevent. The gsearch functionality will still work, but will make requests synchronously. +```python +arlula_session = arlulaapi.ArlulaSession(key, secret, allow_async=False) +``` \ No newline at end of file diff --git a/arlulaapi/__init__.py b/arlulaapi/__init__.py index 729c8d3..24df6b6 100644 --- a/arlulaapi/__init__.py +++ b/arlulaapi/__init__.py @@ -1,4 +1,3 @@ -import grequests import base64 import requests import json @@ -8,7 +7,6 @@ import math import pgeocode import platform -# warnings.filterwarnings("ignore") name = "arlulaapi" sdk_version = "1.2.0" @@ -55,7 +53,6 @@ class ArlulaSessionWarning(Warning): pass # The ArlulaSession code -# At some point, this should be separated into a diff file class ArlulaSession: