From 6d1ee47ab754854c21599b2e42c9557bb518ce74 Mon Sep 17 00:00:00 2001 From: Bedram Tamang Date: Tue, 22 Sep 2026 14:27:52 -0700 Subject: [PATCH] fix(facades): resolve basedpyright errors in facade stubs Facade methods are accessed on the class via the Facade metaclass, so the stubs now declare them as @staticmethod (matching Config.pyi), drop stray self params, mark None defaults as optional and replace imports of modules that do not exist in this package with Any aliases. Co-Authored-By: Claude Opus 5.5 --- .../src/fastapi_startkit/facades/Dump.pyi | 19 +++++--- .../src/fastapi_startkit/facades/Gate.pyi | 21 +++++++-- .../src/fastapi_startkit/facades/Hash.pyi | 21 ++++++--- .../src/fastapi_startkit/facades/Mail.pyi | 17 ++++--- .../fastapi_startkit/facades/Notification.pyi | 11 +++-- .../src/fastapi_startkit/facades/Queue.pyi | 7 +++ .../src/fastapi_startkit/facades/Request.pyi | 37 +++++++++++++--- .../src/fastapi_startkit/facades/Response.pyi | 44 +++++++++++++------ .../src/fastapi_startkit/facades/Session.pyi | 32 +++++++++++--- .../src/fastapi_startkit/facades/View.pyi | 27 +++++++++--- 10 files changed, 178 insertions(+), 58 deletions(-) diff --git a/fastapi_startkit/src/fastapi_startkit/facades/Dump.pyi b/fastapi_startkit/src/fastapi_startkit/facades/Dump.pyi index 15776405..a9efa873 100644 --- a/fastapi_startkit/src/fastapi_startkit/facades/Dump.pyi +++ b/fastapi_startkit/src/fastapi_startkit/facades/Dump.pyi @@ -1,26 +1,31 @@ -from typing import Any, List, TYPE_CHECKING +from typing import Any, List -if TYPE_CHECKING: - from ..dumps import Dump as DumpObject +DumpObject = Any class Dump: """Dumper facade.""" - def clear(self) -> "Dump": + @staticmethod + def clear() -> "Dump": """Clear all dumped data""" ... - def dd(*objects: List[Any]): + @staticmethod + def dd(*objects: Any): """Dump all provided args and die, raising a DumpException.""" ... - def dump(*objects: List[Any]): + @staticmethod + def dump(*objects: Any): """Dump all provided args and continue code execution. This does not raise a DumpException.""" ... + @staticmethod def get_dumps(ascending: bool = False) -> List[DumpObject]: """Get all dumps as Dump objects. If ascending is True, get dumps from oldest to most recents.""" ... - def last(self) -> DumpObject: + @staticmethod + def last() -> DumpObject: """Return last added dump.""" ... + @staticmethod def get_serialized_dumps(ascending: bool = False) -> List[dict]: """Get all dumps as dict. If ascending is True, sort dumps from oldest to most recents.""" ... diff --git a/fastapi_startkit/src/fastapi_startkit/facades/Gate.pyi b/fastapi_startkit/src/fastapi_startkit/facades/Gate.pyi index af9edf96..08f629ba 100644 --- a/fastapi_startkit/src/fastapi_startkit/facades/Gate.pyi +++ b/fastapi_startkit/src/fastapi_startkit/facades/Gate.pyi @@ -1,31 +1,46 @@ -from typing import TYPE_CHECKING, Callable, List, Tuple, Any +from typing import Callable, List, Tuple, Any -if TYPE_CHECKING: - from ..authorization import AuthorizationResponse, Policy, Gate as GateObject +AuthorizationResponse = Any +Policy = Any +GateObject = Any class Gate: """Gate facade.""" + @staticmethod def define(permission: str, condition: Callable): ... + @staticmethod def register_policies(policies: List[Tuple[Any, Policy]]) -> "Gate": ... + @staticmethod def get_policy_for(instance_or_class: "str|Any") -> "None|Policy": ... + @staticmethod def before(before_callback: Callable): ... + @staticmethod def after(after_callback: Callable): ... + @staticmethod def allows(permission: str, *args) -> bool: ... + @staticmethod def denies(permission, *args) -> bool: ... + @staticmethod def has(permission: str) -> bool: ... + @staticmethod def for_user(user: Any) -> GateObject: ... + @staticmethod def any(permissions: List[str], *args) -> bool: """Check that every of those permissions are allowed.""" ... + @staticmethod def none(permissions: List[str], *args) -> bool: """Check that none of those permissions are allowed.""" ... + @staticmethod def authorize(permission: str, *args) -> bool: ... + @staticmethod def inspect(permission: str, *args) -> "bool|AuthorizationResponse": """Get permission checks results for the given user then builds and returns an authorization response.""" ... + @staticmethod def check(permission: str, *args): """The core of the authorization class. Run before() checks, permission check and then after() checks.""" diff --git a/fastapi_startkit/src/fastapi_startkit/facades/Hash.pyi b/fastapi_startkit/src/fastapi_startkit/facades/Hash.pyi index fca84bab..c5116274 100644 --- a/fastapi_startkit/src/fastapi_startkit/facades/Hash.pyi +++ b/fastapi_startkit/src/fastapi_startkit/facades/Hash.pyi @@ -1,26 +1,33 @@ from typing import Any class Hash: + @staticmethod def add_driver(name: str, driver: Any): ... + @staticmethod def set_configuration(config: dict) -> "Hash": ... - def get_driver(name: str = None) -> Any: ... - def get_config_options(driver: str = None) -> dict: ... - def make(string: str, options: dict = {}, driver: str = None) -> str: + @staticmethod + def get_driver(name: str | None = None) -> Any: ... + @staticmethod + def get_config_options(driver: str | None = None) -> dict: ... + @staticmethod + def make(string: str, options: dict = {}, driver: str | None = None) -> str: """Hash a string and return as string based on configured hashing protocol.""" ... - def make_bytes(string: str, options: dict = {}, driver: str = None) -> bytes: + @staticmethod + def make_bytes(string: str, options: dict = {}, driver: str | None = None) -> bytes: """Hash a string and return as bytes based on configured hashing protocol.""" ... + @staticmethod def check( - self, plain_string: str, hashed_string: str, options: dict = {}, - driver: str = None, + driver: str | None = None, ) -> bool: """Verify that a given string matches its hashed version (based on configured hashing protocol).""" ... - def needs_rehash(hashed_string: str, options: dict = {}, driver: str = None) -> bool: + @staticmethod + def needs_rehash(hashed_string: str, options: dict = {}, driver: str | None = None) -> bool: """Verify that a given hash needs to be hashed again because parameters for generating the hash have changed.""" ... diff --git a/fastapi_startkit/src/fastapi_startkit/facades/Mail.pyi b/fastapi_startkit/src/fastapi_startkit/facades/Mail.pyi index 81fc22fa..0de5dbb2 100644 --- a/fastapi_startkit/src/fastapi_startkit/facades/Mail.pyi +++ b/fastapi_startkit/src/fastapi_startkit/facades/Mail.pyi @@ -1,14 +1,19 @@ -from typing import Any, TYPE_CHECKING +from typing import Any -if TYPE_CHECKING: - from ..mail import Mailable +Mailable = Any class Mail: """Mail facade.""" + @staticmethod def add_driver(name: str, driver: Any): ... + @staticmethod def set_configuration(config: dict) -> "Mail": ... - def get_driver(name: str = None) -> Any: ... - def get_config_options(driver: str = None) -> dict: ... + @staticmethod + def get_driver(name: str | None = None) -> Any: ... + @staticmethod + def get_config_options(driver: str | None = None) -> dict: ... + @staticmethod def mailable(mailable: "Mailable") -> "Mail": ... - def send(driver: str = None): ... + @staticmethod + def send(driver: str | None = None): ... diff --git a/fastapi_startkit/src/fastapi_startkit/facades/Notification.pyi b/fastapi_startkit/src/fastapi_startkit/facades/Notification.pyi index 6066ffdf..d34be724 100644 --- a/fastapi_startkit/src/fastapi_startkit/facades/Notification.pyi +++ b/fastapi_startkit/src/fastapi_startkit/facades/Notification.pyi @@ -1,16 +1,20 @@ -from typing import Any, TYPE_CHECKING +from typing import Any -if TYPE_CHECKING: - from ..notification import Notification as NotificationObject +NotificationObject = Any class Notification: """Notification handler facade, which handle sending/queuing notifications anonymously or to notifiables through different channels.""" + @staticmethod def add_driver(name: str, driver: str): ... + @staticmethod def get_driver(name: str) -> Any: ... + @staticmethod def set_configuration(config: dict) -> "Notification": ... + @staticmethod def get_config_options(driver: str) -> dict: ... + @staticmethod def send( notifiables: list, notification: "NotificationObject", @@ -20,6 +24,7 @@ class Notification: ) -> Any: """Send the given notification to the given notifiables.""" ... + @staticmethod def route(driver: str, route: str) -> Any: """Specify how to send a notification to an anonymous notifiable.""" ... diff --git a/fastapi_startkit/src/fastapi_startkit/facades/Queue.pyi b/fastapi_startkit/src/fastapi_startkit/facades/Queue.pyi index 4c1bd270..83544436 100644 --- a/fastapi_startkit/src/fastapi_startkit/facades/Queue.pyi +++ b/fastapi_startkit/src/fastapi_startkit/facades/Queue.pyi @@ -1,10 +1,17 @@ from typing import Any class Queue: + @staticmethod def add_driver(name: str, driver: str): ... + @staticmethod def get_driver(name: str) -> Any: ... + @staticmethod def set_configuration(config: dict) -> "Queue": ... + @staticmethod def get_config_options(driver: str) -> dict: ... + @staticmethod def push(*jobs, **options) -> None: ... + @staticmethod def consume(options: dict) -> Any: ... + @staticmethod def retry(options: dict) -> Any: ... diff --git a/fastapi_startkit/src/fastapi_startkit/facades/Request.pyi b/fastapi_startkit/src/fastapi_startkit/facades/Request.pyi index 284b9cf4..c6c6617e 100644 --- a/fastapi_startkit/src/fastapi_startkit/facades/Request.pyi +++ b/fastapi_startkit/src/fastapi_startkit/facades/Request.pyi @@ -1,88 +1,111 @@ -from typing import TYPE_CHECKING, List, Any +from typing import Any -if TYPE_CHECKING: - from ..routes import Route +Route = Any class Request: """Request facade.""" + @staticmethod def load(): """Load request from environment.""" ... - def load_params(params: dict = None): + @staticmethod + def load_params(params: dict | None = None): """Load request parameters.""" ... + @staticmethod def param(param: str, default: str = "") -> str: """Get query string parameter from request.""" ... + @staticmethod def get_route() -> "Route": """Get Route associated to request if any.""" ... + @staticmethod def get_path() -> str: """Get request path (read from PATH_INFO) environment variable without eventual query string parameters.""" ... + @staticmethod def get_path_with_query() -> str: """Get request path (read from PATH_INFO) environment variable with eventual query string parameters.""" ... + @staticmethod def get_back_path() -> str: """Get previous request path if it has been defined as '__back' input.""" ... + @staticmethod def get_request_method() -> str: """Get request method (read from REQUEST_METHOD environment variable).""" ... + @staticmethod def input(name: str, default: str = "") -> str: """Get a specific request input value with the given name. If the value does not exist in the request return the default value.""" ... - def cookie(name: str, value: str = None, **options) -> None: + @staticmethod + def cookie(name: str, value: str | None = None, **options) -> None: """If no value provided, read the cookie value with the given name from the request. Else create a cookie in the request with the given name and value. Some options can be passed when creating cookie, refer to CookieJar class.""" ... + @staticmethod def delete_cookie(name: str) -> "Request": """Delete cookie with the given name from the request.""" ... - def header(name: str, value: str = None) -> "str|None": + @staticmethod + def header(name: str, value: str | None = None) -> "str|None": """If no value provided, read the header value with the given name from the request. Else add a header in the request with the given name and value.""" ... + @staticmethod def all() -> dict: """Get all inputs from the request as a dictionary.""" ... - def only(*inputs: List[str]) -> dict: + @staticmethod + def only(*inputs: str) -> dict: """Get only the given inputs from the request as a dictionary.""" ... + @staticmethod def old(key: str): """Get value from session for the given key.""" ... + @staticmethod def is_not_safe() -> bool: """Check if the current request is considered 'safe', meaning that the request method is GET, OPTIONS or HEAD.""" ... + @staticmethod def user() -> "None|Any": """Get the current authenticated user if any. LoadUserMiddleware needs to be used for user to be populated in request.""" ... + @staticmethod def set_user(user: Any) -> "Request": """Set the current authenticated user of the request.""" ... + @staticmethod def remove_user() -> "Request": """Log out user of the current request.""" ... + @staticmethod def contains(route: str) -> bool: """Check if current request path match the given URL.""" ... + @staticmethod def get_subdomain(exclude_www: bool = True) -> "None|str": """Get the request subdomain if subdomains are enabled.""" ... + @staticmethod def get_host() -> str: """Get the request host (from HTTP_HOST environment variable).""" ... + @staticmethod def activate_subdomains(): """Enable subdomains for this request.""" ... + @staticmethod def is_ajax() -> bool: """Check if the current request is an AJAX request.""" ... diff --git a/fastapi_startkit/src/fastapi_startkit/facades/Response.pyi b/fastapi_startkit/src/fastapi_startkit/facades/Response.pyi index cb237739..6b305679 100644 --- a/fastapi_startkit/src/fastapi_startkit/facades/Response.pyi +++ b/fastapi_startkit/src/fastapi_startkit/facades/Response.pyi @@ -3,56 +3,72 @@ from typing import Any class Response: """Response facade.""" + @staticmethod def json(payload: Any, status: int = 200) -> bytes: """Set the response as a JSON response.""" ... + @staticmethod def make_headers(content_type: str = "text/html; charset=utf-8") -> None: """Recompute Content-Length of the response after modyifing it.""" ... - def header(name: str, value: str = None) -> "None|str": + @staticmethod + def header(name: str, value: str | None = None) -> "None|str": """Get response header for the given name if no value provided or add headers to response.""" ... - def get_headers(self) -> list: + @staticmethod + def get_headers() -> list: """Get all response headers.""" ... - def cookie(name: str, value: str = None, **options) -> "None|str": + @staticmethod + def cookie(name: str, value: str | None = None, **options) -> "None|str": """Get response cookie for the given name if no value provided or add cookie to the response with the given name, value and options.""" ... + @staticmethod def delete_cookie(name: str) -> "Response": """Delete the cookie with the given name from the response.""" ... - def get_response_content(self) -> bytes: + @staticmethod + def get_response_content() -> bytes: """Get response content.""" ... + @staticmethod def status(status: "str|int") -> "Response": """Set HTTP status code of the response.""" ... + @staticmethod def is_status(code: int) -> bool: """Check if response has the given status code.""" ... - def get_status_code(self) -> str: + @staticmethod + def get_status_code() -> str: """Gets the HTTP status code of the response as a human string, like "200 OK".""" ... - def get_status(self): ... - def data(self) -> bytes: + @staticmethod + def get_status(): ... + @staticmethod + def data() -> bytes: """Get the response content as bytes.""" ... - def converted_data(self) -> "str|bytes": + @staticmethod + def converted_data() -> "str|bytes": """Get the response content as string or bytes so that the WSGI server handles it.""" ... + @staticmethod def view(view: Any, status: int = 200) -> "bytes|Response": """Set the response as a string or view.""" ... - def back(self) -> "Response": + @staticmethod + def back() -> "Response": """Set the response as a redirect response back to previous path defined from the request.""" ... + @staticmethod def redirect( - location: str = None, - name: str = None, + location: str | None = None, + name: str | None = None, params: dict = {}, - url: str = None, + url: str | None = None, status: int = 302, ) -> "Response": """Set the response as a redirect response. The redirection location can be defined @@ -60,9 +76,11 @@ class Response: be provided.""" ... - def to_bytes(self) -> "bytes": + @staticmethod + def to_bytes() -> "bytes": """Converts the response to bytes.""" ... + @staticmethod def download(name: str, location: str, force: bool = False) -> "Response": """Set the response as a file download response.""" ... diff --git a/fastapi_startkit/src/fastapi_startkit/facades/Session.pyi b/fastapi_startkit/src/fastapi_startkit/facades/Session.pyi index 297575f8..26c7ad2b 100644 --- a/fastapi_startkit/src/fastapi_startkit/facades/Session.pyi +++ b/fastapi_startkit/src/fastapi_startkit/facades/Session.pyi @@ -3,57 +3,75 @@ from typing import Any class Session: """Session facade.""" + @staticmethod def add_driver(name: str, driver: Any) -> None: """Register a new session driver with the given name.""" ... + @staticmethod def driver(driver: str) -> Any: """Get a registered session driver with the given name.""" ... + @staticmethod def set_configuration(config: dict) -> "Session": """Set session driver options.""" ... - def get_driver(name: str = None) -> Any: + @staticmethod + def get_driver(name: str | None = None) -> Any: """Get the default session driver or the driver with the given name.""" ... - def get_config_options(driver: str = None) -> dict: + @staticmethod + def get_config_options(driver: str | None = None) -> dict: """Get the options of the default session driver or of the driver with the given name.""" ... - def start(driver: str = None) -> "Session": + @staticmethod + def start(driver: str | None = None) -> "Session": """Initialize session.""" ... - def get_data(self) -> dict: + @staticmethod + def get_data() -> dict: """Get all session data.""" ... - def save(driver: str = None) -> None: + @staticmethod + def save(driver: str | None = None) -> None: """Save session data for the default session driver or the given named driver.""" ... + @staticmethod def set(key: str, value: Any) -> None: """Save value in default session.""" ... + @staticmethod def increment(key: str, count: int = 1) -> None: """Increment session key with given count.""" ... + @staticmethod def decrement(key: str, count: int = 1) -> None: """Decrement session key with given count.""" ... + @staticmethod def has(key: str) -> bool: """Check if key is present in default session.""" ... + @staticmethod def get(key: str) -> Any: """Get value of the given key in default session.""" ... + @staticmethod def pull(key: str) -> Any: """Get and remove value for the given key in session.""" ... - def flush(self) -> None: + @staticmethod + def flush() -> None: """Delete all keys from session.""" ... + @staticmethod def delete(key: str) -> "None|Any": """Delete the given key from session.""" ... + @staticmethod def flash(key: str, value: Any) -> None: """Save temporary value into session.""" ... - def all(self) -> dict: + @staticmethod + def all() -> dict: """Get all session data.""" ... diff --git a/fastapi_startkit/src/fastapi_startkit/facades/View.pyi b/fastapi_startkit/src/fastapi_startkit/facades/View.pyi index 0f7e6640..58b22d02 100644 --- a/fastapi_startkit/src/fastapi_startkit/facades/View.pyi +++ b/fastapi_startkit/src/fastapi_startkit/facades/View.pyi @@ -4,51 +4,68 @@ from jinja2 import PackageLoader, BaseLoader class View: """View facade.""" + @staticmethod def render(template: str, dictionary: dict = {}) -> "View": """Render the given template name with the given context as string.""" ... - def get_content(self) -> str: + @staticmethod + def get_content() -> str: """Get the rendered content as string.""" ... - def hydrate_from_composers(self): + @staticmethod + def hydrate_from_composers(): """Add data into the view from specified composers.""" ... + @staticmethod def composer(composer_name: str, dictionary: dict) -> "View": """Add/Update composer with the given name and data.""" ... + @staticmethod def share(dictionary: dict) -> "View": """Share data to all templates.""" ... + @staticmethod def exists(template: str) -> bool: """Check if a template with the given name exists.""" ... - def add_location(template_location: str, loader: "BaseLoader" = PackageLoader): + @staticmethod + def add_location(template_location: str, loader: type[BaseLoader] = PackageLoader): """Add location directory from which view templates can be loaded. The Jinja2 loader type can be specified.""" ... + @staticmethod def add_namespaced_location(namespace: str, template_location: str): """Add namespaced location directory from which view templates can be loaded.""" ... + @staticmethod def add_from_package(package_name: str, path_in_package: str): ... + @staticmethod def filter(name: str, function: Callable): """Add filter functions to views with the given name.""" ... + @staticmethod def add_extension(extension: str) -> "View": """Register Jinja2 extension to views.""" ... + @staticmethod def load_template(template: str): """Private method for loading all the locations into the current environment.""" ... - def get_current_loaders(self): + @staticmethod + def get_current_loaders(): """Get all enabled Jinja2 loaders.""" ... + @staticmethod def set_separator(token: str) -> "View": """Change separator for view names (default is /).""" ... + @staticmethod def set_file_extension(extension: str) -> "View": """Change file view extension (default is .html).""" ... - def get_response(self) -> str: + @staticmethod + def get_response() -> str: """Get the rendered content as string.""" ... + @staticmethod def test(key: str, obj: Any) -> "View": ...