def setUp(self): options = { 'DOMAIN': 'https://example.com', 'API_PREFIX': 'api/v1', 'TOKEN_TYPE': 'jwt', 'TOKEN_FORMAT': 'JWT {token}', 'LOGIN': '******', 'LOGOUT': 'auth/logout/', } self.api = Api(options=options)
def main(self): """ Main function to call to initiate execution. 1. Get domain name and use to instantiate Api object 2. Call before_login to allow for work before logging in 3. Logging into the server 4. Call after_loging to do actual work with server data """ self.domain = self.get_domain() self.api = RestApi(self.get_options()) self.before_login() ok = self.login() if ok: self.after_login()
class ApiTestCase(unittest.TestCase): api = None def setUp(self): options = { 'DOMAIN': 'https://example.com', 'API_PREFIX': 'api/v1', 'TOKEN_TYPE': 'jwt', 'TOKEN_FORMAT': 'JWT {token}', 'LOGIN': '******', 'LOGOUT': 'auth/logout/', } self.api = Api(options=options) def tearDown(self): self.api = None def test_init(self): self.assertEqual(self.api.base_url, 'https://example.com/api/v1') self.assertTrue(self.api.use_token) self.assertEqual(self.api.token_type, 'jwt') def test_set_token(self): self.assertEqual(self.api.token, None) self.api.set_token('big-token') self.assertEqual(self.api.token, 'big-token') @requests_mock.Mocker() def test_login(self, m): payload = {'jwt': 'big-token', 'username': '******'} m.post('https://example.com/api/v1/auth/login/', text=json.dumps(payload)) ok = self.api.login(email='*****@*****.**', password='******') self.assertTrue(ok) self.assertEqual(self.api.username, 'user1') self.assertEqual(self.api.token, 'big-token') @requests_mock.Mocker() def test_logout(self, m): payload = {'jwt': 'big-token', 'username': '******'} m.post('https://example.com/api/v1/auth/login/', text=json.dumps(payload)) m.post('https://example.com/api/v1/auth/logout/', status_code=204) ok = self.api.login(email='*****@*****.**', password='******') self.assertTrue(ok) self.api.logout() self.assertEqual(self.api.username, None) self.assertEqual(self.api.token, None) @requests_mock.Mocker() def test_get_list(self, m): payload = {"result": ["a", "b", "c"]} m.get('https://example.com/api/v1/test/', text=json.dumps(payload)) resp = self.api.test.get() self.assertEqual(resp['result'], ['a', 'b', 'c']) @requests_mock.Mocker() def test_get_detail(self, m): payload = {"a": "b", "c": "d"} m.get('https://example.com/api/v1/test/my-detail/', text=json.dumps(payload)) resp = self.api.test('my-detail').get() self.assertEqual(resp, {'a': 'b', 'c': 'd'}) @requests_mock.Mocker() def test_get_detail_with_action(self, m): payload = {"a": "b", "c": "d"} m.get('https://example.com/api/v1/test/my-detail/action/', text=json.dumps(payload)) resp = self.api.test('my-detail').action.url() self.assertEqual(resp, 'https://example.com/api/v1/test/my-detail/action/') resp = self.api.test('my-detail').action.get() self.assertEqual(resp, {'a': 'b', 'c': 'd'}) @requests_mock.Mocker() def test_get_detail_with_extra_args(self, m): payload = {"a": "b", "c": "d"} m.get('https://example.com/api/v1/test/my-detail/', text=json.dumps(payload)) resp = self.api.test('my-detail').get(foo='bar') self.assertEqual(resp, {'a': 'b', 'c': 'd'}) @requests_mock.Mocker() def test_post(self, m): payload = {"foo": ["a", "b", "c"]} result = {"id": 1} m.post('https://example.com/api/v1/test/', text=json.dumps(result)) resp = self.api.test.post(payload) self.assertEqual(resp['id'], 1) @requests_mock.Mocker() def test_patch(self, m): payload = {"foo": ["a", "b", "c"]} result = {"id": 1} m.patch('https://example.com/api/v1/test/my-detail/', text=json.dumps(result)) resp = self.api.test('my-detail').patch(payload) self.assertEqual(resp['id'], 1) @requests_mock.Mocker() def test_put(self, m): payload = {"foo": ["a", "b", "c"]} result = {"id": 1} m.put('https://example.com/api/v1/test/my-detail/', text=json.dumps(result)) resp = self.api.test('my-detail').put(payload) self.assertEqual(resp['id'], 1) @requests_mock.Mocker() def test_delete(self, m): result = {"id": 1} m.delete('https://example.com/api/v1/test/my-detail/', text=json.dumps(result)) deleted = self.api.test('my-detail').delete() self.assertTrue(deleted) @requests_mock.Mocker() def test_post_with_error(self, m): payload = {"foo": ["a", "b", "c"]} result = {"id": 1} m.post('https://example.com/api/v1/test/', status_code=400, text=json.dumps(result)) with self.assertRaises(HttpClientError): self.api.test.post(payload) m.post('https://example.com/api/v1/test/', status_code=404, text=json.dumps(result)) with self.assertRaises(HttpClientError): self.api.test.post(payload) m.post('https://example.com/api/v1/test/', status_code=500, text=json.dumps(result)) with self.assertRaises(HttpServerError): self.api.test.post(payload)
logger = logging.getLogger(__name__) username = input('Email? ') password = getpass.getpass() options = { 'DOMAIN': 'http://127.0.0.1:8000', 'API_PREFIX': 'api/v1', 'TOKEN_TYPE': 'jwt', 'TOKEN_FORMAT': 'JWT {token}', 'USERNAME_KEY': 'username', 'LOGIN': '******', 'LOGOUT': 'auth/logout/', } c = RestApi(options) ok = c.login(username=username, password=password) if ok: # GET some data my_objects = c.org.get() for obj in my_objects['results']: pprint(obj) logger.info('------------------------------') logger.info('------------------------------') logger.info('------------------------------') # If the URL includes "-", add under parenthesis: # GET: /api/v1/someresource/some-path/ my_object = c.someresource('some-path').get()
class BaseMain(object): parser = None args = None api = None options = { 'DOMAIN': None, 'API_PREFIX': 'api/v1', 'TOKEN_TYPE': 'jwt', 'TOKEN_FORMAT': 'JWT {token}', 'USERNAME_KEY': 'username', 'LOGIN': '******', 'LOGOUT': 'auth/logout/', } logging_level = logging.INFO def __init__(self): """ Initialize Logging configuration Initialize argument parsing Process any extra arguments Only hard codes one required argument: --user Additional arguments can be configured by overwriting the add_extra_args() method Logging configuration can be changed by overwritting the config_logging() method """ self.parser = argparse.ArgumentParser(description=__doc__) self.parser.add_argument('-u', '--user', dest='username', type=str, required=True, help='Username used for login') self.parser.add_argument('--server', dest='server', type=str, required=True, help='Server Domain Name to use') self.add_extra_args() self.args = self.parser.parse_args() self.config_logging() def _critical_exit(self, msg): LOG.error(msg) sys.exit(1) def main(self): """ Main function to call to initiate execution. 1. Get domain name and use to instantiate Api object 2. Call before_login to allow for work before logging in 3. Logging into the server 4. Call after_loging to do actual work with server data """ self.domain = self.get_domain() self.api = RestApi(self.get_options()) self.before_login() ok = self.login() if ok: self.after_login() # Following functions can be overwritten if needed # ================================================ def get_options(self): options = self.options options['DOMAIN'] = self.domain return options def config_logging(self): """ Overwrite to change the way the logging package is configured :return: Nothing """ logging.basicConfig( level=self.logging_level, format='[%(asctime)-15s] %(levelname)-6s %(message)s', datefmt='%d/%b/%Y %H:%M:%S') def add_extra_args(self): """ Overwrite to change the way extra arguments are added to the args parser :return: Nothing """ pass def get_domain(self) -> str: """ Figure out server domain URL based on --server and --customer args """ if 'https://' not in self.args.server: return f'https://{self.args.server}' return self.args.server def login(self) -> bool: """ Get password from user and login """ password = getpass.getpass() ok = self.api.login(username=self.args.username, password=password) if ok: LOG.info('Welcome {0}'.format(self.args.username)) return ok def before_login(self): """ Overwrite to do work after parsing, but before logging in to the server This is a good place to do additional custom argument checks :return: Nothing """ pass def after_login(self): """ This function MUST be overwritten to do actual work after logging into the Server :return: Nothing """ LOG.warning('No actual work done')