def test_verify(self): """ option for send: verify """ client = Client(send_opt=dict(verify=False)) # testing this client with getPetById httpretty.register_uri(httpretty.GET, 'http://petstore.swagger.wordnik.com/api/pet/1', status=200, content_type='application/json', body=json.dumps(pet_Tom)) resp = client.request(app.op['getPetById'](petId=1)) self.assertEqual(resp.status, 200) self.assertTrue(isinstance(resp.data, Model)) self.assertEqual( resp.data, { u'name': 'Tom', u'tags': [{ u'id': 0, u'name': 'available' }, { u'id': 1, u'name': 'sold' }], u'id': 1 })
def __init__(self, creds=elicit_creds.ElicitCreds(), api_url=PRODUCTION_URL, send_opt=dict(verify=True)): print("Initialize Elicit client library for %s options:" % api_url) print(send_opt) if ((not send_opt['verify']) and api_url.startswith("https")): print('WARNING: not checking SSL') dont_check_ssl() self.api_url = api_url self.swagger_url = self.api_url + '/apidocs/v1/swagger.json' self.app = App._create_(self.swagger_url) self.auth = Security(self.app) self.creds = creds # init swagger client self.client = Client( self.auth, send_opt=send_opt ) # HACK to work around self-signed SSL certs used in development if (self.app.root.host != self.api_url): print( 'WARNING: API URL from swagger doesn\'t match this configuration: [%s] vs [%s]' % (self.api_url, self.app.root.host))
def post_progress_collection(self, info): ''' Update status of (pipeline, vid, mid, status) to SQLDB Status: start(must be first inserted), fail, succeed example: curl -X POST \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ -d '{ "extra_info": "string", "module_name": "string", "status": "start", "video_name": "string" }' 'http://aladdin1.inf.cs.cmu.edu:83/api/progresses/' ''' # app = App.create(url) app = self.logger client = Client() op1 = app.op['post_progress_collection'] req_resp = client.request( op1( payload={ "extra_info": info.get('extra_info'), "module_name": info.get('module_name'), "status": info.get('status'), # start, fail, succeed "video_name": info.get('video_name') })) return req_resp.status == 201 # 500 if failed
def get_progress_collection(self): ''' curl -X GET --header 'Accept: application/json' 'http://aladdin1.inf.cs.cmu.edu:83/api/progresses/' ''' # app = App.create(url) app = self.logger client = Client() resp = client.request(app.op['get_progress_collection']()) return resp
def client(): c = Client() def init_request(self): self.request = functools.partial(self.request, opt={'url_netloc': 'test:8000'}) c.init_request = functools.partial(init_request, c) c.init_request() return c
def __init__( self, api_key: str, swagger_file: str = "http://www.mingweisamuel.com/riotapi-schema/swaggerspec-2.0.yml" ): self.api_key = api_key self.swagger_file = swagger_file self.app = App.create(swagger_file) self.auth = Security(self.app) self.auth.update_with("api_key", api_key) self.client = Client(self.auth)
def request(self, operation, parameters): """Make a request against a certain operation on the API. :param operation: The operation to perform. :type operation: schema.Operation :param parameters: The parameters to use on the operation. :type parameters: dict :rtype: pyswagger.io.Response """ client = PyswaggerClient(Security(self._app)) result = client.request(operation._pyswagger_operation(**parameters)) # pylint: disable=protected-access return Response(result)
def __init__(self, settings): self.settings = settings # create a customized primitive factory for int because library # impractically chooses not to set default (b/t int32 vs int64) b/c # the Swagger/OpenAPI spec doesn't # https://github.com/mission-liao/pyswagger/issues/65 int_factory = SwaggerPrimitive() int_factory.register('integer', '', create_int, validate_int) int_factory.register('integer', None, create_int, validate_int) self.app = SwaggerApp.load(os.path.join( os.path.dirname(os.path.realpath(__file__)), 'luis_api-1.0.swagger.json'), prim=int_factory) self.app.prepare() self.client = Client()
def test_verify(self): """ option for send: verify """ client = Client(send_opt=dict(verify=False)) # testing this client with getPetById httpretty.register_uri(httpretty.GET, 'http://petstore.swagger.wordnik.com/api/pet/1', status=200, content_type='application/json', body=json.dumps(pet_Tom) ) resp = client.request(app.op['getPetById'](petId=1)) self.assertEqual(resp.status, 200) self.assertTrue(isinstance(resp.data, Model)) self.assertEqual(resp.data, {u'name': 'Tom', u'tags': [{u'id': 0, u'name': 'available'}, {u'id': 1, u'name': 'sold'}], u'id': 1} )
class ElicitApi: # PRODUCTION_URL = 'https://elicit.compute.dtu.dk' PRODUCTION_URL = 'http://localhost:3000' def __init__(self, creds=elicit_creds.ElicitCreds(), api_url=PRODUCTION_URL, send_opt=dict(verify=True)): print("Initialize Elicit client library for %s options:" % api_url) print(send_opt) if ((not send_opt['verify']) and api_url.startswith("https")): print('WARNING: not checking SSL') dont_check_ssl() self.api_url = api_url self.swagger_url = self.api_url + '/apidocs/v1/swagger.json' self.app = App._create_(self.swagger_url) self.auth = Security(self.app) self.creds = creds # init swagger client self.client = Client( self.auth, send_opt=send_opt ) # HACK to work around self-signed SSL certs used in development if (self.app.root.host != self.api_url): print( 'WARNING: API URL from swagger doesn\'t match this configuration: [%s] vs [%s]' % (self.api_url, self.app.root.host)) def login(self): """ Login to Elicit using credentials specified in init :return: client with auth header added. """ auth_request = dict(client_id=self.creds.public_client_id, client_secret=self.creds.public_client_secret, grant_type='password', email=self.creds.admin_user, password=self.creds.admin_password) resp = self.client.request( self.app.op['getAuthToken'](auth_request=auth_request)) assert resp.status == 200 self.auth = resp.data self.auth_header = 'Bearer ' + self.auth.access_token self.client._Client__s.headers['Authorization'] = self.auth_header return self.client def __getitem__(self, op): return lambda **args: self.app.op[op](**(self.bind_auth(args))) def bind_auth(self, args): args.update(authorization=self.auth_header) return args
def init(self): self.server = self["server"] self.port = self["port"] self.api = self["api"] openapi_spec = 'http://{}:{}/{}/swagger.json'.format( self.server, str(self.port), self.api) self.app = App._create_(openapi_spec) self.client = Client() StratusClient.init(self)
def connect(self, token: str) -> None: """ Establish connection for OpenSTF server :param token: stf access token :return: None """ url = self.swagger_uri self.logger.debug(f"Fetch API spec from: {url}") # load Swagger resource file into App object try: self._app = App._create_(url) # pylint: disable-line except (FileNotFoundError, urllib.error.URLError) as error: self.logger.error(error) raise auth = Security(self._app) auth.update_with('accessTokenAuth', f"Bearer {token}") # token # init swagger client self._client = Client(auth) self.logger.info('StfClient library initiated')
def __init__(self, url, *auths): app = App._create_(url) auth = Security(app) for t, cred in auths: auth.update_with(t, cred) client = Client(auth) self.app, self.client = app, client self.client._Client__s.hooks['response'] = logHttp
def test_verify(self): """ option for send: verify """ client = Client(send_opt=dict(verify=False)) # testing this client with getPetById httpretty.register_uri( httpretty.GET, "http://petstore.swagger.wordnik.com/api/pet/1", status=200, content_type="application/json", body=json.dumps(pet_Tom), ) resp = client.request(app.op["getPetById"](petId=1)) self.assertEqual(resp.status, 200) self.assertTrue(isinstance(resp.data, Model)) self.assertEqual( resp.data, {u"name": "Tom", u"tags": [{u"id": 0, u"name": "available"}, {u"id": 1, u"name": "sold"}], u"id": 1}, )
def get_swagger(self): """Gets an authenticated Swagger Client.""" swagger_url = self.get_url( 'swagger', replacement_fields={'base_url': self.base_url}) # load Swagger resource file into App object app = App._create_(swagger_url) auth = Security(app) # TODO: this isn't working... # ValueError: Unknown security name: [api_key] auth.update_with('api_key', self.api_token) # init swagger client client = Client(auth) return app, client
def __init__( self, schema_path, codec=None, username=None, password=None, token=None, security_name=None, extra_headers=None, ): if extra_headers is None: extra_headers = {} self.extra_headers = extra_headers self._schema_path = schema_path self._username = username self._password = password self._token = token self._auth_creds = None if username or password: security_name = security_name or "basic" self._auth_creds = (security_name, (username, password)) elif token: security_name = security_name or "apiKey" self._auth_creds = (security_name, token) if codec is None: codec = CodecFactory() self._prim_factory = (codec._pyswagger_factory) # pylint: disable=protected-access self._app = App.load(schema_path, prim=self._prim_factory) self._app.prepare() self._api = Api(self) security = Security(self._app) if self._auth_creds: security.update_with(*self._auth_creds) self.client = PyswaggerClient(security)
def get_method_list(): from pyswagger import SwaggerApp, SwaggerSecurity from pyswagger.contrib.client.requests import Client from pyswagger.utils import jp_compose app = SwaggerApp._create_(swagger_spec) client = Client() methods = list(app.op.keys()) apis = dict() for m in methods: full_method = m.split('!##!') if not full_method[0] in apis: apis[full_method[0]] = set() apis[full_method[0]].add(full_method[1]) return apis
from pyswagger import SwaggerApp, SwaggerSecurity from pyswagger.contrib.client.requests import Client from pyswagger.utils import jp_compose # load Swagger resource file into SwaggerApp object app = SwaggerApp._create_('http://petstore.swagger.io/v2/swagger.json') auth = SwaggerSecurity(app) auth.update_with('api_key', '12312312312312312313q') # api key auth.update_with('petstore_auth', '12334546556521123fsfss') # oauth2 # init swagger client client = Client(auth) # a dict is enough for representing a Model in Swagger pet_Tom=dict(id=1, name='Tom', photoUrls=['http://test']) # a request to create a new pet client.request(app.op['addPet'](body=pet_Tom)) # - access an Operation object via SwaggerApp.op when operationId is defined # - a request to get the pet back pet = client.request(app.op['getPetById'](petId=1)).data assert pet.id == 1 assert pet.name == 'Tom' # new ways to get Operation object corresponding to 'getPetById'. # 'jp_compose' stands for JSON-Pointer composition pet = client.request(app.resolve(jp_compose('/pet/{petId}', base='#/paths')).get(petId=1)).data assert pet.id == 1
def main(roomId): host = 'https://goldennumber.aiedu.msra.cn/' jsonpath = '/swagger/v1/swagger.json' app = App._create_(host + jsonpath) client = Client() if not roomId: # Input the roomid if there is no roomid in args roomId = input("Input room id: ") try: roomId = int(roomId) except: roomId = 0 print('Parse room id failed, default join in to room 0') userInfoFile = "userinfo.txt" userId = None nickName = None try: # Use an exist player with open(userInfoFile) as f: userId, nickName = f.read().split(',')[:2] print('Use an exist player: ' + nickName + ' Id: ' + userId) except: # Create a new player userResp = client.request(app.op['NewUser']( nickName='AI Player ' + str(random.randint(0, 9999)))) assert userResp.status == 200 user = userResp.data userId = user.userId nickName = user.nickName print('Create a new player: ' + nickName + ' Id: ' + userId) with open(userInfoFile, "w") as f: f.write("%s,%s" % (userId, nickName)) print('Room id: ' + str(roomId)) while True: stateResp = client.request(app.op['State'](uid=userId, roomid=roomId)) assert stateResp.status == 200 state = stateResp.data if state.state == 2: print('The game has finished') break if state.state == 1: print('The game has not started, query again after 1 second') time.sleep(1) continue if state.hasSubmitted: print('Already submitted this round, wait for next round') if state.maxUserCount == 0: time.sleep(state.leftTime + 1) else: # One round can be finished when all players submitted their numbers if the room have set the max count of users, need to check the state every second. time.sleep(1) continue print('\r\nThis is round ' + str(state.finishedRoundCount + 1)) todayGoldenListResp = client.request( app.op['TodayGoldenList'](roomid=roomId)) assert todayGoldenListResp.status == 200 todayGoldenList = todayGoldenListResp.data if len(todayGoldenList.goldenNumberList) != 0: print('Last golden number is: ' + str(todayGoldenList.goldenNumberList[-1])) number1, number2 = GeneratePredictionNumbers( todayGoldenList.goldenNumberList, state.numbers) if (state.numbers == 2): submitRsp = client.request(app.op['Submit'](uid=userId, rid=state.roundId, n1=str(number1), n2=str(number2))) if submitRsp.status == 200: print('You submit numbers: ' + str(number1) + ', ' + str(number2)) else: print('Error: ' + submitRsp.data.message) else: submitRsp = client.request(app.op['Submit'](uid=userId, rid=state.roundId, n1=str(number1))) if submitRsp.status == 200: print('You submit number: ' + str(number1)) else: print('Error: ' + submitRsp.data.message)
def client(): client = Client() return client
def _create_client(self): return Client()
from pyswagger import App, Security from pyswagger.contrib.client.requests import Client from pyswagger.utils import jp_compose # load Swagger resource file into App object app = App._create_('https://canvas.instructure.com/doc/api/courses.json') auth = Security(app) # auth.update_with('api_key', '9371~SNSl0krgbvfe8JYXS5NSKh7FJLcqO8yNmwZOb9ku79YGDmIXLNCjzjiOBGvfFya9') # api key # auth.update_with('petstore_auth', '12334546556521123fsfss') # oauth2 # init swagger client client = Client(auth)
class LuisTrainer(NluTrainer): # TODO: formalize/abstract return values def __init__(self, settings): self.settings = settings # create a customized primitive factory for int because library # impractically chooses not to set default (b/t int32 vs int64) b/c # the Swagger/OpenAPI spec doesn't # https://github.com/mission-liao/pyswagger/issues/65 int_factory = SwaggerPrimitive() int_factory.register('integer', '', create_int, validate_int) int_factory.register('integer', None, create_int, validate_int) self.app = SwaggerApp.load(os.path.join( os.path.dirname(os.path.realpath(__file__)), 'luis_api-1.0.swagger.json'), prim=int_factory) self.app.prepare() self.client = Client() def _request(self, op, body={}): time.sleep(asdur(self.settings.req_throttle)) req, res = self.app.op[op](**body) req.header['Ocp-Apim-Subscription-Key'] = self.settings.sub_key response = self.client.request((req, res)) ret = None if response.raw: ret = json.loads(response.raw) # pyswagger requires "requests" library... but roll their own request/ # response object. copying raise_for_status() functionality... http_error_msg = '' if 400 <= response.status < 500: http_error_msg = '%s Client Error: %s' % (response.status, ret['error']['message']) elif 500 <= response.status < 600: http_error_msg = '%s Server Error: %s' % (response.status, ret['error']['message']) if http_error_msg: raise HTTPError(http_error_msg, response=response) return ret def _sanitize(self, text): ''' Emulates behavior where LUIS lowercases the input and pads spaces for "special" chars. ''' CHARS = '"\',.-()' # based on observation and may not be exhaustive if not isinstance(text, (str, unicode)): text = unicode(text) text = text.lower().strip() # todo: improve this poor man's way of tokenizing t = text.split(' ') for idx, val in enumerate(t): for c in CHARS: if c in val: val = val.replace(c, ' %s ' % c) # pad c with spaces t[idx] = val.split() return ' '.join(morph.flatten(t)) def add_intent(self, app_id, intent): return self._request(INTENT_POST, dict(appId=app_id, intentModel={'Name': intent})) def add_entity(self, app_id, entity): if entity in BUILTIN_ENTITIES: # returning prebuilt entity id to normalize response return self._request( PB_ENTITY_POST, dict(appId=app_id, prebuiltExtractorNames=entity))[0]['id'] return self._request( ENTITY_POST, dict(appId=app_id, hierarchicalModel={'Name': entity})) def add_synonyms(self, app_id, synonyms): pass def train(self, app_id, text, intent, entities): labels = [] for t, e in entities.items(): index = util.phrase_index(text, e) if index: labels.append({ 'EntityType': t, 'StartToken': index[0], 'EndToken': index[1] }) return self._request( EXAMPLE_POST, dict(appId=app_id, exampleLabel={ 'ExampleText': text, 'SelectedIntentName': intent, 'EntityLabels': labels })) def predict(self, app_id, text): intent = None score = None entities = {} body = aadict.d2ar( self._request(PREDICT_GET, dict(appId=app_id, example=text))) for i in body.IntentsResults: # returns the intent with the highest score if i.score > score: score = i.score intent = i.Name for e in body.EntitiesResults: entities[e.name] = e.word return (body.utteranceText, intent, entities, score) def update(self, app_id): self._request(UPDATE_POST, dict(appId=app_id)) while True: time.sleep(asdur(self.settings.status_polling_interval)) status = [ i['Details']['Status'] for i in self._request(UPDATE_GET, dict(appId=app_id)) ] if 'In progress' not in set(status): break def get_update(self, app_id): return self._request(UPDATE_GET, dict(appId=app_id)) #---------------------------------------------------------------------------- # todo: should we expose the following in the api interface? def get_intents(self, app_id): return self._request(INTENTS_GET, dict(appId=app_id)) def delete_intent(self, app_id, intent_id): return self._request(INTENT_DELETE, dict(appId=app_id, intentId=intent_id)) def get_entities(self, app_id): return self._request(ENTITIES_GET, dict(appId=app_id)) \ + self._request(PB_ENTITIES_GET, dict(appId=app_id)) # untested/not currently used # def get_entity(self, app_id, entity_id): # self._request(ENTITY_GET, dict(appId=app_id, entityId=entity_id)) # self._request(PB_ENTITY_GET, dict(appId=app_id, prebuiltId=entity_id)) def delete_entity(self, app_id, entity_id): try: return self._request(ENTITY_DELETE, dict(appId=app_id, entityId=entity_id)) except HTTPError as e: if 'prebuilt' in e.message: return self._request(PB_ENTITY_DELETE, dict(appId=app_id, prebuiltId=entity_id)) raise e def get_examples(self, app_id): return self._request(EXAMPLES_GET, dict(appId=app_id, skip=0, count=10)) def delete_example(self, app_id, example_id): return self._request(EXAMPLE_DELETE, dict(appId=app_id, exampleId=example_id)) def get_synonyms(self): pass #---------------------------------------------------------------------------- # app provisioning def list_app(self): return self._request(APP_GET_ALL) def create_app(self, app_name, locale='en-us'): return self._request( APP_POST, dict(applicationInfo={ 'Name': app_name, 'Culture': locale })) def rename_app(self, app_id, new_app_name): return self._request( APP_PUT, dict(appId=app_id, applicationInfo={'Name': new_app_name})) def import_app(self, app_name, app_json): return self._request(APP_IMPORT, dict(appName=app_name, jSONApp=app_json)) def delete_app(self, app_id): return self._request(APP_DELETE, dict(appId=app_id)) def export_app(self, app_id): return self._request(APP_EXPORT, dict(appId=app_id)) def publish_app(self, app_id): # todo: support agentConfigurationDTO to enable subscription key assignment return self._request(APP_PUBLISH, dict(appId=app_id))
#!/usr/bin/env python3 from pyswagger import App, Security from pyswagger.contrib.client.requests import Client as SwagClient from shared.config import config import startup oauth_credentials = startup.run_flow() # Autheticates against the Bikebuds API using google-based oauth identity. # I can't figure out how to do this with firebase identity swag_app = App._create_(config.api_url + '/bikebudsv1openapi.json') swag_auth = Security(swag_app) swag_auth.update_with('api_key', config.python_client_testing_api_key) api_client = SwagClient(swag_auth) api_client._Client__s.headers[ 'Authorization'] = 'Bearer ' + oauth_credentials.id_token # This is a hack for my server, auth_util.verify_claims by default tries to # validate via firebase. api_client._Client__s.headers['UseAltAuth'] = '1' req, resp = swag_app.op['getProfile'](body=None) req.produce('application/json') api_client.request((req, resp)) print(resp.status) print(resp.data)
def generate_client(URL, KEY=None): app = App._create_(URL) auth = Security(app) auth.update_with('apiKeyHeader', KEY) # api key client = Client(auth) return app, client
class Client: """Client to use to access the Swagger application according to its schema. :param schema_path: The URL of or file path to the API definition. :type schema_path: str :param codec: Used to convert between JSON and objects. :type codec: codec.CodecFactory or None """ def __init__( self, schema_path, codec=None, username=None, password=None, token=None, security_name=None, extra_headers=None, ): if extra_headers is None: extra_headers = {} self.extra_headers = extra_headers self._schema_path = schema_path self._username = username self._password = password self._token = token self._auth_creds = None if username or password: security_name = security_name or "basic" self._auth_creds = (security_name, (username, password)) elif token: security_name = security_name or "apiKey" self._auth_creds = (security_name, token) if codec is None: codec = CodecFactory() self._prim_factory = (codec._pyswagger_factory) # pylint: disable=protected-access self._app = App.load(schema_path, prim=self._prim_factory) self._app.prepare() self._api = Api(self) security = Security(self._app) if self._auth_creds: security.update_with(*self._auth_creds) self.client = PyswaggerClient(security) def __repr__(self): return "{}(schema_path={!r})".format(self.__class__.__name__, self._schema_path) @property def api(self): """The API accessible from this client. :rtype: `schema.Api` """ return self._api def request(self, operation, parameters): """Make a request against a certain operation on the API. :param operation: The operation to perform. :type operation: schema.Operation :param parameters: The parameters to use on the operation. :type parameters: dict :rtype: pyswagger.io.Response """ result = self.client.request( req_and_resp=operation._pyswagger_operation(**parameters), headers=self.extra_headers, ) # pylint: disable=protected-access return Response(result) @property def _pyswagger_app(self): """The underlying pyswagger definition of the app - useful elsewhere internally but not expected to be referenced external to the package. :rtype: pyswagger.core.App """ return self._app
def connect_to_stf(self, host, token): self.app = App._create_('http://%s/api/v1/swagger.json' % host) auth = Security(self.app) auth.update_with('accessTokenAuth', 'Bearer ' + token) self.client = Client(auth)
from pyswagger import SwaggerApp from pyswagger.contrib.client.requests import Client from pyswagger.primitives import Model from ..utils import get_test_data_folder import unittest import httpretty import json import pytest import sys app = SwaggerApp._create_( get_test_data_folder(version='1.2', which='model_subtypes')) client = Client() u_mission = dict(id=1, username='******', password='******') uwi_mary = dict(id=2, username='******', password='******', email='*****@*****.**', phone='123') uwi_kevin = dict(id=3, username='******') @pytest.mark.skipif(sys.version_info[:2] >= (3, 3), reason='httpretty corrupt in python3') class ModelInteritanceTestCase(unittest.TestCase): """ test cases for model inheritance """ @httpretty.activate def test_inheritantce_full(self): """ init a Model with every property along the inheritance path.
'endsystem': self.endsystem, 'profit': self.profit(), 'jumps': getjumps((self.startsystem, self.endsystem), highseconly), 'profitperjump': self.profitperjump(highseconly), 'totalvol': self.totalvol(), } if __name__ == '__main__': import customlog logger = customlog.initlogger('mylogger', console=True, loglevel='debug') from pyswagger import App from pyswagger.contrib.client.requests import Client app = App.create('https://esi.tech.ccp.is/latest/swagger.json?datasource=tranquility') swaggerclient = Client() # initorderDB() # t1 = time.time() # orders = getorderdata(API='CREST') # logger.info('Pulled {} orders in {:.2f} seconds'.format(len(orders), time.time()-t1)) # writeorderstoDB(orders) t1 = time.time() orders = readordersfromDB() logger.info('Read orders from DB in {:.2f} sec'.format(time.time() - t1)) t1 = time.time() trades = findtrades(orders) logger.info('Found {} total trades in {:.2f} seconds'.format(len(trades), time.time()-t1))
class APIGatewayView(views.APIView): """ API gateway receives API requests, enforces throttling and security policies, passes requests to the back-end service and then passes the response back to the requester """ permission_classes = (permissions.IsAuthenticated, AllowLogicModuleGroup) schema = None _logic_modules = None _data = None def __init__(self, **kwargs): self._logic_modules = dict() self._data = dict() self.client = Client() super().__init__(**kwargs) def get(self, request, *args, **kwargs): return self.make_service_request(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.make_service_request(request, *args, **kwargs) def delete(self, request, *args, **kwargs): return self.make_service_request(request, *args, **kwargs) def put(self, request, *args, **kwargs): return self.make_service_request(request, *args, **kwargs) def patch(self, request, *args, **kwargs): return self.make_service_request(request, *args, **kwargs) def make_service_request(self, request, *args, **kwargs): """ Create a request for the defined service """ # validate incoming request before creating a service request try: self._validate_incoming_request(request, **kwargs) except exceptions.RequestValidationError as e: return HttpResponse(content=e.content, status=e.status, content_type=e.content_type) # load Swagger resource file and init swagger client try: app = self._load_swagger_resource(kwargs['service']) except exceptions.ServiceDoesNotExist as e: logger.error(e.content) return HttpResponse(content=e.content, status=e.status, content_type=e.content_type) # create and perform a service request response = self._perform_service_request( app=app, request=request, **kwargs ) # aggregate data if requested if request.query_params.get('aggregate', '_none').lower() == 'true': try: self._aggregate_response_data( request=request, response=response, **kwargs ) except exceptions.ServiceDoesNotExist as e: logger.error(e.content) # aggregate/join with the JoinRecord-models if request.query_params.get('join', None) is not None: try: self._join_response_data( request=request, response=response, **kwargs ) except exceptions.ServiceDoesNotExist as e: logger.error(e.content) if response.data is not None: content = json.dumps(response.data, cls=utils.GatewayJSONEncoder) else: content = response.raw content_type = ''.join(response.header.get('Content-Type', [])) return HttpResponse(content=content, status=response.status, content_type=content_type) def _get_logic_module(self, service_name: str) -> gtm.LogicModule: if service_name not in self._logic_modules: try: self._logic_modules[service_name] = gtm.LogicModule.objects.get(endpoint_name=service_name) except gtm.LogicModule.DoesNotExist: raise exceptions.ServiceDoesNotExist(f'Service "{service_name}" not found.') return self._logic_modules[service_name] def _join_response_data(self, request: Request, response: PySwaggerResponse, **kwargs) -> None: """ Same like: _aggregate_response_data, but this method uses the new Data Mesh models instead of the LogicModule.relationship - field. Aggregate data from first response. :param rest_framework.Request request: incoming request info :param PySwaggerResponse response: fist response :param kwargs: extra arguments ['service', 'model', 'pk'] :return PySwaggerResponse: response with expanded data """ service_name = kwargs['service'] resp_data = response.data if isinstance(resp_data, dict): if 'results' in resp_data: # In case of pagination take 'results' as a items data resp_data = resp_data.get('results', None) logic_module = self._get_logic_module(service_name) # find out forwards relations through logic module from request as origin endpoint = request.path[len(f'/{logic_module.endpoint_name}'):] endpoint = endpoint[:endpoint.index('/', 1) + 1] logic_module_model = LogicModuleModel.objects.prefetch_related('joins_origins')\ .get(logic_module_endpoint_name=logic_module.endpoint_name, endpoint=endpoint) relationships = logic_module_model.get_relationships() origin_lookup_field = logic_module_model.lookup_field_name if isinstance(resp_data, dict): # detailed view self._add_nested_data(request, resp_data, relationships, origin_lookup_field) elif isinstance(resp_data, list): # list view for data_item in resp_data: self._add_nested_data(request, data_item, relationships, origin_lookup_field) return def _add_nested_data(self, request: Request, data_item: dict, relationships: List[Tuple[Relationship, bool]], origin_lookup_field: str) -> None: """ Nests data retrieved from related services """ origin_pk = data_item.get(origin_lookup_field) if not origin_pk: raise exceptions.DataMeshError( f'DataMeshConfigurationError: lookup_field_name "{origin_lookup_field}" ' f'not found in response.') for relationship, is_forward_lookup in relationships: join_records = JoinRecord.objects.get_join_records(origin_pk, relationship, is_forward_lookup) # now backwards get related objects through join_records if join_records: related_objects = [] related_model, related_record_field = datamesh_utils.prepare_lookup_kwargs( is_forward_lookup, relationship, join_records[0]) app = self._load_swagger_resource(related_model.logic_module_endpoint_name) for join_record in join_records: # remove query_params from original request request._request.GET = QueryDict(mutable=True) request_kwargs = { 'pk': (str(getattr(join_record, related_record_field))), 'model': related_model.endpoint.strip('/'), 'method': request.META['REQUEST_METHOD'].lower() } # create and perform a service request response = self._perform_service_request( app=app, request=request, **request_kwargs ) if response.data: related_objects.append(dict(response.data)) else: logger.error(f'No response data for join record (request params: {request_kwargs})') # aggregate data_item[relationship.key] = related_objects def _aggregate_response_data(self, request: Request, response: PySwaggerResponse, **kwargs): """ Aggregate data from first response :param rest_framework.Request request: incoming request info :param PySwaggerResponse response: fist response :param kwargs: extra arguments ['service', 'model', 'pk'] :return PySwaggerResponse: response with expanded data """ service_name = kwargs['service'] resp_data = response.data if isinstance(resp_data, dict): if 'results' in resp_data: # DRF API payload structure resp_data = resp_data.get('results', None) logic_module = self._get_logic_module(service_name) # TODO: Implement depth validation # TODO: Implement authorization when retrieve Buildly data if isinstance(resp_data, list): for data in resp_data: extension_map = self._generate_extension_map( logic_module=logic_module, model_name=kwargs['model'], data=data ) r = self._expand_data(request, extension_map) data.update(**r) elif isinstance(resp_data, dict): extension_map = self._generate_extension_map( logic_module=logic_module, model_name=kwargs['model'], data=resp_data ) r = self._expand_data(request, extension_map) resp_data.update(**r) def _get_buildly_uuid_name(self, model): # TODO: Remove this once all buildly.models have only one `uuid`-field for field in model._meta.fields: if field.name.endswith('uuid') and field.unique and \ field.default == uuid.uuid4: return field.name def _expand_data(self, request: Request, extend_models: list): """ Use extension maps to fetch data from different services and replace the relationship key by real data. :param Request request: incoming request :param list extend_models: list of dicts with relationships info :return dict: relations with their data """ result = dict() for extend_model in extend_models: data = None if extend_model['service'] == 'buildly': if hasattr(wfm, extend_model['model']): cls = getattr(wfm, extend_model['model']) uuid_name = self._get_buildly_uuid_name(cls) lookup = { uuid_name: extend_model['pk'] } try: obj = cls.objects.get(**lookup) except cls.DoesNotExist as e: logger.info(e) except ValueError: logger.info(f' Not found: {extend_model["model"]} with' f' uuid_name={extend_model["pk"]}') else: utils.validate_object_access(request, obj) data = model_to_dict(obj) else: app = self._load_swagger_resource( extend_model['service'] ) # remove query_params from original request request._request.GET = QueryDict(mutable=True) # create and perform a service request res = self._perform_service_request( app=app, request=request, **extend_model ) data = res.data if data is not None: result[extend_model['relationship_key']] = data return result def _generate_extension_map(self, logic_module: gtm.LogicModule, model_name: str, data: dict): """ Generate a list of relationship map of a specific service model. :param LogicModule logic_module: a logic module instance :param str model_name: Model name that should expand the relationships :param dict data: response data from first request :return list: list of dicts with relationships info """ extension_map = [] if not logic_module.relationships: logger.warning(f'Tried to aggregate but no relationship defined ' f'in {logic_module}.') return extension_map for k, v in logic_module.relationships[model_name].items(): value = v.split('.') collection_args = { 'service': value[0], 'model': value[1], 'pk': str(data[k]), 'relationship_key': k } extension_map.append(collection_args) return extension_map def _load_swagger_resource(self, endpoint_name: str): """ Get Swagger spec of specified service and create an app instance to be able to validate requests/responses and perform request. :param endpoint_name: name of the service endpoint that data will be retrieved :return PySwagger.App: an app instance """ # load Swagger resource file logic_module = self._get_logic_module(endpoint_name) schema_url = utils.get_swagger_url_by_logic_module(logic_module) if schema_url not in self._data: # load swagger json as a raw App and prepare it try: app = App.load(schema_url) except URLError: raise URLError( f'Make sure that {schema_url} is accessible.') if app.raw.basePath == '/': getattr(app, 'raw').update_field('basePath', '') app.prepare() self._data[schema_url] = app return self._data[schema_url] def _validate_incoming_request(self, request, **kwargs): """ Do certain validations to the request before starting to create a new request to services :param rest_framework.Request request: request info :param kwargs: info about request like obj's PK, service and model """ if (request.META['REQUEST_METHOD'] in ['PUT', 'PATCH', 'DELETE'] and kwargs['pk'] is None): raise exceptions.RequestValidationError( 'The object ID is missing.', 400) def _get_swagger_data(self, request): """ Create the data structure to be used in PySwagger. GET and DELETE requests don't required body, so the data structure will have just query parameter if passed. :param rest_framework.Request request: request info :return dict: request body structured for PySwagger """ method = request.META['REQUEST_METHOD'].lower() data = request.query_params.dict() # remove specific gateway query params if data.get('aggregate', None): data.pop('aggregate') if data.get('join', None) is not None: data.pop('join') if method in ['post', 'put', 'patch']: qd_body = request.data if hasattr(request, 'data') else dict() body = (qd_body.dict() if isinstance(qd_body, QueryDict) else qd_body) data.update(body) if request.content_type == 'application/json' and data: data = { 'data': data } # handle uploaded files if request.FILES: for key, value in request.FILES.items(): data[key] = { 'header': { 'Content-Type': value.content_type, }, 'data': value, 'filename': value.name, } return data def _get_req_and_rep(self, app, request, **kwargs): """ It resolves the path that should be used by the gateway in the request based on model, service and foreign key and return a request and response object :param app: App object from pyswagger :param rest_framework.Request request: request info :param kwargs: info about request like obj's PK, service and model :return: a tuple with pyswagger Request and Response obj """ pk = kwargs.get('pk') model = kwargs.get('model', '').lower() method = request.META['REQUEST_METHOD'].lower() data = self._get_swagger_data(request) if pk is None: # resolve the path path = '/%s/' % model path_item = app.s(path) else: if utils.valid_uuid4(pk): pk_name = 'uuid' else: pk_name = 'id' # evaluates to '/siteprofiles/uuid/' or '/siteprofiles/id/' path = '/{0}/{{{1}}}/'.format(model, pk_name) data.update({pk_name: pk}) try: path_item = app.s(path) except KeyError: raise exceptions.EndpointNotFound(f'Endpoint not found: {method.upper()} {path}') # call operation if not (hasattr(path_item, method) and callable(getattr(path_item, method))): raise exceptions.EndpointNotFound(f'Endpoint not found: {method.upper()} {path}') return getattr(path_item, method).__call__(**data) def _get_service_request_headers(self, request): """ Get all the headers that are necessary to redirect the request to the needed service :param rest_framework.Request request: request info :return: a dictionary with all the needed headers """ # get the authorization header from current request authorization = get_authorization_header(request).decode('utf-8') # Add only Authorization header, PySwagger will handle the rest of it headers = { 'Authorization': authorization, } return headers def _perform_service_request(self, app: App, request: Request, **kwargs): """ Perform request to the service using the PySwagger client. :param pyswagger.App app: an instance of App :param rest_framework.Request request: incoming request info :return pyswagger.Response: response from the service """ req, resp = self._get_req_and_rep(app, request, **kwargs) req.prepare(handle_files=False) # prepare request to get URL from it for checking cache key_url = req.url if request.META['REQUEST_METHOD'].lower() == 'get' and key_url in self._data: # Caching is only for GET requests return self._data[key_url] else: headers = self._get_service_request_headers(request) try: data = self.client.request((req, resp), headers=headers) except Exception as e: error_msg = (f'An error occurred when redirecting the request to ' f'or receiving the response from the service.\n' f'Origin: ({e.__class__.__name__}: {e})') raise exceptions.PySwaggerError(error_msg) if request.META['REQUEST_METHOD'].lower() == 'get': # Cache only GET requests self._data[key_url] = data return data
from pyswagger import App from pyswagger.contrib.client.requests import Client # load Swagger resource file into App object app = App.create( 'https://esi.tech.ccp.is/latest/swagger.json?datasource=tranquility') swaggerclient = Client() response = swaggerclient.request(app.op['post_universe_names'](ids={ ids: [35, 165] })) # auth = Security(app) # auth.update_with('api_key', '12312312312312312313q') # api key # auth.update_with('petstore_auth', '12334546556521123fsfss') # oauth2 # # init swagger client # client = Client(auth) # # a dict is enough for representing a Model in Swagger # pet_Tom=dict(id=1, name='Tom', photoUrls=['http://test']) # # a request to create a new pet # client.request(app.op['addPet'](body=pet_Tom)) # # - access an Operation object via App.op when operationId is defined # # - a request to get the pet back # pet = client.request(app.op['getPetById'](petId=1)).data # assert pet.id == 1 # assert pet.name == 'Tom' # # new ways to get Operation object corresponding to 'getPetById'.
def main(): gp = goldPoint() # 初始化 swagger 客户端 host = 'https://goldennumber.aiedu.msra.cn/' jsonpath = '/swagger/v1/swagger.json' app = App._create_(host + jsonpath) client = Client() parser = argparse.ArgumentParser() parser.add_argument('--room', type=int, help='Room ID', required=False) args = parser.parse_args() roomId = args.room if roomId is None: # 如果参数中没有给出room ID,则要求输入room ID roomId = input("Input room id: ") try: roomId = int(roomId) except: roomId = 0 print('Parse room id failed, default join in to room 0') userInfoFile = "userinfo.txt" userId = "019" nickName = None try: # 使用已存在的玩家 with open(userInfoFile) as f: nickName, userId, key = f.read().split(',')[:3] print('Use an exist player: ' + nickName + ' Id: ' + userId) except: # 创建一个新的玩家 userResp = client.request(app.op['NewUser'](nickName='019')) assert userResp.status == 200 user = userResp.data userId = user.userId nickName = user.nickName print('Create a new player: ' + nickName + ' Id: ' + userId) with open(userInfoFile, "w") as f: f.write("%s,%s" % (userId, nickName)) print('Room id: ' + str(roomId)) while True: stateResp = client.request(app.op['State'](uid=userId, roomid=roomId)) if stateResp.status != 200: print('Network issue, query again after 1 second') time.sleep(1) continue state = stateResp.data if state.state == 2: print('The game has finished') break if state.state == 1: print('The game has not started, query again after 1 second') time.sleep(1) continue if state.hasSubmitted: print('Already submitted this round, wait for next round') if state.maxUserCount == 0: time.sleep(state.leftTime + 1) else: # 每秒检测一次:当设置了最大用户数量后,当所有用户都已提交信息后,一个回合就应该结束 time.sleep(1) continue print('\r\nThis is round ' + str(state.finishedRoundCount + 1)) todayGoldenListResp = client.request( app.op['TodayGoldenList'](roomid=roomId)) if todayGoldenListResp.status != 200: print('Network issue, query again after 1 second') time.sleep(1) continue todayGoldenList = todayGoldenListResp.data if len(todayGoldenList.goldenNumberList) != 0: print('Last golden number is: ' + str(todayGoldenList.goldenNumberList[-1])) lastRoundResp = client.request(app.op['History'](roomid=roomId, count=1)) if lastRoundResp.status != 200: print('Network issue, query again after 1 second') time.sleep(1) continue lastScore = 0 if len(lastRoundResp.data.rounds) > 0: scoreArray = [ user for user in lastRoundResp.data.rounds[0].userNumbers if user.userId == userId ] if len(scoreArray) == 1: lastScore = scoreArray[0].score print('Last round score: {}'.format(lastScore)) number1, number2 = gp.predict(todayGoldenList.goldenNumberList) # number1, number2 = random.random(), random.random() print(number1, number2) if (state.numbers == 2): submitRsp = client.request(app.op['Submit']( uid=userId, rid=state.roundId, n1=str(number1), n2=str(number2), token=base64.b64encode( hashlib.sha256( (userId + state.roundId + key).encode(encoding='utf-8')).hexdigest().encode( encoding='utf-8')))) if submitRsp.status == 200: print('You submit numbers: ' + str(number1) + ', ' + str(number2)) else: print('Error: ' + submitRsp.data.message) time.sleep(1) else: submitRsp = client.request(app.op['Submit']( uid=userId, rid=state.roundId, n1=str(number1), token=base64.b64encode( hashlib.sha256( (userId + state.roundId + key).encode(encoding='utf-8')).hexdigest().encode( encoding='utf-8')))) if submitRsp.status == 200: print('You submit number: ' + str(number1)) else: print('Error: ' + submitRsp.data.message) time.sleep(1)
def __init__(self, **kwargs): self._logic_modules = dict() self._data = dict() self.client = Client() super().__init__(**kwargs)