Skip to content

Commit e1b396b

Browse files
kristapraticorajivnandivada
authored andcommitted
adds exceptions docs and edits/typo fixes to core readme (Azure#5730)
1 parent 101138a commit e1b396b

File tree

2 files changed

+119
-19
lines changed

2 files changed

+119
-19
lines changed

sdk/core/azure-core/README.md

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
## Pipeline
66

7-
The Azure Core pipeline is a re-strucuting of the msrest pipeline introduced in msrest 0.6.0.
7+
The Azure Core pipeline is a re-structuring of the msrest pipeline introduced in msrest 0.6.0.
88
Further discussions on the msrest implementation can be found in the [msrest wiki](https://github.com/Azure/msrest-for-python/wiki/msrest-0.6.0---Pipeline).
99

1010
The Azure Core Pipeline is an implementation of chained policies as described in the [Azure SDK guidelines](https://github.com/Azure/azure-sdk/tree/master/docs/design).
1111

12-
The Python implementation of the pipeline has some mechanisms specific to Python. This is due to the fact that both synchronous and asynchronous implementations of the pipeline must be supported indepedently.
12+
The Python implementation of the pipeline has some mechanisms specific to Python. This is due to the fact that both synchronous and asynchronous implementations of the pipeline must be supported independently.
1313

1414
When constructing an SDK, a developer may consume the pipeline like so:
1515

@@ -22,26 +22,28 @@ from azure.core.pipeline.policies import (
2222
RetryPolicy,
2323
RedirectPolicy,
2424
BearerTokenCredentialPolicy,
25-
ContentDecodePolicy
25+
ContentDecodePolicy,
26+
NetworkTraceLoggingPolicy,
27+
ProxyPolicy
2628
)
2729

2830
class FooServiceClient():
2931

3032
@staticmethod
31-
def create_config(**kwargs):
33+
def create_config(credential, scopes, **kwargs):
3234
# Here the SDK developer would define the default
3335
# config to interact with the service
3436
config = Configuration(**kwargs)
3537
config.headers_policy = HeadersPolicy({"CustomHeader": "Value"}, **kwargs)
3638
config.user_agent_policy = UserAgentPolicy("ServiceUserAgentValue", **kwargs)
37-
config.authentication_policy = BearerTokenCredentialPolicy(credential, **kwargs)
39+
config.authentication_policy = BearerTokenCredentialPolicy(credential, scopes, **kwargs)
3840
config.retry_policy = RetryPolicy(**kwargs)
3941
config.redirect_policy = RedirectPolicy(**kwargs)
4042
config.logging_policy = NetworkTraceLoggingPolicy(**kwargs)
4143
config.proxy_policy = ProxyPolicy(**kwargs)
4244
config.transport = kwargs.get('transport', RequestsTransport)
4345

44-
def __init__(self, endpoint=None, credentials=None, configuration=None, **kwargs):
46+
def __init__(self, transport=None, configuration=None, **kwargs):
4547
config = configuration or FooServiceClient.create_config(**kwargs)
4648
transport = config.get_transport(**kwargs)
4749
policies = [
@@ -92,7 +94,7 @@ response = client.get_foo_properties(redirects_max=0)
9294
# Scenario where user wishes to fully customize the policies.
9395
# We expose the SDK-developer defined configuration to allow it to be tweaked
9496
# or entire policies replaced or patched.
95-
foo_config = FooserviceClient.create_config()
97+
foo_config = FooServiceClient.create_config()
9698

9799
foo_config.retry_policy = CustomRetryPolicy()
98100
foo_config.redirect_policy.max_redirects = 5
@@ -120,7 +122,7 @@ transport = RequestsTransport(config)
120122
policies = [
121123
config.headers_policy,
122124
config.user_agent_policy,
123-
config.authentication_policy, # Credentials policy needs to be inserted after all request mutation to accomodate signing.
125+
config.authentication_policy, # Authentication policy needs to be inserted after all request mutation to accommodate signing.
124126
ContentDecodePolicy(),
125127
config.redirect_policy,
126128
config.retry_policy,
@@ -137,6 +139,8 @@ The policies that should currently be defined on the Configuration object are as
137139
- Configuration.user_agent_policy # UserAgentPolicy
138140
- Configuration.connection # The is a ConnectionConfiguration, used to provide common transport parameters.
139141
- Configuration.proxy_policy # While this is a ProxyPolicy object, current implementation is transport configuration.
142+
- Configuration.authentication_policy # BearerTokenCredentialPolicy
143+
140144
```
141145

142146
### Transport
@@ -151,15 +155,15 @@ synchronous_transport = RequestsTransport()
151155
```
152156

153157
For asynchronous pipelines a couple of transport options are available. Each of these transports are interchangable depending on whether the user has installed various 3rd party dependencies (i.e. aiohttp or trio), and the user
154-
should easily be able to specify their chosen transport. SDK developers should use the `aiohttp` transport as the default for asynchronous pipelines where the user has not specified as alternative.
158+
should easily be able to specify their chosen transport. SDK developers should use the `aiohttp` transport as the default for asynchronous pipelines where the user has not specified an alternative.
155159
```
156160
from azure.foo.aio import FooServiceClient
157161
from azure.core.pipeline.transport import (
158-
# Identical implementation as the synchronous RequestsTrasport wrapped in an asynchronous using the
162+
# Identical implementation as the synchronous RequestsTransport wrapped in an asynchronous using the
159163
# built-in asyncio event loop.
160164
AsyncioRequestsTransport,
161165
162-
# Identical implementation as the synchronous RequestsTrasport wrapped in an asynchronous using the
166+
# Identical implementation as the synchronous RequestsTransport wrapped in an asynchronous using the
163167
# third party trio event loop.
164168
TrioRequestsTransport,
165169
@@ -176,16 +180,19 @@ Some common properties can be configured on all transports, and can be set on th
176180
class ConnectionConfiguration(object):
177181
"""Configuration of HTTP transport.
178182
179-
:param connection_timeout: The connect and read timeout value, in seconds. Default value is 100.
180-
:param verify: SSL certificate verification. Enabled by default. Set to False to disable, alternatively
181-
can be set to the path to a CA_BUNDLE file or directory with certificates of trusted CAs.
182-
:param cert: Client-side certificates. You can specify a local cert to use as client side certificate, as a single file (containing the private key and the certificate) or as a tuple of both files’ paths.
183+
:param int connection_timeout: The connect and read timeout value. Defaults to 100 seconds.
184+
:param bool connection_verify: SSL certificate verification. Enabled by default. Set to False to disable,
185+
alternatively can be set to the path to a CA_BUNDLE file or directory with certificates of trusted CAs.
186+
:param str connection_cert: Client-side certificates. You can specify a local cert to use as client side
187+
certificate, as a single file (containing the private key and the certificate) or as a tuple of both files' paths.
188+
:param int connection_data_block_size: The block size of data sent over the connection. Defaults to 4096 bytes.
183189
"""
184190

185191
def __init__(self, **kwargs):
186192
self.timeout = kwargs.pop('connection_timeout', 100)
187193
self.verify = kwargs.pop('connection_verify', True)
188194
self.cert = kwargs.pop('connection_cert', None)
195+
self.data_block_size = kwargs.pop('connection_data_block_size', 4096)
189196
```
190197

191198
### HttpRequest and HttpResponse
@@ -283,7 +290,7 @@ While the SDK developer will not construct the PipelineRequest explicitly, they
283290
object that is returned from `pipeline.run()`
284291
These objects are universal for all transports, both synchronous and asynchronous.
285292

286-
The pipeline request and response containers are also responsable for carrying a `context` object. This is
293+
The pipeline request and response containers are also responsible for carrying a `context` object. This is
287294
transport specific and can contain data persisted between pipeline requests (for example reusing an open connection
288295
pool or "session"), as well as used by the SDK developer to carry arbitrary data through the pipeline.
289296

@@ -372,7 +379,7 @@ Currently provided HTTP policies include:
372379
```python
373380
from azure.core.pipeline.policies import (
374381
RetryPolicy,
375-
AsyncRetryPolicy.
382+
AsyncRetryPolicy,
376383
RedirectPolicy,
377384
AsyncRedirectPolicy
378385
)
@@ -385,8 +392,8 @@ A pipeline can either be synchronous or asynchronous.
385392
The pipeline does not expose the policy chain, so individual policies cannot/should not be further
386393
configured once the pipeline has been instantiated.
387394

388-
The pipeline hasa single exposed operation: `run(request)` which will seen a new HttpRequest object down
389-
the pipeline. This operation returns a `PipelineResonse` object.
395+
The pipeline has a single exposed operation: `run(request)` which will send a new HttpRequest object down
396+
the pipeline. This operation returns a `PipelineResponse` object.
390397

391398
```python
392399
class Pipeline:
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Azure Core Library Exceptions
2+
3+
## AzureError
4+
AzureError is the base exception for all errors.
5+
```python
6+
class AzureError(Exception):
7+
def __init__(self, message, *args, **kwargs):
8+
self.inner_exception = kwargs.get('error')
9+
self.exc_type, self.exc_value, self.exc_traceback = sys.exc_info()
10+
self.exc_type = self.exc_type.__name__ if self.exc_type else type(self.inner_exception)
11+
self.exc_msg = "{}, {}: {}".format(message, self.exc_type, self.exc_value) # type: ignore
12+
self.message = str(message)
13+
super(AzureError, self).__init__(self.message, *args)
14+
```
15+
16+
*message* is any message (str) to be associated with the exception.
17+
18+
*args* are any additional args to be included with exception.
19+
20+
*kwargs* are keyword arguments to include with the exception. Use the keyword *error* to pass in an internal exception.
21+
22+
23+
**The following exceptions inherit from AzureError:**
24+
25+
## ServiceRequestError
26+
An error occurred while attempt to make a request to the service. No request was sent.
27+
28+
## ServiceResponseError
29+
The request was sent, but the client failed to understand the response.
30+
The connection may have timed out. These errors can be retried for idempotent or safe operations.
31+
32+
33+
## HttpResponseError
34+
Error occurs when a request was made, and a non-success status code was received from the service.
35+
```python
36+
class HttpResponseError(AzureError):
37+
def __init__(self, message=None, response=None, **kwargs):
38+
self.reason = None
39+
self.response = response
40+
if response:
41+
self.reason = response.reason
42+
message = "Operation returned an invalid status code '{}'".format(self.reason)
43+
try:
44+
try:
45+
if self.error.error.code or self.error.error.message:
46+
message = "({}) {}".format(
47+
self.error.error.code,
48+
self.error.error.message)
49+
except AttributeError:
50+
if self.error.message: #pylint: disable=no-member
51+
message = self.error.message #pylint: disable=no-member
52+
except AttributeError:
53+
pass
54+
super(HttpResponseError, self).__init__(message=message, **kwargs)
55+
```
56+
57+
*response* is the HTTP response (optional).
58+
59+
*kwargs* are keyword arguments to include with the exception.
60+
61+
62+
**The following exceptions inherit from HttpResponseError:**
63+
64+
## DecodeError
65+
An error raised during response deserialization.
66+
67+
## ResourceExistsError
68+
An error response with status code 4xx. This will not be raised directly by the Azure core pipeline.
69+
70+
## ResourceNotFoundError
71+
An error response, typically triggered by a 412 response (for update) or 404 (for get/post).
72+
73+
## ClientAuthenticationError
74+
An error response with status code 4xx. This will not be raised directly by the Azure core pipeline.
75+
76+
## ResourceModifiedError
77+
An error response with status code 4xx, typically 412 Conflict. This will not be raised directly by the Azure core pipeline.
78+
79+
## TooManyRedirectsError
80+
An error raised when the maximum number of redirect attempts is reached. The maximum amount of redirects can be configured in the RedirectPolicy.
81+
```python
82+
class TooManyRedirectsError(HttpResponseError):
83+
def __init__(self, history, *args, **kwargs):
84+
self.history = history
85+
message = "Reached maximum redirect attempts."
86+
super(TooManyRedirectsError, self).__init__(message, *args, **kwargs)
87+
```
88+
89+
*history* is used to document the requests/responses that resulted in redirected requests.
90+
91+
*args* are any additional args to be included with exception.
92+
93+
*kwargs* are keyword arguments to include with the exception.

0 commit comments

Comments
 (0)