def test_read_file_displays_errors(self, mock_open_file, mock_print_warning): mock_open_file.side_effect = IOError() fileutils.read_file(self.fake_path, continue_on_error=True, display_errors=True) self.assertTrue(mock_print_warning.called)
def test_read_file_exits_code_2_on_unicodedecodeerror(self, mock_open_file): fake_decode_error = UnicodeDecodeError('fake-encoding', b'fakebytes', 0, 1, 'testing only') mock_open_file.return_value.__enter__( ).read.side_effect = fake_decode_error with self.assertRaises(SystemExit) as context: fileutils.read_file(self.fake_path) self.assertEqual(context.exception.code, 2)
def from_credentials_file(cls, filename): """Generates Credentials from a stored Credentials file. The same file will be used to save the credentials when the access token is refreshed. Args: filename: String, the name of a file containing JSON credentials to load. The same filename will be used to save credentials back to disk. Returns: The credentials loaded from disk. Raises: InvalidCredentialsFileError: When the credentials file cannot be opened. EmptyCredentialsFileError: When the provided file contains no credentials. """ file_content = fileutils.read_file(filename, continue_on_error=True, display_errors=False) if file_content is None: raise InvalidCredentialsFileError( f'File {filename} could not be opened') info = json.loads(file_content) if not info: raise EmptyCredentialsFileError( f'File {filename} contains no credential data') try: # We read the existing data from the passed in file, but we also want to # save future data/tokens in the same place. return cls.from_authorized_user_info(info, filename=filename) except ValueError as e: raise InvalidCredentialsFileError(str(e))
def test_read_file_default_params(self, mock_open_file): fake_content = 'some fake content' mock_open_file.return_value.__enter__().read.return_value = fake_content self.assertEqual(fileutils.read_file(self.fake_path), fake_content) self.assertEqual(mock_open_file.call_args[0][0], self.fake_path) self.assertEqual(mock_open_file.call_args[0][1], 'r') self.assertIsNone(mock_open_file.call_args[1]['newline'])
def test_read_file_continues_on_errors_without_displaying( self, mock_open_file, mock_print_warning): mock_open_file.side_effect = IOError() contents = fileutils.read_file(self.fake_path, continue_on_error=True, display_errors=False) self.assertIsNone(contents) self.assertFalse(mock_print_warning.called)
def create_message(): chat = build() body = {} i = 3 while i < len(sys.argv): myarg = sys.argv[i].lower() if myarg == 'text': body['text'] = sys.argv[i + 1].replace('\\r', '\r').replace('\\n', '\n') i += 2 elif myarg == 'textfile': filename = sys.argv[i + 1] i, encoding = gam.getCharSet(i + 2) body['text'] = fileutils.read_file(filename, encoding=encoding) elif myarg == 'space': space = sys.argv[i + 1] if space[:7] != 'spaces/': space = f'spaces/{space}' i += 2 elif myarg == 'thread': body['thread'] = {'name': sys.argv[i + 1]} i += 2 else: controlflow.invalid_argument_exit(myarg, 'gam create chat') if not space: controlflow.system_error_exit(2, 'space <ChatSpace> is required.') if 'text' not in body: controlflow.system_error_exit( 2, 'text <String> or textfile <FileName> is required.') if len(body['text']) > 4096: body['text'] = body['text'][:4095] print('WARNING: trimmed message longer than 4k to be 4k in length.') try: resp = gapi.call(chat.spaces().messages(), 'create', parent=space, body=body, throw_reasons=THROW_REASONS) except googleapiclient.errors.HttpError as err: _chat_error_handler(chat, err) if 'thread' in body: print(f'responded to thread {resp["thread"]["name"]}') else: print(f'started new thread {resp["thread"]["name"]}') print(f'message {resp["name"]}')
def update_message(): chat = build() body = {} name = None updateMask = 'text' i = 3 while i < len(sys.argv): myarg = sys.argv[i].lower() if myarg == 'text': body['text'] = sys.argv[i + 1].replace('\\r', '\r').replace('\\n', '\n') i += 2 elif myarg == 'textfile': filename = sys.argv[i + 1] i, encoding = gam.getCharSet(i + 2) body['text'] = fileutils.read_file(filename, encoding=encoding) elif myarg == 'name': name = sys.argv[i + 1] i += 2 else: controlflow.invalid_argument_exit(myarg, 'gam update chat') if not name: controlflow.system_error_exit(2, 'name <String> is required.') if 'text' not in body: controlflow.system_error_exit( 2, 'text <String> or textfile <FileName> is required.') if len(body['text']) > 4096: body['text'] = body['text'][:4095] print('WARNING: trimmed message longer than 4k to be 4k in length.') try: resp = gapi.call(chat.spaces().messages(), 'update', name=name, updateMask=updateMask, body=body) except googleapiclient.errors.HttpError as err: _chat_error_handler(chat, err) if 'thread' in body: print(f'updated response to thread {resp["thread"]["name"]}') else: print(f'updated message on thread {resp["thread"]["name"]}') print(f'message {resp["name"]}')
def from_client_secrets_file(cls, client_secrets_file, scopes, access_type='offline', login_hint=None, credentials_file=None, use_console_flow=False): """Runs an OAuth Flow from secrets stored on disk to generate credentials. Args: client_secrets_file: String, path to a file containing a client ID and secret. scopes: Sequence[str], A list of scopes to include in the credentials. access_type: String, 'offline' or 'online'. Indicates whether your application can refresh access tokens when the user is not present at the browser. Valid parameter values are online, which is the default value, and offline. Set the value to offline if your application needs to refresh access tokens when the user is not present at the browser. This is the method of refreshing access tokens described later in this document. This value instructs the Google authorization server to return a refresh token and an access token the first time that your application exchanges an authorization code for tokens. login_hint: String, The email address that will be displayed on the Google login page as a hint for the user to login to the correct account. credentials_file: String, the path to a file to use to save the credentials. use_console_flow: Boolean, True if the authentication flow should be run strictly from a console; False to launch a browser for authentication. Raises: InvalidClientSecretsFileError: If the client secrets file cannot be opened. InvalidClientSecretsFileFormatError: If the client secrets file does not contain the required data or the data is malformed. Returns: Credentials """ cs_data = fileutils.read_file(client_secrets_file, continue_on_error=True, display_errors=False) if not cs_data: raise InvalidClientSecretsFileError( f'File {client_secrets_file} could not be opened') try: cs_json = json.loads(cs_data) client_id = cs_json['installed']['client_id'] # Chop off .apps.googleusercontent.com suffix as it's not needed # and we need to keep things short for the Auth URL. client_id = re.sub(r'\.apps\.googleusercontent\.com$', '', client_id) client_secret = cs_json['installed']['client_secret'] except (ValueError, IndexError, KeyError): raise InvalidClientSecretsFileFormatError( f'Could not extract Client ID or Client Secret from file {client_secrets_file}' ) return cls.from_client_secrets(client_id, client_secret, scopes, access_type=access_type, login_hint=login_hint, filename=credentials_file, use_console_flow=use_console_flow)
def test_read_file_exits_code_2_on_unicodeerror(self, mock_open_file): mock_open_file.return_value.__enter__( ).read.side_effect = UnicodeError() with self.assertRaises(SystemExit) as context: fileutils.read_file(self.fake_path) self.assertEqual(context.exception.code, 2)
def test_read_file_exits_code_6_when_continue_on_error_is_false( self, mock_open_file): mock_open_file.side_effect = IOError() with self.assertRaises(SystemExit) as context: fileutils.read_file(self.fake_path, continue_on_error=False) self.assertEqual(context.exception.code, 6)
def test_read_file_from_stdin(self, mock_stdin): mock_stdin.read.return_value = 'some stdin content' self.assertEqual(fileutils.read_file('-'), mock_stdin.read.return_value)