api: Use custom exceptions in API client.
This removes the use of RuntimeError, and replaces it with a custom error class called ZulipError. In a few places, we use a subclass to make it easier for code to interact with the error type.
This commit is contained in:
parent
b7b083f094
commit
fc1d134685
|
@ -7,7 +7,7 @@ import unittest
|
||||||
import zulip
|
import zulip
|
||||||
|
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
from zulip import ZulipError
|
||||||
if six.PY2:
|
if six.PY2:
|
||||||
from mock import patch
|
from mock import patch
|
||||||
else:
|
else:
|
||||||
|
@ -38,7 +38,7 @@ Zulip API configuration:
|
||||||
parser = zulip.add_default_arguments(argparse.ArgumentParser(usage="lorem ipsum"))
|
parser = zulip.add_default_arguments(argparse.ArgumentParser(usage="lorem ipsum"))
|
||||||
test_path = '~/zuliprc'
|
test_path = '~/zuliprc'
|
||||||
args = parser.parse_args(['--config-file', test_path])
|
args = parser.parse_args(['--config-file', test_path])
|
||||||
with self.assertRaises(RuntimeError) as cm:
|
with self.assertRaises(ZulipError) as cm:
|
||||||
zulip.init_from_options(args)
|
zulip.init_from_options(args)
|
||||||
expanded_test_path = os.path.abspath(os.path.expanduser(test_path))
|
expanded_test_path = os.path.abspath(os.path.expanduser(test_path))
|
||||||
self.assertEqual(str(cm.exception), 'api_key or email not specified and '
|
self.assertEqual(str(cm.exception), 'api_key or email not specified and '
|
||||||
|
|
|
@ -267,13 +267,19 @@ def get_default_config_filename():
|
||||||
config_file = os.path.join(os.environ["HOME"], ".zuliprc")
|
config_file = os.path.join(os.environ["HOME"], ".zuliprc")
|
||||||
if (not os.path.exists(config_file) and
|
if (not os.path.exists(config_file) and
|
||||||
os.path.exists(os.path.join(os.environ["HOME"], ".humbugrc"))):
|
os.path.exists(os.path.join(os.environ["HOME"], ".humbugrc"))):
|
||||||
raise RuntimeError("The Zulip API configuration file is now ~/.zuliprc; please run:\n\n"
|
raise ZulipError("The Zulip API configuration file is now ~/.zuliprc; please run:\n\n"
|
||||||
" mv ~/.humbugrc ~/.zuliprc\n")
|
" mv ~/.humbugrc ~/.zuliprc\n")
|
||||||
return config_file
|
return config_file
|
||||||
|
|
||||||
class ZulipError(Exception):
|
class ZulipError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class ConfigNotFoundError(ZulipError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MissingURLError(ZulipError):
|
||||||
|
pass
|
||||||
|
|
||||||
class Client(object):
|
class Client(object):
|
||||||
def __init__(self, email=None, api_key=None, config_file=None,
|
def __init__(self, email=None, api_key=None, config_file=None,
|
||||||
verbose=False, retry_on_errors=True,
|
verbose=False, retry_on_errors=True,
|
||||||
|
@ -331,11 +337,11 @@ class Client(object):
|
||||||
elif insecure_setting == "false":
|
elif insecure_setting == "false":
|
||||||
insecure = False
|
insecure = False
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("insecure is set to '%s', it must be 'true' or 'false' if it is used in %s"
|
raise ZulipError("insecure is set to '%s', it must be 'true' or 'false' if it is used in %s"
|
||||||
% (insecure_setting, config_file))
|
% (insecure_setting, config_file))
|
||||||
elif None in (api_key, email):
|
elif None in (api_key, email):
|
||||||
raise RuntimeError("api_key or email not specified and file %s does not exist"
|
raise ConfigNotFoundError("api_key or email not specified and file %s does not exist"
|
||||||
% (config_file,))
|
% (config_file,))
|
||||||
|
|
||||||
assert(api_key is not None and email is not None)
|
assert(api_key is not None and email is not None)
|
||||||
self.api_key = api_key
|
self.api_key = api_key
|
||||||
|
@ -350,7 +356,7 @@ class Client(object):
|
||||||
site = site.rstrip("/")
|
site = site.rstrip("/")
|
||||||
self.base_url = site
|
self.base_url = site
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Missing Zulip server URL; specify via --site or ~/.zuliprc.")
|
raise MissingURLError("Missing Zulip server URL; specify via --site or ~/.zuliprc.")
|
||||||
|
|
||||||
if not self.base_url.endswith("/api"):
|
if not self.base_url.endswith("/api"):
|
||||||
self.base_url += "/api"
|
self.base_url += "/api"
|
||||||
|
@ -362,8 +368,8 @@ class Client(object):
|
||||||
self.tls_verification = False # type: Union[bool, str]
|
self.tls_verification = False # type: Union[bool, str]
|
||||||
elif cert_bundle is not None:
|
elif cert_bundle is not None:
|
||||||
if not os.path.isfile(cert_bundle):
|
if not os.path.isfile(cert_bundle):
|
||||||
raise RuntimeError("tls bundle '%s' does not exist"
|
raise ConfigNotFoundError("tls bundle '%s' does not exist"
|
||||||
% (cert_bundle,))
|
% (cert_bundle,))
|
||||||
self.tls_verification = cert_bundle
|
self.tls_verification = cert_bundle
|
||||||
else:
|
else:
|
||||||
# Default behavior: verify against system CA certificates
|
# Default behavior: verify against system CA certificates
|
||||||
|
@ -371,16 +377,16 @@ class Client(object):
|
||||||
|
|
||||||
if client_cert is None:
|
if client_cert is None:
|
||||||
if client_cert_key is not None:
|
if client_cert_key is not None:
|
||||||
raise RuntimeError("client cert key '%s' specified, but no client cert public part provided"
|
raise ConfigNotFoundError("client cert key '%s' specified, but no client cert public part provided"
|
||||||
% (client_cert_key,))
|
% (client_cert_key,))
|
||||||
else: # we have a client cert
|
else: # we have a client cert
|
||||||
if not os.path.isfile(client_cert):
|
if not os.path.isfile(client_cert):
|
||||||
raise RuntimeError("client cert '%s' does not exist"
|
raise ConfigNotFoundError("client cert '%s' does not exist"
|
||||||
% (client_cert,))
|
% (client_cert,))
|
||||||
if client_cert_key is not None:
|
if client_cert_key is not None:
|
||||||
if not os.path.isfile(client_cert_key):
|
if not os.path.isfile(client_cert_key):
|
||||||
raise RuntimeError("client cert key '%s' does not exist"
|
raise ConfigNotFoundError("client cert key '%s' does not exist"
|
||||||
% (client_cert_key,))
|
% (client_cert_key,))
|
||||||
self.client_cert = client_cert
|
self.client_cert = client_cert
|
||||||
self.client_cert_key = client_cert_key
|
self.client_cert_key = client_cert_key
|
||||||
|
|
||||||
|
@ -398,7 +404,7 @@ class Client(object):
|
||||||
|
|
||||||
# Build a client cert object for requests
|
# Build a client cert object for requests
|
||||||
if self.client_cert_key is not None:
|
if self.client_cert_key is not None:
|
||||||
assert(self.client_cert is not None) # Otherwise RuntimeError near end of __init__
|
assert(self.client_cert is not None) # Otherwise ZulipError near end of __init__
|
||||||
client_cert = (self.client_cert, self.client_cert_key) # type: Union[None, str, Tuple[str, str]]
|
client_cert = (self.client_cert, self.client_cert_key) # type: Union[None, str, Tuple[str, str]]
|
||||||
else:
|
else:
|
||||||
client_cert = self.client_cert
|
client_cert = self.client_cert
|
||||||
|
|
Loading…
Reference in a new issue