Skip to content

Commit 8c06557

Browse files
committed
docs: Consistency around admonitions
Throughout the documentation we had a bit of inconsistency around admonitions. As such we added few rules to keep the consistency which will improve the UX: * we should use `???+` instead of `!!!` so we can have a collapse block (default open) * for admonitions with default title, we should write the description on a new line * for admonitions which has a custom title as well as a description, we should adhere to the format `<admonitions type>: <custom title>`. E.g - for a tip admonitions with a custom title "Did you know?" and description of "Powertools is a brilliant library" ``` ???+ tip "Tip: Did you know?" Powertools is a brilliant library ```
1 parent cd15ee9 commit 8c06557

14 files changed

+317
-283
lines changed

Diff for: docs/core/event_handler/api_gateway.md

+28-17
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ You can define your functions to match a path and HTTP method, when you use the
7171

7272
Here's an example where we have two separate functions to resolve two paths: `/hello`.
7373

74-
!!! info "We automatically serialize `Dict` responses as JSON, trim whitespaces for compact responses, and set content-type to `application/json`"
74+
???+ info
75+
We automatically serialize `Dict` responses as JSON, trim whitespaces for compact responses, and set content-type to `application/json`.
7576

7677
=== "app.py"
7778

@@ -309,13 +310,15 @@ You can also nest paths as configured earlier in [our sample infrastructure](#re
309310

310311
#### Catch-all routes
311312

312-
!!! note "We recommend having explicit routes whenever possible; use catch-all routes sparingly"
313+
???+ note
314+
We recommend having explicit routes whenever possible; use catch-all routes sparingly.
313315

314316
You can use a regex string to handle an arbitrary number of paths within a request, for example `.+`.
315317

316318
You can also combine nested paths with greedy regex to catch in between routes.
317319

318-
!!! warning "We will choose the more explicit registered route that match incoming event"
320+
???+ warning
321+
We will choose the more explicit registered route that match incoming event.
319322

320323
=== "app.py"
321324

@@ -421,8 +424,8 @@ HTTP methods.
421424
}
422425
```
423426

424-
!!! note "It is usually better to have separate functions for each HTTP method, as the functionality tends to differ
425-
depending on which method is used."
427+
???+ note
428+
It is usually better to have separate functions for each HTTP method, as the functionality tends to differ depending on which method is used.
426429

427430
### Accessing request details
428431

@@ -569,7 +572,8 @@ You can use **`exception_handler`** decorator with any Python exception. This al
569572

570573
You can easily raise any HTTP Error back to the client using `ServiceError` exception.
571574

572-
!!! info "If you need to send custom headers, use [Response](#fine-grained-responses) class instead."
575+
???+ info
576+
If you need to send custom headers, use [Response](#fine-grained-responses) class instead.
573577

574578
Additionally, we provide pre-defined errors for the most popular ones such as HTTP 400, 401, 404, 500.
575579

@@ -664,7 +668,8 @@ This will lead to a HTTP 404 despite having your Lambda configured correctly. Se
664668
}
665669
```
666670

667-
Note: After removing a path prefix with `strip_prefixes`, the new root path will automatically be mapped to the path argument of `/`. For example, when using `strip_prefixes` value of `/pay`, there is no difference between a request path of `/pay` and `/pay/`; and the path argument would be defined as `/`.
671+
???+ note
672+
After removing a path prefix with `strip_prefixes`, the new root path will automatically be mapped to the path argument of `/`. For example, when using `strip_prefixes` value of `/pay`, there is no difference between a request path of `/pay` and `/pay/`; and the path argument would be defined as `/`.
668673

669674
## Advanced
670675

@@ -732,7 +737,8 @@ This will ensure that CORS headers are always returned as part of the response w
732737
}
733738
```
734739

735-
!!! tip "Optionally disable class on a per path basis with `cors=False` parameter"
740+
???+ tip
741+
Optionally disable class on a per path basis with `cors=False` parameter.
736742

737743
#### Pre-flight
738744

@@ -744,7 +750,8 @@ For convenience, we automatically handle that for you as long as you [setup CORS
744750

745751
For convenience, these are the default values when using `CORSConfig` to enable CORS:
746752

747-
!!! warning "Always configure `allow_origin` when using in production"
753+
???+ warning
754+
Always configure `allow_origin` when using in production.
748755

749756
Key | Value | Note
750757
------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------
@@ -797,7 +804,8 @@ You can use the `Response` class to have full control over the response, for exa
797804

798805
You can compress with gzip and base64 encode your responses via `compress` parameter.
799806

800-
!!! warning "The client must send the `Accept-Encoding` header, otherwise a normal response will be sent"
807+
???+ warning
808+
The client must send the `Accept-Encoding` header, otherwise a normal response will be sent.
801809

802810
=== "app.py"
803811

@@ -847,7 +855,8 @@ For convenience, we automatically base64 encode binary responses. You can also u
847855

848856
Like `compress` feature, the client must send the `Accept` header with the correct media type.
849857

850-
!!! warning "This feature requires API Gateway to configure binary media types, see [our sample infrastructure](#required-resources) for reference"
858+
???+ warning
859+
This feature requires API Gateway to configure binary media types, see [our sample infrastructure](#required-resources) for reference.
851860

852861
=== "app.py"
853862

@@ -942,7 +951,8 @@ You can enable debug mode via `debug` param, or via `POWERTOOLS_EVENT_HANDLER_DE
942951

943952
This will enable full tracebacks errors in the response, print request and responses, and set CORS in development mode.
944953

945-
!!! warning "This might reveal sensitive information in your logs and relax CORS restrictions, use it sparingly."
954+
???+ warning
955+
This might reveal sensitive information in your logs and relax CORS restrictions, use it sparingly.
946956

947957
=== "debug.py"
948958

@@ -1276,21 +1286,22 @@ Event Handler naturally leads to a single Lambda function handling multiple rout
12761286

12771287
Both single (monolithic) and multiple functions (micro) offer different set of trade-offs worth knowing.
12781288

1279-
!!! tip "TL;DR. Start with a monolithic function, add additional functions with new handlers, and possibly break into micro functions if necessary."
1289+
???+ tip
1290+
TL;DR. Start with a monolithic function, add additional functions with new handlers, and possibly break into micro functions if necessary.
12801291

12811292
#### Monolithic function
12821293

12831294
![Monolithic function sample](./../../media/monolithic-function.png)
12841295

12851296
A monolithic function means that your final code artifact will be deployed to a single function. This is generally the best approach to start.
12861297

1287-
**Benefits**
1298+
_**Benefits**_
12881299

12891300
* **Code reuse**. It's easier to reason about your service, modularize it and reuse code as it grows. Eventually, it can be turned into a standalone library.
12901301
* **No custom tooling**. Monolithic functions are treated just like normal Python packages; no upfront investment in tooling.
12911302
* **Faster deployment and debugging**. Whether you use all-at-once, linear, or canary deployments, a monolithic function is a single deployable unit. IDEs like PyCharm and VSCode have tooling to quickly profile, visualize, and step through debug any Python package.
12921303

1293-
**Downsides**
1304+
_**Downsides**_
12941305

12951306
* **Cold starts**. Frequent deployments and/or high load can diminish the benefit of monolithic functions depending on your latency requirements, due to [Lambda scaling model](https://docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html){target="_blank"}. Always load test to pragmatically balance between your customer experience and development cognitive load.
12961307
* **Granular security permissions**. The micro function approach enables you to use fine-grained permissions & access controls, separate external dependencies & code signing at the function level. Conversely, you could have multiple functions while duplicating the final code artifact in a monolithic approach.
@@ -1303,13 +1314,13 @@ A monolithic function means that your final code artifact will be deployed to a
13031314

13041315
A micro function means that your final code artifact will be different to each function deployed. This is generally the approach to start if you're looking for fine-grain control and/or high load on certain parts of your service.
13051316

1306-
**Benefits**
1317+
_**Benefits**_
13071318

13081319
* **Granular scaling**. A micro function can benefit from the [Lambda scaling model](https://docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html){target="_blank"} to scale differently depending on each part of your application. Concurrency controls and provisioned concurrency can also be used at a granular level for capacity management.
13091320
* **Discoverability**. Micro functions are easier do visualize when using distributed tracing. Their high-level architectures can be self-explanatory, and complexity is highly visible — assuming each function is named to the business purpose it serves.
13101321
* **Package size**. An independent function can be significant smaller (KB vs MB) depending on external dependencies it require to perform its purpose. Conversely, a monolithic approach can benefit from [Lambda Layers](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html){target="_blank"} to optimize builds for external dependencies.
13111322

1312-
**Downsides**
1323+
_**Downsides**_
13131324

13141325
* **Upfront investment**. Python ecosystem doesn't use a bundler — you need a custom build tooling to ensure each function only has what it needs and account for [C bindings for runtime compatibility](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html){target="_blank"}. Operations become more elaborate — you need to standardize tracing labels/annotations, structured logging, and metrics to pinpoint root causes.
13151326
- Engineering discipline is necessary for both approaches. Micro-function approach however requires further attention in consistency as the number of functions grow, just like any distributed system.

Diff for: docs/core/event_handler/appsync.md

+9-7
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ You must have an existing AppSync GraphQL API and IAM permissions to invoke your
2727

2828
This is the sample infrastructure we are using for the initial examples with a AppSync Direct Lambda Resolver.
2929

30-
=== "schema.graphql"
30+
???+ tip "Tip: Designing GraphQL Schemas for the first time?"
31+
Visit [AWS AppSync schema documentation](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html){target="_blank"} for understanding how to define types, nesting, and pagination.
3132

32-
!!! tip "Designing GraphQL Schemas for the first time?"
33-
Visit [AWS AppSync schema documentation](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html){target="_blank"} for understanding how to define types, nesting, and pagination.
33+
=== "schema.graphql"
3434

3535
```typescript
3636
--8<-- "docs/shared/getting_started_schema.graphql"
@@ -176,7 +176,8 @@ You can define your functions to match GraphQL types and fields with the `app.re
176176

177177
Here's an example where we have two separate functions to resolve `getTodo` and `listTodos` fields within the `Query` type. For completion, we use Scalar type utilities to generate the right output based on our schema definition.
178178

179-
!!! info "GraphQL arguments are passed as function arguments"
179+
???+ info
180+
GraphQL arguments are passed as function arguments.
180181

181182
=== "app.py"
182183

@@ -456,8 +457,8 @@ Assuming you have [Amplify CLI installed](https://docs.amplify.aws/cli/start/ins
456457

457458
[Create two new basic Python functions](https://docs.amplify.aws/cli/function#set-up-a-function){target="_blank"} via `amplify add function`.
458459

459-
!!! note "Amplify CLI generated functions use `Pipenv` as a dependency manager"
460-
Your function source code is located at **`amplify/backend/function/your-function-name`**.
460+
???+ note
461+
Amplify CLI generated functions use `Pipenv` as a dependency manager. Your function source code is located at **`amplify/backend/function/your-function-name`**.
461462

462463
Within your function's folder, add Lambda Powertools as a dependency with `pipenv install aws-lambda-powertools`.
463464

@@ -713,7 +714,8 @@ You can subclass `AppSyncResolverEvent` to bring your own set of methods to hand
713714

714715
### Split operations with Router
715716

716-
!!! tip "Read the **[considerations section for trade-offs between monolithic and micro functions](./api_gateway.md#considerations){target="_blank"}**, as it's also applicable here."
717+
???+ tip
718+
Read the **[considerations section for trade-offs between monolithic and micro functions](./api_gateway.md#considerations){target="_blank"}**, as it's also applicable here.
717719

718720
As you grow the number of related GraphQL operations a given Lambda function should handle, it is natural to split them into separate files to ease maintenance - That's where the `Router` feature is useful.
719721

0 commit comments

Comments
 (0)