Skip to content

[ALERT] Fix for breaking changes introduced by Bearer Token work #121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Dec 22, 2021
41 changes: 20 additions & 21 deletions Algorithmia/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,16 @@ class Client(object):
requestSession = None
bearerToken = None


def __init__(self, apiKey = None, apiAddress = None, caCert = None, bearerToken=None):
def __init__(self, apiKey=None, apiAddress=None, caCert=None, bearerToken=None):
# Override apiKey with environment variable
config = None
self.requestSession = requests.Session()
if apiKey is None and 'ALGORITHMIA_API_KEY' in os.environ:
apiKey = os.environ['ALGORITHMIA_API_KEY']
if apiKey is None:
if bearerToken is None and 'ALGORITHMIA_BEARER_TOKEN' in os.environ:
bearerToken = os.environ['ALGORITHMIA_BEARER_TOKEN']
self.bearerToken = bearerToken
elif bearerToken is None and 'ALGORITHMIA_BEARER_TOKEN' in os.environ:
bearerToken = os.environ['ALGORITHMIA_BEARER_TOKEN']

self.bearerToken = bearerToken
self.apiKey = apiKey
if apiAddress is not None:
self.apiAddress = apiAddress
Expand Down Expand Up @@ -225,8 +223,8 @@ def postJsonHelper(self, url, input_object, parse_response_as_json=True, **query
headers = {}
if self.apiKey is not None:
headers['Authorization'] = self.apiKey
else:
headers['Authorization'] = "Bearer "+ self.bearerToken
elif self.bearerToken is not None:
headers['Authorization'] = 'Bearer ' + self.bearerToken

input_json = None
if input_object is None:
Expand Down Expand Up @@ -254,42 +252,42 @@ def getHelper(self, url, **query_parameters):
headers = {}
if self.apiKey is not None:
headers['Authorization'] = self.apiKey
else:
headers['Authorization'] = 'Bearer '+ self.bearerToken
elif self.bearerToken is not None:
headers['Authorization'] = 'Bearer ' + self.bearerToken
return self.requestSession.get(self.apiAddress + url, headers=headers, params=query_parameters)

def getStreamHelper(self, url, **query_parameters):
headers = {}
if self.apiKey is not None:
headers['Authorization'] = self.apiKey
else:
headers['Authorization'] = 'Bearer '+ self.bearerToken
elif self.bearerToken is not None:
headers['Authorization'] = 'Bearer ' + self.bearerToken
return self.requestSession.get(self.apiAddress + url, headers=headers, params=query_parameters, stream=True)

def patchHelper(self, url, params):
headers = {'content-type': 'application/json'}
if self.apiKey is not None:
headers['Authorization'] = self.apiKey
else:
headers['Authorization'] = 'Bearer '+ self.bearerToken
elif self.bearerToken is not None:
headers['Authorization'] = 'Bearer ' + self.bearerToken
return self.requestSession.patch(self.apiAddress + url, headers=headers, data=json.dumps(params))

# Used internally to get http head result
def headHelper(self, url):
headers = {}
if self.apiKey is not None:
headers['Authorization'] = self.apiKey
else:
headers['Authorization'] = 'Bearer '+ self.bearerToken
elif self.bearerToken is not None:
headers['Authorization'] = 'Bearer ' + self.bearerToken
return self.requestSession.head(self.apiAddress + url, headers=headers)

# Used internally to http put a file
def putHelper(self, url, data):
headers = {}
if self.apiKey is not None:
headers['Authorization'] = self.apiKey
else:
headers['Authorization'] = 'Bearer '+ self.bearerToken
elif self.bearerToken is not None:
headers['Authorization'] = 'Bearer ' + self.bearerToken
if isJson(data):
headers['Content-Type'] = 'application/json'

Expand All @@ -303,8 +301,8 @@ def deleteHelper(self, url):
headers = {}
if self.apiKey is not None:
headers['Authorization'] = self.apiKey
else:
headers['Authorization'] = 'Bearer '+ self.bearerToken
elif self.bearerToken is not None:
headers['Authorization'] = 'Bearer ' + self.bearerToken
response = self.requestSession.delete(self.apiAddress + url, headers=headers)
if response.reason == "No Content":
return response
Expand Down Expand Up @@ -364,11 +362,12 @@ def freeze(self, manifest_path, manifest_output_dir="."):
required_files[i]['md5_checksum'] = md5_checksum
lock_md5_checksum = md5_for_str(str(manifest_file))
manifest_file['lock_checksum'] = lock_md5_checksum
with open(manifest_output_dir+'/'+'model_manifest.json.freeze', 'w') as f:
with open(manifest_output_dir + '/' + 'model_manifest.json.freeze', 'w') as f:
json.dump(manifest_file, f)
else:
print("Expected to find a model_manifest.json file, none was discovered in working directory")


def isJson(myjson):
try:
json_object = json.loads(myjson)
Expand Down
3 changes: 3 additions & 0 deletions Test/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ def _start_webserver():
async def process_algo_req(request: Request, username, algoname, output: Optional[str] = None):
metadata = {"request_id": "req-55c0480d-6af3-4a21-990a-5c51d29f5725", "duration": 0.000306774}
content_type = request.headers['Content-Type']
auth = request.headers.get('Authorization', None)
if auth is None:
return {"error": {"message": "authorization required"}}
request = await request.body()
if output and output == "void":
return {"async": "abcd123", "request_id": "req-55c0480d-6af3-4a21-990a-5c51d29f5725"}
Expand Down
26 changes: 21 additions & 5 deletions Test/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@

import unittest
import Algorithmia
from Algorithmia.errors import AlgorithmException
from uuid import uuid4

if sys.version_info.major >= 3:
unicode = str


class ClientDummyTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
Expand Down Expand Up @@ -71,7 +73,6 @@ def test_get_build_logs(self):

self.assertTrue(u'error' not in result)


def test_edit_org(self):
org_name = "a_myOrg84"

Expand Down Expand Up @@ -138,7 +139,7 @@ def test_algorithm_programmatic_create_process(self):
algorithm_name = "algo_e2d_test"
payload = "John"
expected_response = "hello John"
full_path = "a_Mrtest/" + algorithm_name
full_path = "a_Mrtest/" + algorithm_name
details = {
"summary": "Example Summary",
"label": "QA",
Expand Down Expand Up @@ -189,6 +190,23 @@ def test_algorithm_programmatic_create_process(self):
response = created_algo.info(git_hash)

self.assertEqual(response.version_info.semantic_version, "0.1.0", "information is incorrect")

def test_no_auth_client(self):

key = os.environ.get('ALGORITHMIA_API_KEY', "")
if key != "":
del os.environ['ALGORITHMIA_API_KEY']

client = Algorithmia.client(api_address="http://localhost:8080")
error = None
try:
client.algo("demo/hello").pipe("world")
except Exception as e:
error = e
finally:
os.environ['ALGORITHMIA_API_KEY'] = key
self.assertEqual(str(error), str(AlgorithmException(message="authorization required", stack_trace=None, error_type=None)))

else:
class ClientTest(unittest.TestCase):
seed(datetime.now().microsecond)
Expand All @@ -201,7 +219,7 @@ class ClientTest(unittest.TestCase):
def setUp(self):
self.admin_api_key = unicode(os.environ.get('ALGORITHMIA_A_KEY'))
self.regular_api_key = unicode(os.environ.get('ALGORITHMIA_API_KEY'))

self.admin_username = self.admin_username + str(int(random() * 10000))
self.admin_org_name = self.admin_org_name + str(int(random() * 10000))
self.admin_client = Algorithmia.client(api_address="https://test.algorithmia.com",
Expand Down Expand Up @@ -400,7 +418,5 @@ def test_algorithm_programmatic_create_process(self):
def test_algo_freeze(self):
self.regular_client.freeze("Test/resources/manifests/example_manifest.json", "Test/resources/manifests")



if __name__ == '__main__':
unittest.main()