def cli(ctx, apiroot, config, organization): """A command line tool for working with Transcriptic.""" if ctx.invoked_subcommand in [ 'login', 'compile', 'preview', 'summarize', 'init' ]: # For login/local commands, initialize empty connection ctx.obj = ContextObject() ctx.obj.api = Connection(use_environ=False) else: try: ctx.obj = ContextObject() ctx.obj.api = Connection.from_file(config) if organization is not None: ctx.obj.api.organization_id = organization if apiroot is not None: ctx.obj.api.api_root = apiroot except: click.echo( "Welcome to TxPy! It seems like your `.transcriptic` config file is missing or out of date" ) analytics = click.confirm( "Send TxPy CLI usage information to improve the CLI user " "experience?", default=True) ctx.obj.api = Connection( use_environ=False) # Initialize empty connection ctx.invoke(login, analytics=analytics) if ctx.obj.api.analytics: try: ctx.obj.api._post_analytics(event_action=ctx.invoked_subcommand, event_category="cli") except: pass
def format_commands(self, ctx, formatter): """Custom formatter to control whether a command is displayed Note: This is only called when formatting the help message. """ ctx.obj = ContextObject() try: ctx.obj.api = Connection.from_file('~/.transcriptic') except (FileNotFoundError, OSError): # This defaults to feature_groups = [] ctx.obj.api = Connection() rows = [] for subcommand in self.list_commands(ctx): cmd = self.get_command(ctx, subcommand) if cmd is None: continue try: if cmd.feature is not None and \ cmd.feature in ctx.obj.api.feature_groups: help = cmd.short_help or '' rows.append((subcommand, help)) else: continue except AttributeError: help = cmd.short_help or '' rows.append((subcommand, help)) if rows: with formatter.section('Commands'): formatter.write_dl(rows)
def test_api(monkeypatch): from transcriptic.config import Connection from .helpers.mockAPI import _req_call as mockCall api = Connection(email="*****@*****.**", organization_id="mock", api_root="mock-api") monkeypatch.setattr(api, '_req_call', mockCall) return api
def login(ctx, api_root): '''Authenticate to your Transcriptic account.''' email = click.prompt('Email') password = click.prompt('Password', hide_input=True) r = requests.post("%s/users/sign_in" % api_root, data=json.dumps({ 'user': { 'email': email, 'password': password, }, }), headers={ 'Accept': 'application/json', 'Content-Type': 'application/json', }) if r.status_code != 200: click.echo("Error logging into Transcriptic: %s" % r.json()['error']) sys.exit(1) user = r.json() token = (user.get('authentication_token') or user['test_mode_authentication_token']) if len(user['organizations']) < 1: click.echo( "Error: You don't appear to belong to any organizations. \nVisit %s " "and create an organization." % api_root) sys.exit(1) if len(user['organizations']) == 1: organization = user['organizations'][0]['subdomain'] else: click.echo("You belong to %s organizations:" % len(user['organizations'])) for o in user['organizations']: click.echo(" %s (%s)" % (o['name'], o['subdomain'])) organization = click.prompt( 'Which would you like to login as', default=user['organizations'][0]['subdomain'], prompt_suffix='? ') r = requests.get('%s/%s' % (api_root, organization), headers={ 'X-User-Email': email, 'X-User-Token': token, 'Accept': 'application/json', }) if r.status_code != 200: click.echo("Error accessing organization: %s" % r.text) sys.exit(1) ctx.obj = Connection(email, token, organization, api_root=api_root) ctx.obj.save(ctx.parent.params['config']) click.echo('Logged in as %s (%s)' % (user['email'], organization))
def cli(ctx, api_root, email, token, organization, config): """A command line tool for working with Transcriptic. Note: This is the main entry point of the CLI. If specifying credentials, note that the order of preference is: --flag, environment then config file. Example: `transcriptic --organization "my_org" projects` >> `export USER_ORGANIZATION="my_org"` >> `"organization_id": "my_org" in ~/.transcriptic """ # Initialize ContextObject to be used for storing api object ctx.obj = ContextObject() if ctx.invoked_subcommand in ['compile', 'preview', 'summarize', 'init']: # For local commands, initialize empty connection ctx.obj.api = Connection() elif ctx.invoked_subcommand == 'login': # Load analytics option from existing dotfile if present, else prompt try: api = Connection.from_file(config) api.api_root = ( api_root or os.environ.get('BASE_URL', None) or api.api_root ) ctx.obj.api = api except (OSError, IOError): ctx.obj.api = Connection() # Echo a warning if other options are defined for login if organization or email or token: click.echo("Only the `--api-root` option is applicable for the " "`login` command. All other options are ignored.") else: try: api = Connection.from_file(config) api.api_root = ( api_root or os.environ.get('BASE_URL', None) or api.api_root ) api.organization_id = ( organization or os.environ.get('USER_ORGANIZATION', None) or api.organization_id ) api.email = ( email or os.environ.get('USER_EMAIL', None) or api.email ) api.token = ( token or os.environ.get('USER_TOKEN', None) or api.token ) ctx.obj.api = api except (OSError, IOError): click.echo("Welcome to TxPy! It seems like your `.transcriptic` " "config file is missing or out of date") analytics = click.confirm("Send TxPy CLI usage information to " "improve the CLI user " "experience?", default=True) ctx.obj.api = Connection() # Initialize empty connection ctx.invoke(login_cmd, api_root=api_root, analytics=analytics) if ctx.obj.api.analytics: try: ctx.obj.api._post_analytics(event_action=ctx.invoked_subcommand, event_category="cli") except requests.exceptions.RequestException: pass
def login(api, config, api_root=None, analytics=True): """Authenticate to your Transcriptic account.""" if api_root is None: # Always default to the pre-defined api-root if possible, else use # the secure.transcriptic.com domain try: api_root = api.api_root except ValueError: api_root = "https://secure.transcriptic.com" email = click.prompt('Email') password = click.prompt('Password', hide_input=True) try: r = api.post( routes.login(api_root=api_root), data=json.dumps({ 'user': { 'email': email, 'password': password, }, }), headers={ 'Accept': 'application/json', 'Content-Type': 'application/json', }, status_response={ '200': lambda resp: resp, '401': lambda resp: resp, 'default': lambda resp: resp } ) except requests.exceptions.RequestException: click.echo("Error logging into specified host: {}. Please check your " "internet connection and host name".format(api_root)) sys.exit(1) if r.status_code != 200: click.echo("Error logging into Transcriptic: %s" % r.json()['error']) sys.exit(1) user = r.json() token = (user.get('authentication_token') or user['test_mode_authentication_token']) user_id = user.get("id") feature_groups = user.get('feature_groups') organization = org_prompt(user['organizations']) r = api.get( routes.get_organization(api_root=api_root, org_id=organization), headers={ 'X-User-Email': email, 'X-User-Token': token, 'Accept': 'application/json'}, status_response={ '200': lambda resp: resp, 'default': lambda resp: resp} ) if r.status_code != 200: click.echo("Error accessing organization: %s" % r.text) sys.exit(1) api = Connection(email=email, token=token, organization_id=organization, api_root=api_root, user_id=user_id, analytics=analytics, feature_groups=feature_groups) api.save(config) click.echo('Logged in as %s (%s)' % (user['email'], organization))
def login(ctx, api_root, analytics=True): """Authenticate to your Transcriptic account.""" email = click.prompt('Email') password = click.prompt('Password', hide_input=True) r = ctx.obj.api.post(routes.login(api_root=api_root), data=json.dumps({ 'user': { 'email': email, 'password': password, }, }), headers={ 'Accept': 'application/json', 'Content-Type': 'application/json', }, status_response={ '200': lambda resp: resp, 'default': lambda resp: resp }, custom_request=False) if r.status_code != 200: click.echo("Error logging into Transcriptic: %s" % r.json()['error']) sys.exit(1) user = r.json() token = (user.get('authentication_token') or user['test_mode_authentication_token']) user_id = user.get("id") if len(user['organizations']) < 1: click.echo("Error: You don't appear to belong to any organizations. \n" "Visit %s and create an organization." % api_root) sys.exit(1) if len(user['organizations']) == 1: organization = user['organizations'][0]['subdomain'] else: click.echo("You belong to %s organizations:" % len(user['organizations'])) for indx, o in enumerate(user['organizations']): click.echo("%s. %s (%s)" % (indx + 1, o['name'], o['subdomain'])) def parse_valid_org(indx): from click.exceptions import BadParameter try: return user['organizations'][int(indx) - 1]['subdomain'] except: raise BadParameter("Please enter an integer between 1 and %s" % (len(user['organizations'])), ctx=ctx) organization = click.prompt( 'Which organization would you like to log in as', default=1, prompt_suffix='? ', type=int, value_proc=lambda x: parse_valid_org(x)) r = ctx.obj.api.get(routes.get_organization(api_root=api_root, org_id=organization), headers={ 'X-User-Email': email, 'X-User-Token': token, 'Accept': 'application/json', }, status_response={ '200': lambda resp: resp, 'default': lambda resp: resp }, custom_request=True) if r.status_code != 200: click.echo("Error accessing organization: %s" % r.text) sys.exit(1) ctx.obj.api = Connection(email=email, token=token, organization_id=organization, api_root=api_root, user_id=user_id, analytics=analytics) ctx.obj.api.save(ctx.parent.params['config']) click.echo('Logged in as %s (%s)' % (user['email'], organization))