Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: move internal code-blocks to docs/examples/**/*.py files to be automatically tested #3445

Open
wants to merge 33 commits into
base: main
Choose a base branch
from

Conversation

JacobCoffee
Copy link
Member

@JacobCoffee JacobCoffee commented Apr 27, 2024

Description

Authored by @Kumzy in #3392, moved here due to fork issues

  • Moving all code-block to files

Closes

#3362

Kumzy added 30 commits April 27, 2024 12:08
… and adding language python to missing blocks
@JacobCoffee JacobCoffee requested review from provinzkraut and a team as code owners April 27, 2024 17:21
@github-actions github-actions bot added area/docs This PR involves changes to the documentation size: large pr/internal labels Apr 27, 2024
@JacobCoffee JacobCoffee changed the title Kumzy/main docs: move internal code-blocks to docs/examples/**/*.py files to be automatically tested Apr 27, 2024
@JacobCoffee
Copy link
Member Author

JacobCoffee commented Apr 27, 2024

Still remaining @Kumzy we just need to fix any pre-commit failures

pre-commit install
pre-commit run --all-files

and fix the ones in the new docs/examples dirs.

Basically most of them look like missing imports like

docs/examples/templating/template_file.py:1:2: F821 Undefined name `get`
Details

ruff.....................................................................Failed
- hook id: ruff
- exit code: 1

docs/examples/channels/publish_data.py:1:1: F821 Undefined name channels
docs/examples/channels/subscribe_method_context_manager.py:1:12: F821 Undefined name channels
docs/examples/channels/subscribe_method_manually.py:1:14: F704 await statement outside of a function
docs/examples/channels/subscribe_method_manually.py:1:14: PLE1142 await should be used within an async function
docs/examples/channels/subscribe_method_manually.py:1:20: F821 Undefined name channels
docs/examples/channels/subscribe_method_manually.py:5:5: F704 await statement outside of a function
docs/examples/channels/subscribe_method_manually.py:5:5: PLE1142 await should be used within an async function
docs/examples/channels/subscribe_method_manually.py:5:11: F821 Undefined name channels
docs/examples/channels/unsubscribe_method_context_manager.py:1:12: F821 Undefined name channels
docs/examples/channels/unsubscribe_method_context_manager.py:3:5: F704 await statement outside of a function
docs/examples/channels/unsubscribe_method_context_manager.py:3:5: PLE1142 await should be used within an async function
docs/examples/channels/unsubscribe_method_context_manager.py:3:11: F821 Undefined name channels
docs/examples/channels/unsubscribe_method_manually.py:1:14: F704 await statement outside of a function
docs/examples/channels/unsubscribe_method_manually.py:1:14: PLE1142 await should be used within an async function
docs/examples/channels/unsubscribe_method_manually.py:1:20: F821 Undefined name channels
docs/examples/channels/unsubscribe_method_manually.py:3:1: F704 await statement outside of a function
docs/examples/channels/unsubscribe_method_manually.py:3:1: PLE1142 await should be used within an async function
docs/examples/channels/unsubscribe_method_manually.py:3:7: F821 Undefined name channels
docs/examples/data_transfer_objects/factory/enveloping_return_data_1.py:10:11: F821 Undefined name List
docs/examples/data_transfer_objects/factory/enveloping_return_data_2.py:6:29: F821 Undefined name User
docs/examples/data_transfer_objects/factory/enveloping_return_data_3.py:4:20: F821 Undefined name UserDTO
docs/examples/data_transfer_objects/factory/enveloping_return_data_3.py:5:20: F821 Undefined name WithCount
docs/examples/data_transfer_objects/factory/enveloping_return_data_3.py:5:30: F821 Undefined name User
docs/examples/data_transfer_objects/factory/enveloping_return_data_3.py:6:12: F821 Undefined name WithCount
docs/examples/data_transfer_objects/factory/enveloping_return_data_3.py:9:13: F821 Undefined name User
docs/examples/data_transfer_objects/factory/enveloping_return_data_3.py:13:28: F821 Undefined name datetime
docs/examples/data_transfer_objects/factory/excluding_fields_2.py:1:10: F821 Undefined name DTOConfig
docs/examples/data_transfer_objects/factory/paginated_return_data_1.py:6:29: F821 Undefined name User
docs/examples/data_transfer_objects/factory/paginated_return_data_2.py:5:20: F821 Undefined name UserDTO
docs/examples/data_transfer_objects/factory/paginated_return_data_2.py:6:38: F821 Undefined name User
docs/examples/data_transfer_objects/factory/paginated_return_data_2.py:12:13: F821 Undefined name User
docs/examples/data_transfer_objects/factory/paginated_return_data_2.py:16:28: F821 Undefined name datetime
docs/examples/data_transfer_objects/factory/response_return_data_1.py:6:29: F821 Undefined name User
docs/examples/data_transfer_objects/factory/response_return_data_2.py:4:20: F821 Undefined name UserDTO
docs/examples/data_transfer_objects/factory/response_return_data_2.py:5:29: F821 Undefined name User
docs/examples/data_transfer_objects/factory/response_return_data_2.py:7:17: F821 Undefined name User
docs/examples/data_transfer_objects/factory/response_return_data_2.py:11:24: F821 Undefined name datetime
docs/examples/debugging/running_litestar_with_pdb_on_exception.py:1:7: F821 Undefined name Litestar
docs/examples/events/argument_to_listener.py:1:38: F821 Undefined name Any
docs/examples/events/argument_to_listener.py:1:53: F821 Undefined name Any
docs/examples/events/event_base.py:24:37: F821 Undefined name UserDTO
docs/examples/events/listener_exception.py:1:2: F821 Undefined name listener
docs/examples/events/listener_exception.py:3:11: F821 Undefined name send_farewell_email
docs/examples/events/listener_exception.py:6:2: F821 Undefined name listener
docs/examples/events/listener_exception.py:9:11: F821 Undefined name client
docs/examples/events/listener_exception.py:12:2: F821 Undefined name dataclass
docs/examples/events/listener_exception.py:18:2: F821 Undefined name post
docs/examples/events/listener_exception.py:19:37: F821 Undefined name UserDTO
docs/examples/events/listener_exception.py:19:55: F821 Undefined name Request
docs/examples/events/listener_exception.py:20:11: F821 Undefined name user_repository
docs/examples/events/listener_exception.py:20:44: F821 Undefined name email
docs/examples/events/listener_no_exception.py:1:2: F821 Undefined name listener
docs/examples/events/listener_no_exception.py:3:11: F821 Undefined name send_farewell_email
docs/examples/events/listener_no_exception.py:6:2: F821 Undefined name listener
docs/examples/events/listener_no_exception.py:8:11: F821 Undefined name client
docs/examples/events/multiple_events.py:8:11: F821 Undefined name send_email
docs/examples/events/multiple_listeners.py:30:37: F821 Undefined name UserDTO
docs/examples/events/multiple_listeners.py:31:44: F821 Undefined name email
docs/examples/execution_order.py:1:7: F821 Undefined name Litestar
docs/examples/execution_order.py:1:26: F821 Undefined name ctx_a
docs/examples/execution_order.py:1:33: F821 Undefined name ctx_b
docs/examples/execution_order.py:1:54: F821 Undefined name hook_a
docs/examples/execution_order.py:1:62: F821 Undefined name hook_b
docs/examples/htmx/htmx_client_redirect.py:1:2: F821 Undefined name get
docs/examples/htmx/htmx_client_redirect.py:2:18: F821 Undefined name ClientRedirect
docs/examples/htmx/htmx_client_redirect.py:3:12: F821 Undefined name ClientRedirect
docs/examples/htmx/htmx_client_refresh.py:1:2: F821 Undefined name get
docs/examples/htmx/htmx_client_refresh.py:2:18: F821 Undefined name ClientRefresh
docs/examples/htmx/htmx_client_refresh.py:3:12: F821 Undefined name ClientRefresh
docs/examples/htmx/htmx_push_url.py:1:2: F821 Undefined name get
docs/examples/htmx/htmx_push_url.py:2:18: F821 Undefined name PushUrl
docs/examples/htmx/htmx_push_url.py:3:12: F821 Undefined name PushUrl
docs/examples/htmx/htmx_replace_url.py:1:2: F821 Undefined name get
docs/examples/htmx/htmx_replace_url.py:2:18: F821 Undefined name ReplaceUrl
docs/examples/htmx/htmx_replace_url.py:3:12: F821 Undefined name ReplaceUrl
docs/examples/htmx/htmx_request.py:19:63: F821 Undefined name context
docs/examples/htmx/htmx_response.py:5:2: F821 Undefined name get
docs/examples/htmx/htmx_response.py:7:14: F821 Undefined name HTMXRequest
docs/examples/htmx/htmx_response.py:11:17: F821 Undefined name context
docs/examples/htmx/htmx_response_change_dom.py:1:2: F821 Undefined name get
docs/examples/htmx/htmx_response_change_dom.py:2:18: F821 Undefined name HXLocation
docs/examples/htmx/htmx_response_change_dom.py:3:12: F821 Undefined name HXLocation
docs/examples/htmx/htmx_response_change_dom.py:6:16: F821 Undefined name source
docs/examples/htmx/htmx_response_change_dom.py:7:15: F821 Undefined name event
docs/examples/htmx/htmx_response_no_dom_change.py:1:2: F821 Undefined name get
docs/examples/htmx/htmx_response_no_dom_change.py:2:18: F821 Undefined name HXStopPolling
docs/examples/htmx/htmx_response_no_dom_change.py:3:12: F821 Undefined name HXStopPolling
docs/examples/htmx/htmx_reswap.py:1:2: F821 Undefined name get
docs/examples/htmx/htmx_reswap.py:2:18: F821 Undefined name Reswap
docs/examples/htmx/htmx_reswap.py:3:12: F821 Undefined name Reswap
docs/examples/htmx/htmx_retarget.py:1:2: F821 Undefined name get
docs/examples/htmx/htmx_retarget.py:2:18: F821 Undefined name Retarget
docs/examples/htmx/htmx_retarget.py:3:12: F821 Undefined name Retarget
docs/examples/htmx/htmx_trigger_event.py:1:2: F821 Undefined name get
docs/examples/htmx/htmx_trigger_event.py:2:18: F821 Undefined name TriggerEvent
docs/examples/htmx/htmx_trigger_event.py:3:12: F821 Undefined name TriggerEvent
docs/examples/metrics/Init.py:1:1: N999 Invalid module name: 'Init'
docs/examples/middleware/builtin/csrf_cookies.py:1:15: F821 Undefined name CSRFConfig
docs/examples/middleware/builtin/csrf_exclude_route.py:1:2: F821 Undefined name post
docs/examples/middleware/creation/create_middleware_using_middleware_protocol_2.py:18:25: UP031 Use format specifiers instead of percent format
docs/examples/middleware/creation/create_middleware_using_middleware_protocol_2.py:18:25: G002 Logging statement uses %
docs/examples/responses/response_cookies_dict.py:1:2: F821 Undefined name get
docs/examples/responses/response_headers_attributes.py:1:2: F821 Undefined name get
docs/examples/routing/handler_asgi_2.py:18:1: E402 Module level import not at top of file
docs/examples/routing/handler_asgi_2.py:19:1: E402 Module level import not at top of file
docs/examples/routing/handler_asgi_2.py:23:11: F811 Redefinition of unused my_asgi_app from line 8
docs/examples/security/exclude_from_auth.py:1:2: F821 Undefined name get
docs/examples/security/exclude_from_auth.py:2:24: F821 Undefined name Any
docs/examples/security/exclude_from_auth.py:5:2: F821 Undefined name get
docs/examples/security/exclude_from_auth.py:6:26: F821 Undefined name Any
docs/examples/security/exclude_from_auth_with_key.py:1:2: F821 Undefined name get
docs/examples/security/exclude_from_auth_with_key.py:2:24: F821 Undefined name Any
docs/examples/security/exclude_from_auth_with_key.py:5:2: F821 Undefined name get
docs/examples/security/exclude_from_auth_with_key.py:6:26: F821 Undefined name Any
docs/examples/security/exclude_from_auth_with_key.py:9:16: F821 Undefined name SessionAuth
docs/examples/security/exclude_from_auth_with_key.py:9:28: F821 Undefined name User
docs/examples/security/exclude_from_auth_with_key.py:9:34: F821 Undefined name ServerSideSessionBackend
docs/examples/security/exclude_from_auth_with_key.py:10:27: F821 Undefined name retrieve_user_handler
docs/examples/security/exclude_from_auth_with_key.py:13:28: F821 Undefined name ServerSideSessionConfig
docs/examples/security/excluding_routes.py:1:16: F821 Undefined name SessionAuth
docs/examples/security/excluding_routes.py:1:28: F821 Undefined name User
docs/examples/security/excluding_routes.py:1:34: F821 Undefined name ServerSideSessionBackend
docs/examples/security/excluding_routes.py:2:27: F821 Undefined name retrieve_user_handler
docs/examples/security/excluding_routes.py:5:28: F821 Undefined name ServerSideSessionConfig
docs/examples/security/including_routes.py:1:16: F821 Undefined name SessionAuth
docs/examples/security/including_routes.py:1:28: F821 Undefined name User
docs/examples/security/including_routes.py:1:34: F821 Undefined name ServerSideSessionBackend
docs/examples/security/including_routes.py:2:27: F821 Undefined name retrieve_user_handler
docs/examples/security/including_routes.py:5:28: F821 Undefined name ServerSideSessionConfig
docs/examples/security/middleware/auth_middleware_creation.py:36:9: SIM117 Use a single with statement with multiple contexts instead of nested with statements
docs/examples/signature_namespace/handler_signature_1.py:13:21: N805 First argument of a method should be named self
docs/examples/templating/template_file.py:1:2: F821 Undefined name get
docs/examples/templating/template_file.py:2:24: F821 Undefined name Template
docs/examples/templating/template_file.py:3:12: F821 Undefined name Template
docs/examples/templating/template_string.py:1:2: F821 Undefined name get
docs/examples/templating/template_string.py:2:24: F821 Undefined name Template
docs/examples/templating/template_string.py:4:12: F821 Undefined name Template
docs/examples/todo_app/create/dynamic_route.py:1:2: F821 Undefined name get
docs/examples/todo_app/hello_world_2.py:5:15: F821 Undefined name get
docs/examples/websockets/receiving_json_and_sending_it_back_as_messagepack.py:7:43: F821 Undefined name mode
docs/examples/whats_new/attrs_v1.py:1:2: F821 Undefined name get
docs/examples/whats_new/attrs_v1.py:2:24: F821 Undefined name Parameter
docs/examples/whats_new/attrs_v2.py:1:2: F821 Undefined name get
docs/examples/whats_new/attrs_v2.py:2:18: F821 Undefined name Annotated
docs/examples/whats_new/attrs_v2.py:2:33: F821 Undefined name Parameter
docs/examples/whats_new/before_send_v1.py:1:32: F821 Undefined name Message
docs/examples/whats_new/before_send_v1.py:1:48: F821 Undefined name State
docs/examples/whats_new/before_send_v2.py:1:32: F821 Undefined name Message
docs/examples/whats_new/before_send_v2.py:1:48: F821 Undefined name State
docs/examples/whats_new/before_send_v2.py:1:62: F821 Undefined name Scope
docs/examples/whats_new/dependencies_without_provide_v1.py:4:7: F821 Undefined name Litestar
docs/examples/whats_new/dependencies_without_provide_v1.py:4:38: F821 Undefined name Provide
docs/examples/whats_new/dependencies_without_provide_v2.py:4:7: F821 Undefined name Litestar
docs/examples/whats_new/initial_state_v1.py:1:7: F821 Undefined name Starlite
docs/examples/whats_new/initial_state_v2.py:1:7: F821 Undefined name Litestar
docs/examples/whats_new/initial_state_v2.py:1:27: F821 Undefined name State
docs/examples/whats_new/lifespan_hook_v1.py:1:23: F821 Undefined name State
docs/examples/whats_new/lifespan_hook_v2.py:1:21: F821 Undefined name Litestar
docs/examples/whats_new/response_cookies_v1.py:1:2: F821 Undefined name get
docs/examples/whats_new/response_cookies_v1.py:1:29: F821 Undefined name Cookie
docs/examples/whats_new/response_cookies_v2.py:1:2: F821 Undefined name get
docs/examples/whats_new/response_headers_v2.py:12:11: F811 Redefinition of unused handler from line 5
docs/examples/whats_new/sync_to_thread_v1.py:1:2: F821 Undefined name get
docs/examples/whats_new/sync_to_thread_v2.py:1:2: F821 Undefined name get
docs/examples/whats_new/sync_to_thread_v2.py:8:2: F821 Undefined name get
docs/examples/whats_new/sync_to_thread_v2.py:9:5: F811 Redefinition of unused handler from line 2
Found 166 errors.
No fixes available (3 hidden fixes can be enabled with the --unsafe-fixes option).

and any test failures that this has exposed

 =========================== short test summary info ============================
ERROR docs/examples/testing/test_app_1.py
ERROR docs/examples/testing/test_app_2.py
ERROR docs/examples/testing/test_client_async.py
ERROR docs/examples/testing/test_client_conf_async.py
ERROR docs/examples/testing/test_client_conf_sync.py
ERROR docs/examples/testing/test_client_sync.py
ERROR docs/examples/testing/test_polyfactory_1.py
ERROR docs/examples/testing/test_polyfactory_2.py
ERROR docs/examples/testing/test_request_factory_2.py
ERROR docs/examples/testing/test_request_factory_3.py
= 5196 passed, 3 skipped, 2 xfailed, 4 warnings, 10 errors in 69.89s (0:01:09) =
Error: Process completed with exit code 1.

@JacobCoffee
Copy link
Member Author

@litestar-org/maintainers when we have examples like this, how do we want to handle the moving of them? Should we create my_app? or do we ignore and allow the test to not run (and then go stale, and so then why have we moved all of these code blocks 🙃)

 /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
docs/examples/testing/test_request_factory_3.py:2: in <module>
    from my_app.guards import secret_token_guard
E   ModuleNotFoundError: No module named 'my_app'
from os import environ

from my_app.guards import secret_token_guard

from litestar import get


@get(path="/secret", guards=[secret_token_guard], opt={"secret": environ.get("SECRET")})
def secret_endpoint() -> None: ...

@provinzkraut
Copy link
Member

@litestar-org/maintainers when we have examples like this, how do we want to handle the moving of them? Should we create my_app? or do we ignore and allow the test to not run (and then go stale, and so then why have we moved all of these code blocks 🙃)

 /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
docs/examples/testing/test_request_factory_3.py:2: in <module>
    from my_app.guards import secret_token_guard
E   ModuleNotFoundError: No module named 'my_app'
from os import environ

from my_app.guards import secret_token_guard

from litestar import get


@get(path="/secret", guards=[secret_token_guard], opt={"secret": environ.get("SECRET")})
def secret_endpoint() -> None: ...

Examples should all be self-contained. There are rare exceptions (like templates / static files), but this isn't one of them; The guard could very well be defined in the same file.

Having an app for every code example also give the benefit of us being able to auto-run them which, even if the example isn't tested explicitly, at least implicitly ensures that we don't have broken examples.

@Kumzy
Copy link
Member

Kumzy commented Apr 30, 2024

Had some question regarding latest changes to add import:

  1. for channels, is it correct to fix the following with from litestar.channels import ChannelsPlugin as Channels and replace channels by Channels
subscriber = await channels.subscribe(["foo", "bar"])
try:
    ...  # do some stuff here
finally:
    await channels.unsubscribe(subscriber)
  1. How should I fix the following, I have to create ctx_a ctx_b and hook_a and hook_b ?
from litestar import Litestar

app = Litestar(lifespan=[ctx_a, ctx_b], on_shutdown=[hook_a, hook_b])
  1. What to do about context there, what should I import or create?
@get(path="/form")
def get_form(request: HTMXRequest) -> Template:
    htmx = request.htmx  # if true will return HTMXDetails class object
    if htmx:
        print(htmx.current_url)
    # OR
    if request.htmx:
        print(request.htmx.current_url)
    return HTMXTemplate(template_name="partial.html", context=context, push_url="/form")
  1. mode was not declared and the type is Literal("text","binary"), are the modifications there correct?
from litestar import WebSocket, websocket
from litestar.types.asgi_types import WebSocketMode


mode = WebSocketMode("text")

@websocket("/")
async def handler(socket: WebSocket) -> None:
    await socket.accept()
    async for message in socket.iter_data(mode):
        await socket.send_msgpack(message)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/docs This PR involves changes to the documentation pr/internal size: large
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants