diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..c5955ea --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,8 @@ +{ + "permissions": { + "allow": [ + "WebFetch(domain:omz-software.com)" + ], + "deny": [] + } +} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 16bb8b4..f50d5e0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,4 +27,4 @@ jobs: run: uv run mypy - name: Check code formatting with black - run: uv run black --check + run: uv run black --check --diff . diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..076dda8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,70 @@ +Here are the key best practices for writing Python type stub libraries: + +## Structure and Organization + +**Follow the source layout**: Mirror the structure of the runtime library you're stubbing. If the original package is `mylib/module.py`, your stub should be `mylib/module.pyi`. + +**Use `.pyi` extension**: Type stubs should always use the `.pyi` extension, never `.py`. + +**Include `py.typed` marker**: For stub packages, include an empty `py.typed` file in the package root to indicate it contains type information. + +## Type Annotations + +**Be precise but practical**: Use the most specific types that accurately represent the API without being overly complex. Prefer `list[str]` over `List[str]` (Python 3.9+). + +**Use `typing_extensions` when needed**: Import from `typing_extensions` for newer typing features that need to work with older Python versions. + +**Leverage generics appropriately**: Use `TypeVar` for generic functions and classes, but don't over-generify simple APIs. + +```python +from typing import TypeVar, Generic +T = TypeVar('T') + +class Container(Generic[T]): + def get(self) -> T: ... +``` + +## Stub Content Guidelines + +**Omit implementation details**: Stubs should only contain signatures, not implementations. Use `...` (Ellipsis) for function bodies. + +**Include all public APIs**: Cover all publicly documented functions, classes, methods, and constants. + +**Use `@overload` for complex signatures**: When functions accept different parameter combinations that return different types. + +```python +from typing import overload + +@overload +def process(data: str) -> str: ... +@overload +def process(data: int) -> int: ... +``` + +**Handle optional parameters correctly**: Use proper defaults and Optional types. + +## Documentation and Metadata + +**Include docstrings sparingly**: Only add docstrings if they provide type-relevant information not captured in the signature. + +**Version compatibility**: Use `if TYPE_CHECKING:` blocks and version checks when APIs differ across Python versions. + +**Mark incomplete stubs**: Use `# type: ignore` or add comments explaining limitations for partially-stubbed modules. + +## Distribution and Packaging + +**Follow naming conventions**: Stub-only packages should be named `types-{package}` (e.g., `types-requests`). + +**Specify supported versions**: Clearly document which versions of the runtime library your stubs support. + +**Keep stubs minimal**: Don't include runtime code in stub packages - they should be purely type information. + +## Testing and Validation + +**Test with mypy**: Run mypy against code that uses your stubs to ensure they work correctly. + +**Validate completeness**: Use tools like `stubtest` (part of mypy) to verify stubs match the runtime API. + +**Check multiple Python versions**: Ensure stubs work across the Python versions you claim to support. + +The key is balancing precision with usability - your stubs should provide helpful type checking without being so complex that they're hard to maintain or understand. diff --git a/README.md b/README.md index 7c423d6..0253eb9 100755 --- a/README.md +++ b/README.md @@ -6,41 +6,47 @@ [![CI](https://github.com/hbmartin/pythonista-stubs/actions/workflows/ci.yml/badge.svg)](https://github.com/hbmartin/pythonista-stubs/actions/workflows/ci.yml) - -Stubs for the [Pythonista iOS API](http://omz-software.com/pythonista/docs/ios/). This allows for better error detection and IDE / editor autocomplete. +Stubs for the [Pythonista iOS API](https://omz-software.com/pythonista/lab/). This allows for better error detection and IDE / editor autocomplete. ## Installation and Usage -``` +Install using your preferred package manager: + +```bash +# Using uv (recommended) uv add pythonista-stubs + +# Using pip +pip install pythonista-stubs ``` + You can now develop from your computer editor with proper typing and completions. ## API Coverage -| Module | Status | -| ----------- |--------| -| appex | ✔ | -| canvas | WIP | -| cb | [WIP](https://github.com/hbmartin/pythonista-stubs/issues/7) | -| clipboard | ✔ | -| console | ✔ | -| contacts | ✔ | -| dialogs | ✔ | -| editor | ✔ | -| keychain | ✔ | -| linguistictagger | ✔ | -| location | ✔ | -| motion | ✔ | -| notification | ✔ | -| objc_util | [WIP](https://github.com/hbmartin/pythonista-stubs/issues/7) | -| photos | ✔ | -| reminders | ✔ | -| scene | [✘](https://github.com/hbmartin/pythonista-stubs/issues/9) | -| sound | ✔ | -| speech | ✔ | -| twitter | ✘ | -| ui | [WIP](https://github.com/hbmartin/pythonista-stubs/issues/6) | +| Module | Status | Documentation | +| ----------- |--------|---------------| +| appex | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/appex.html) | +| canvas | WIP | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/canvas.html) | +| cb | [WIP](https://github.com/hbmartin/pythonista-stubs/issues/7) | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/cb.html) | +| clipboard | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/clipboard.html) | +| console | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/console.html) | +| contacts | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/contacts.html) | +| dialogs | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/dialogs.html) | +| editor | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/editor.html) | +| keychain | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/keychain.html) | +| linguistictagger | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/linguistictagger.html) | +| location | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/location.html) | +| motion | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/motion.html) | +| notification | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/notification.html) | +| objc_util | [WIP](https://github.com/hbmartin/pythonista-stubs/issues/7) | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/objc_util.html) | +| photos | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/photos.html) | +| reminders | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/reminders.html) | +| scene | [✘](https://github.com/hbmartin/pythonista-stubs/issues/9) | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/scene.html) | +| sound | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/sound.html) | +| speech | ✔ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/speech.html) | +| twitter | ✘ | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/twitter.html) | +| ui | [WIP](https://github.com/hbmartin/pythonista-stubs/issues/6) | [API Docs](https://omz-software.com/pythonista/docs-3.4/py3/ios/ui.html) | ## Built With @@ -53,28 +59,22 @@ You can now develop from your computer editor with proper typing and completions * [PEP 561 -- Distributing and Packaging Type Information](https://www.python.org/dev/peps/pep-0561/) * [PEP 3107 -- Function Annotations](https://www.python.org/dev/peps/pep-3107/) +## Troubleshooting + +### Type Checker Not Finding Stubs +- **VSCode**: Ensure the Python extension is using the correct interpreter where pythonista-stubs is installed +- **PyCharm**: Check that the stub package appears in your project's external libraries +- **mypy**: Make sure mypy can find the stubs in your Python path + +### Import Errors in IDE +- Verify pythonista-stubs is installed in the same environment as your project +- Try restarting your IDE after installation +- Check that your IDE is using the correct Python interpreter + ## Contributing Please [file a bug report](https://github.com/hbmartin/pythonista-stubs/issues) for any issues you find. Even more excellent than a good bug report is a fix for a bug, or the implementation of a much-needed stub. We'd love to have your contributions. -### Conventions - -* long functions and methods should be split up with one argument per line -* all function bodies should be empty -* prefer ``...`` over ``pass`` -* prefer ``...`` on the same line as the class/function signature -* avoid vertical whitespace between consecutive module-level functions, names, or methods and fields within a single class -* use a single blank line between top-level class definitions -* do not use docstrings -* use variable annotations instead of type comments -* for arguments with a type and a default, use spaces around the `=` -* use `float` instead of `Union[int, float]` -* avoid Union return types: https://github.com/python/mypy/issues/1693 -* imports in stubs are considered private unless they use the form ``from library import name as name`` -* avoid using the `Any` type when possible -* type variables and aliases for legibility reasons should be prefixed with an underscore to make it obvious to the reader they are not part of the stubbed API. -* these conventions derived from [typeshed](https://github.com/python/typeshed/blob/master/CONTRIBUTING.md#conventions) - ### Code of Conduct Everyone participating in this community is expected to treat other people with respect and more generally to follow the guidelines articulated in the [Python Community Code of Conduct](https://www.python.org/psf/codeofconduct/). @@ -91,4 +91,4 @@ This is not an official project and is not associated with omz:software ## License -[Apache License 2.0](LICENSE.txt) +[Apache License 2.0](LICENSE) diff --git a/stubs/_cb.pyi b/stubs/_cb.pyi index 0d8240f..34dfbda 100644 --- a/stubs/_cb.pyi +++ b/stubs/_cb.pyi @@ -1,35 +1,32 @@ # Created on July, 07 2025 by o-murphy -""" -pythonista `_cb` module type annotations +"""pythonista `_cb` module type annotations according to [pythonista.cb docs](https://omz-software.com/pythonista/docs/ios/cb.html) and references to pythonista built-in `_cb` module help >>> import _cb >>> help(_cb) """ -from typing import Optional, List - __all__ = ( - "CM_STATE_UNKNOWN", - "CM_STATE_RESETTING", - "CM_STATE_UNSUPPORTED", - "CM_STATE_UNAUTHORIZED", - "CM_STATE_POWERED_OFF", - "CM_STATE_POWERED_ON", - "CH_PROP_BROADCAST", - "CH_PROP_READ", - "CH_PROP_WRITE_WITHOUT_RESPONSE", - "CH_PROP_WRITE", - "CH_PROP_NOTIFY", - "CH_PROP_INDICATE", "CH_PROP_AUTHENTICATED_SIGNED_WRITES", + "CH_PROP_BROADCAST", "CH_PROP_EXTENDED_PROPERTIES", - "CH_PROP_NOTIFY_ENCRYPTION_REQUIRED", + "CH_PROP_INDICATE", "CH_PROP_INDICATE_ENCRYPTION_REQUIRED", + "CH_PROP_NOTIFY", + "CH_PROP_NOTIFY_ENCRYPTION_REQUIRED", + "CH_PROP_READ", + "CH_PROP_WRITE", + "CH_PROP_WRITE_WITHOUT_RESPONSE", + "CM_STATE_POWERED_OFF", + "CM_STATE_POWERED_ON", + "CM_STATE_RESETTING", + "CM_STATE_UNAUTHORIZED", + "CM_STATE_UNKNOWN", + "CM_STATE_UNSUPPORTED", + "CentralManager", "Characteristic", - "Service", "Peripheral", - "CentralManager", + "Service", ) CM_STATE_UNKNOWN: int = 0 @@ -52,29 +49,34 @@ CH_PROP_INDICATE_ENCRYPTION_REQUIRED: int = 512 class Characteristic: properties: int - value: Optional[bytes] + value: bytes | None uuid: str # hex notifying: bool class Service: - characteristics: List[Characteristic] + characteristics: list[Characteristic] primary: bool uuid: str # hex class Peripheral: manufacturer_data: bytes - name: Optional[str] + name: str | None uuid: str # hex state: int - services: List[Service] + services: list[Service] def discover_services(self) -> None: ... def discover_characteristics(self, service: Service) -> None: ... def set_notify_value( - self, characteristic: Characteristic, flag: bool = True + self, + characteristic: Characteristic, + flag: bool = True, ) -> None: ... def write_characteristic_value( - self, characteristic, data, with_response + self, + characteristic: Characteristic, + data: bytes, + with_response: bool, ) -> None: ... def read_characteristic_value(self, characteristic: Characteristic) -> None: ... @@ -89,15 +91,21 @@ class CentralManager: def did_discover_peripheral(self, p: Peripheral) -> None: ... def did_connect_peripheral(self, p: Peripheral) -> None: ... def did_fail_to_connect_peripheral( - self, p: Peripheral, error: Optional[str] + self, + p: Peripheral, + error: str | None, ) -> None: ... def did_disconnect_peripheral( - self, p: Peripheral, error: Optional[str] + self, + p: Peripheral, + error: str | None, ) -> None: ... - def did_discover_services(self, p: Peripheral, error: Optional[str]) -> None: ... + def did_discover_services(self, p: Peripheral, error: str | None) -> None: ... def did_discover_characteristics( - self, s: Service, error: Optional[str] + self, + s: Service, + error: str | None, ) -> None: ... - def did_write_value(self, c: Characteristic, error: Optional[str]) -> None: ... - def did_update_value(self, c: Characteristic, error: Optional[str]) -> None: ... + def did_write_value(self, c: Characteristic, error: str | None) -> None: ... + def did_update_value(self, c: Characteristic, error: str | None) -> None: ... def did_update_state(self) -> None: ... diff --git a/stubs/pythonista_stubs/appex.pyi b/stubs/pythonista_stubs/appex.pyi index 310e54b..9257f67 100644 --- a/stubs/pythonista_stubs/appex.pyi +++ b/stubs/pythonista_stubs/appex.pyi @@ -2,7 +2,7 @@ functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import Any, Literal, TypeAlias, overload +from typing import Any, Literal, overload from PIL.Image import Image as PILImage @@ -45,56 +45,28 @@ def get_attachments(uti: str = "public.data") -> list[Any]: uti (str, optional): The type identifier to match. Defaults to 'public.data'. Returns: - List[Any]: A list of attachments. + list[Any]: A list of attachments. """ ... -_ImageType: TypeAlias = Literal["ui", "pil"] - @overload def get_images() -> list[PILImage]: ... @overload def get_images(image_type: Literal["pil"]) -> list[PILImage]: ... @overload def get_images(image_type: Literal["ui"]) -> list[UIImage]: ... -def get_images(image_type: _ImageType = "pil") -> list[UIImage | PILImage]: - """Return a list of images in the input of the share sheet. - - Args: - image_type (Literal['ui', 'pil'], optional): The desired image type. - Defaults to 'pil'. - - Returns: - List[Union[ui.Image, PIL.Image.Image]]: A list of images. - - """ - ... - @overload def get_image() -> PILImage | None: ... @overload def get_image(image_type: Literal["pil"]) -> PILImage | None: ... @overload def get_image(image_type: Literal["ui"]) -> UIImage | None: ... -def get_image(image_type: _ImageType = "pil") -> UIImage | PILImage | None: - """Return the first image in the input of the share sheet. - - Args: - image_type (Literal['ui', 'pil'], optional): The desired image type. - Defaults to 'pil'. - - Returns: - Optional[Union[ui.Image, PIL.Image.Image]]: The first image, or None. - - """ - ... - def get_image_data() -> bytes | None: """Return raw image data for the first image in the share sheet's input. Returns: - Optional[bytes]: The raw image data as a byte string, or None. + bytes | None: The raw image data as a byte string, or None. """ ... @@ -103,7 +75,7 @@ def get_images_data() -> list[bytes]: """Return raw image data for all images in the share sheet's input. Returns: - List[bytes]: A list of byte strings, or an empty list. + list[bytes]: A list of byte strings, or an empty list. """ ... @@ -112,7 +84,7 @@ def get_text() -> str | None: """Return text input of the share sheet. Returns: - Optional[str]: The text as a unicode string, or None. + str | None: The text as a unicode string, or None. """ ... @@ -121,7 +93,7 @@ def get_urls() -> list[str]: """Return a list of URLs in the share sheet's input. Returns: - List[str]: A list of URLs, or an empty list. + list[str]: A list of URLs, or an empty list. """ ... @@ -130,7 +102,7 @@ def get_url() -> str | None: """Return the first URL in the share sheet's input. Returns: - Optional[str]: The first URL, or None. + str | None: The first URL, or None. """ ... @@ -139,7 +111,7 @@ def get_file_paths() -> list[str]: """Return a list of file paths in the share sheet's input. Returns: - List[str]: A list of file paths, or an empty list. + list[str]: A list of file paths, or an empty list. """ ... @@ -148,7 +120,7 @@ def get_file_path() -> str | None: """Return the first file path in the share sheet's input. Returns: - Optional[str]: The first file path, or None. + str | None: The first file path, or None. """ ... @@ -157,7 +129,7 @@ def get_vcards() -> list[str]: """Return a list of VCard records in the share sheet's input. Returns: - List[str]: A list of VCard records as strings, or an empty list. + list[str]: A list of VCard records as strings, or an empty list. """ ... @@ -166,7 +138,7 @@ def get_vcard() -> str | None: """Return the first VCard record in the share sheet's input. Returns: - Optional[str]: The first VCard record as a string, or None. + str | None: The first VCard record as a string, or None. """ ... @@ -176,7 +148,7 @@ def get_web_page_info() -> dict[str, str]: currently loaded page. Returns: - Dict[str, str]: A dictionary with page information, or an empty dict. + dict[str, str]: A dictionary with page information, or an empty dict. """ ... @@ -188,7 +160,7 @@ def get_widget_view() -> View | None: """Return the view that is currently shown in the Today widget. Returns: - Optional[ui.View]: The current view, or None. + ui.View | None: The current view, or None. """ ... @@ -197,7 +169,7 @@ def set_widget_view(view: View | None) -> None: """Set the widget's view to a ui.View object. Args: - view (Optional[ui.View]): The view to set, or None to remove the current view. + view (ui.View | None): The view to set, or None to remove the current view. """ ... diff --git a/stubs/pythonista_stubs/canvas.pyi b/stubs/pythonista_stubs/canvas.pyi index 3b32039..9e4e740 100644 --- a/stubs/pythonista_stubs/canvas.pyi +++ b/stubs/pythonista_stubs/canvas.pyi @@ -1,10 +1,7 @@ -""" -This is a stub file for the `canvas` module, providing type hints for its +"""This is a stub file for the `canvas` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import Optional, Tuple - # ----------------------------------------------------------------------------- # Blend Modes (Constants) # ----------------------------------------------------------------------------- @@ -43,7 +40,7 @@ def clear() -> None: """Clears the canvas.""" ... -def get_size() -> Tuple[float, float]: +def get_size() -> tuple[float, float]: """Return the size of the canvas as a tuple of width and height.""" ... @@ -90,7 +87,12 @@ def set_stroke_color(r: float, g: float, b: float, a: float = 1.0) -> None: # Vector Drawing Functions def add_curve( - cp1x: float, cp1y: float, cp2x: float, cp2y: float, x: float, y: float + cp1x: float, + cp1y: float, + cp2x: float, + cp2y: float, + x: float, + y: float, ) -> None: """Adds a cubic bezier curve to the current path.""" ... @@ -185,8 +187,8 @@ def draw_image( image_name: str, x: float, y: float, - width: Optional[float] = None, - height: Optional[float] = None, + width: float | None = None, + height: float | None = None, ) -> None: """Draws the image with the given name in a rectangle.""" ... @@ -195,11 +197,11 @@ def draw_clipboard(x: float, y: float, width: float, height: float) -> None: """Draw the image in the clipboard in a given rectangle.""" ... -def get_clipboard_size() -> Tuple[float, float]: +def get_clipboard_size() -> tuple[float, float]: """Return the size of the image in the clipboard in points.""" ... -def get_image_size(image_name: str) -> Tuple[float, float]: +def get_image_size(image_name: str) -> tuple[float, float]: """Returns the size of the image with the given name in points.""" ... @@ -215,7 +217,9 @@ def draw_text( ... def get_text_size( - text: str, font_name: str = "Helvetica", font_size: float = 16.0 -) -> Tuple[float, float]: + text: str, + font_name: str = "Helvetica", + font_size: float = 16.0, +) -> tuple[float, float]: """Get the size of a line of text as a tuple of (width, height).""" ... diff --git a/stubs/pythonista_stubs/cb.pyi b/stubs/pythonista_stubs/cb.pyi index 7b85722..7b40215 100644 --- a/stubs/pythonista_stubs/cb.pyi +++ b/stubs/pythonista_stubs/cb.pyi @@ -1,89 +1,86 @@ -""" -`pythonista.cb` module type annotations +"""`pythonista.cb` module type annotations according to [pythonista.cb docs](https://omz-software.com/pythonista/docs/ios/cb.html) """ -from typing import Optional, Protocol -from _cb import ( - CM_STATE_UNKNOWN, - CM_STATE_RESETTING, - CM_STATE_UNSUPPORTED, - CM_STATE_UNAUTHORIZED, - CM_STATE_POWERED_OFF, - CM_STATE_POWERED_ON, - CH_PROP_BROADCAST, - CH_PROP_READ, - CH_PROP_WRITE_WITHOUT_RESPONSE, - CH_PROP_WRITE, - CH_PROP_NOTIFY, - CH_PROP_INDICATE, +from typing import Protocol + +from _cb import ( # type: ignore[import-not-found] CH_PROP_AUTHENTICATED_SIGNED_WRITES, + CH_PROP_BROADCAST, CH_PROP_EXTENDED_PROPERTIES, - CH_PROP_NOTIFY_ENCRYPTION_REQUIRED, + CH_PROP_INDICATE, CH_PROP_INDICATE_ENCRYPTION_REQUIRED, + CH_PROP_NOTIFY, + CH_PROP_NOTIFY_ENCRYPTION_REQUIRED, + CH_PROP_READ, + CH_PROP_WRITE, + CH_PROP_WRITE_WITHOUT_RESPONSE, + CM_STATE_POWERED_OFF, + CM_STATE_POWERED_ON, + CM_STATE_RESETTING, + CM_STATE_UNAUTHORIZED, + CM_STATE_UNKNOWN, + CM_STATE_UNSUPPORTED, + CentralManager, Characteristic, - Service, Peripheral, - CentralManager, + Service, ) __all__ = ( - "CM_STATE_UNKNOWN", - "CM_STATE_RESETTING", - "CM_STATE_UNSUPPORTED", - "CM_STATE_UNAUTHORIZED", - "CM_STATE_POWERED_OFF", - "CM_STATE_POWERED_ON", - "CH_PROP_BROADCAST", - "CH_PROP_READ", - "CH_PROP_WRITE_WITHOUT_RESPONSE", - "CH_PROP_WRITE", - "CH_PROP_NOTIFY", - "CH_PROP_INDICATE", "CH_PROP_AUTHENTICATED_SIGNED_WRITES", + "CH_PROP_BROADCAST", "CH_PROP_EXTENDED_PROPERTIES", - "CH_PROP_NOTIFY_ENCRYPTION_REQUIRED", + "CH_PROP_INDICATE", "CH_PROP_INDICATE_ENCRYPTION_REQUIRED", + "CH_PROP_NOTIFY", + "CH_PROP_NOTIFY_ENCRYPTION_REQUIRED", + "CH_PROP_READ", + "CH_PROP_WRITE", + "CH_PROP_WRITE_WITHOUT_RESPONSE", + "CM_STATE_POWERED_OFF", + "CM_STATE_POWERED_ON", + "CM_STATE_RESETTING", + "CM_STATE_UNAUTHORIZED", + "CM_STATE_UNKNOWN", + "CM_STATE_UNSUPPORTED", + "CentralManager", "Characteristic", - "Service", "Peripheral", - "CentralManager", - "SharedCentralManager", - "shared_manager", - "set_central_delegate", - "set_verbose", - "scan_for_peripherals", - "stop_scan", - "connect_peripheral", + "Service", "cancel_peripheral_connection", + "connect_peripheral", "get_state", "reset", + "scan_for_peripherals", + "set_central_delegate", + "set_verbose", + "stop_scan", ) class _CentralManagerDelegate(Protocol): def did_discover_peripheral(self, p: Peripheral) -> None: ... def did_connect_peripheral(self, p: Peripheral) -> None: ... def did_fail_to_connect_peripheral( - self, p: Peripheral, error: Optional[str] + self, + p: Peripheral, + error: str | None, ) -> None: ... def did_disconnect_peripheral( - self, p: Peripheral, error: Optional[str] + self, + p: Peripheral, + error: str | None, ) -> None: ... - def did_discover_services(self, p: Peripheral, error: Optional[str]) -> None: ... + def did_discover_services(self, p: Peripheral, error: str | None) -> None: ... def did_discover_characteristics( - self, s: Service, error: Optional[str] + self, + s: Service, + error: str | None, ) -> None: ... - def did_write_value(self, c: Characteristic, error: Optional[str]) -> None: ... - def did_update_value(self, c: Characteristic, error: Optional[str]) -> None: ... + def did_write_value(self, c: Characteristic, error: str | None) -> None: ... + def did_update_value(self, c: Characteristic, error: str | None) -> None: ... def did_update_state(self) -> None: ... -class SharedCentralManager(CentralManager): - delegate: Optional[_CentralManagerDelegate] = None - verbose: bool = False - def verbose_log(self): ... - -shared_manager: Optional[SharedCentralManager] = SharedCentralManager() - def set_central_delegate(delegate: _CentralManagerDelegate) -> None: ... def set_verbose(flag: bool) -> None: ... def scan_for_peripherals() -> None: ... diff --git a/stubs/pythonista_stubs/clipboard.pyi b/stubs/pythonista_stubs/clipboard.pyi index 00f120f..83bcce4 100644 --- a/stubs/pythonista_stubs/clipboard.pyi +++ b/stubs/pythonista_stubs/clipboard.pyi @@ -1,35 +1,30 @@ -""" -This is a stub file for the `clipboard` module, providing type hints for its +"""This is a stub file for the `clipboard` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import Optional, Literal, Any +from typing import Literal, TypeAlias -# Assuming 'PIL' is from the Pillow library, which is not part of the standard library -# and might not be available in all Pythonista environments. -# We'll use `Any` as a fallback or assume a type alias exists. -try: - from PIL.Image import Image -except ImportError: - Image: Any # type: ignore[no-redef] +from PIL.Image import Image def get() -> str: - """Returns the clipboard’s content as a Unicode string. + """Returns the clipboard's content as a Unicode string. Returns: str: The content of the clipboard. + """ ... -def set(string: str) -> None: - """Sets the clipboard’s content to a new string. +def set(string: str) -> None: # noqa: A001 + """Sets the clipboard's content to a new string. Args: string (str): The new content for the clipboard. + """ ... -def get_image(idx: int = 0) -> Optional[Image]: +def get_image(idx: int = 0) -> Image | None: """Returns an image from the clipboard. If there are multiple images in the clipboard, the `idx` parameter can be @@ -40,15 +35,18 @@ def get_image(idx: int = 0) -> Optional[Image]: idx (int, optional): The index of the image to retrieve. Defaults to 0. Returns: - Optional[Image]: The image from the clipboard, or None if no image + Image | None: The image from the clipboard, or None if no image was found at the given index. + """ ... -_ImageFormat = Literal["png", "jpeg"] +_ImageFormat: TypeAlias = Literal["png", "jpeg"] def set_image( - image: Image, format: _ImageFormat = "png", jpeg_quality: float = 0.75 + image: Image, + format: _ImageFormat = "png", + jpeg_quality: float = 0.75, ) -> None: """Stores a given PIL Image in the clipboard. @@ -59,5 +57,6 @@ def set_image( jpeg_quality (float, optional): The quality for JPEG format. Should be a float between 0.0 and 1.0. This is ignored if `format` is 'png'. Defaults to 0.75. + """ ... diff --git a/stubs/pythonista_stubs/console.pyi b/stubs/pythonista_stubs/console.pyi index 1c0cd7d..dff14c0 100644 --- a/stubs/pythonista_stubs/console.pyi +++ b/stubs/pythonista_stubs/console.pyi @@ -1,21 +1,22 @@ -""" -This is a stub file for the `console` module, providing type hints for its +"""This is a stub file for the `console` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import Optional, Union, Tuple, Sequence, Literal +from collections.abc import Sequence +from typing import Literal, TypeAlias # These are simple utility functions. def clear() -> None: """Clears the console output.""" ... -def set_font(name: Optional[str] = None, size: Optional[int] = None) -> None: +def set_font(name: str | None = None, size: int | None = None) -> None: """Sets the font and font size for the following output. Args: name (str, optional): The font name (e.g. "Menlo"). If None, reset to default. size (int, optional): The font size. If None, reset to default. + """ ... @@ -28,14 +29,15 @@ def set_color(r: float, g: float, b: float) -> None: r (float): The red component. g (float): The green component. b (float): The blue component. + """ ... -def secure_input(prompt: Optional[str] = None) -> str: +def secure_input(prompt: str | None = None) -> str: """Gets user input with hidden characters. - This function is similar to the built-in raw_input function, but the user’s - input is hidden, so that it’s suitable to request passwords and other + This function is similar to the built-in raw_input function, but the user's + input is hidden, so that it's suitable to request passwords and other sensitive information. Args: @@ -43,14 +45,16 @@ def secure_input(prompt: Optional[str] = None) -> str: Returns: str: The string entered by the user. + """ ... -def show_image(image_path: Union[str]) -> None: +def show_image(image_path: str) -> None: """Shows an image in the console output area. Args: image_path (str or Path): The path to the image file. + """ ... @@ -58,14 +62,14 @@ def alert( title: str, message: str = "", button1: str = "OK", - button2: Optional[str] = None, - button3: Optional[str] = None, + button2: str | None = None, + button3: str | None = None, hide_cancel_button: bool = False, ) -> int: """Shows an alert dialog with up to three custom buttons. The selected button is returned as an integer (button1 => 1, etc.). - Unless `hide_cancel_button` is True, all alert dialogs contain a ‘Cancel’ + Unless `hide_cancel_button` is True, all alert dialogs contain a 'Cancel' button that sends a KeyboardInterrupt. Args: @@ -79,6 +83,7 @@ def alert( Returns: int: The integer corresponding to the selected button (1, 2, or 3). + """ ... @@ -92,7 +97,7 @@ def input_alert( """Shows a dialog with a single text field. The text field can be pre-filled with the `input` parameter. The text - that was entered by the user is returned. The ‘Cancel’ button sends a + that was entered by the user is returned. The 'Cancel' button sends a KeyboardInterrupt. Args: @@ -107,6 +112,7 @@ def input_alert( Returns: str: The text entered by the user. + """ ... @@ -120,7 +126,7 @@ def password_alert( """Shows a dialog with a password entry text field. The password field can be pre-filled with the `password` parameter. - The password that was entered by the user is returned. The ‘Cancel’ button + The password that was entered by the user is returned. The 'Cancel' button sends a KeyboardInterrupt. Args: @@ -135,6 +141,7 @@ def password_alert( Returns: str: The password entered by the user. + """ ... @@ -144,11 +151,11 @@ def login_alert( login: str = "", password: str = "", ok_button_title: str = "OK", -) -> Tuple[str, str]: +) -> tuple[str, str]: """Shows a dialog with two text fields, one for login and one for a password. The text fields can be pre-filled with the `login` and `password` parameters. - Returns a tuple of the entered text as `(login, password)`. The ‘Cancel’ + Returns a tuple of the entered text as `(login, password)`. The 'Cancel' button sends a KeyboardInterrupt. Args: @@ -163,6 +170,7 @@ def login_alert( Returns: Tuple[str, str]: A tuple containing the entered login and password. + """ ... @@ -174,7 +182,7 @@ def hide_activity() -> None: """Hides the animated “network activity indicator” in the status bar.""" ... -_HudIcon = Literal["success", "error"] +_HudIcon: TypeAlias = Literal["success", "error"] def hud_alert(message: str, icon: _HudIcon = "success", duration: float = 1.8) -> None: """Shows a HUD-style alert with the given message. @@ -187,6 +195,7 @@ def hud_alert(message: str, icon: _HudIcon = "success", duration: float = 1.8) - symbol) or 'error' (a cross symbol). Defaults to 'success'. duration (float, optional): How long the alert is shown. It Can be between 0.25 and 5.0 seconds. Defaults to 1.8 seconds. + """ ... @@ -196,6 +205,7 @@ def write_link(title: str, link_url: str) -> None: Args: title (str): The title of the link to display. link_url (str): The URL link should open. + """ ... @@ -203,7 +213,7 @@ def hide_output() -> None: """Hides the console output area with a sliding animation.""" ... -def quicklook(file_path: Union[str, Sequence[str]]) -> None: +def quicklook(file_path: str | Sequence[str]) -> None: """Shows a full-screen preview of local files. The function returns when the preview is dismissed. @@ -211,18 +221,20 @@ def quicklook(file_path: Union[str, Sequence[str]]) -> None: Args: file_path (str or Path or Sequence): The path to a single file, or a sequence of paths to preview multiple files. + """ ... -def open_in(file_path: str) -> Optional[str]: +def open_in(file_path: str) -> str | None: """Shows the iOS “Open in...” menu for the specified file. Args: file_path (str or Path): The path to the file. Returns: - Optional[str]: The bundle identifier of the selected app, or None + str | None: The bundle identifier of the selected app, or None if the menu was cancelled or no app can open the file. + """ ... @@ -232,6 +244,7 @@ def set_idle_timer_disabled(flag: bool) -> None: Args: flag (bool): If True, the idle timer is disabled (a device won't go to sleep). If False, the idle timer is re-enabled. + """ ... @@ -240,5 +253,6 @@ def is_in_background() -> bool: Returns: bool: True if the app is in the background, False otherwise. + """ ... diff --git a/stubs/pythonista_stubs/contacts.pyi b/stubs/pythonista_stubs/contacts.pyi index e9b8d96..bf0d299 100644 --- a/stubs/pythonista_stubs/contacts.pyi +++ b/stubs/pythonista_stubs/contacts.pyi @@ -1,10 +1,8 @@ -""" -This is a stub file for the `contacts` module, providing type hints for its +"""This is a stub file for the `contacts` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ import datetime -from typing import Dict, List, Optional, Tuple # ----------------------------------------------------------------------------- # Constants for multi-value attributes @@ -43,29 +41,29 @@ COUNTRY_CODE: str = ... class Person: """Person objects represent people in the address book.""" - address: List[Tuple[str, Dict[str, str]]] + address: list[tuple[str, dict[str, str]]] """Street address(es). The inner dictionary uses keys from the constants section (e.g., STREET, CITY). """ - birthday: Optional[datetime.datetime] + birthday: datetime.datetime | None """Birthday as a datetime object.""" creation_date: datetime.datetime """When the person was added (readonly).""" department: str """Department name.""" - email: List[Tuple[str, str]] + email: list[tuple[str, str]] """Email address(es).""" first_name: str """First name.""" first_name_phonetic: str """Phonetic first name.""" full_name: str - """The person’s full name (readonly).""" + """The person's full name (readonly).""" id: int """The persistent identifier of the person record (readonly).""" - image_data: Optional[bytes] - """The person’s image data (e.g., PNG or JPEG) or None.""" - instant_message: List[Tuple[str, Dict[str, str]]] + image_data: bytes | None + """The person's image data (e.g., PNG or JPEG) or None.""" + instant_message: list[tuple[str, dict[str, str]]] """Instant message accounts.""" job_title: str """Job title.""" @@ -87,17 +85,17 @@ class Person: """Additional notes.""" organization: str """Organization name.""" - phone: List[Tuple[str, str]] + phone: list[tuple[str, str]] """Phone number(s).""" prefix: str """Prefix (e.g., 'Sir').""" - related_names: List[Tuple[str, str]] + related_names: list[tuple[str, str]] """Related names.""" - social_profile: List[Tuple[str, Dict[str, str]]] + social_profile: list[tuple[str, dict[str, str]]] """Social profile(s).""" suffix: str """Suffix (e.g., 'Jr.').""" - url: List[Tuple[str, str]] + url: list[tuple[str, str]] """URL(s).""" vcard: str """VCard representation of the person's data (readonly).""" @@ -109,25 +107,27 @@ class Group: """A Group object represents a group in the address book.""" name: str - """The group’s name.""" + """The group's name.""" id: int """The persistent identifier of the group (readonly).""" # ----------------------------------------------------------------------------- # Functions # ----------------------------------------------------------------------------- -def get_group(group_id: int) -> Optional[Group]: - """Return the Group with the given id.""" +def get_group(group_id: int) -> Group | None: + """Return the Group with the given id, or None if not found.""" ... -def get_all_groups() -> List[Group]: +def get_all_groups() -> list[Group]: """Return a list of all Group objects in the address book.""" ... def add_group() -> Group: """Add a new Group to the address book. + Returns: Group: The newly created Group object. + """ ... @@ -143,16 +143,16 @@ def remove_person(person: Person) -> None: """Remove a Person from the address book.""" ... -def find(name: str) -> List[Person]: +def find(name: str) -> list[Person]: """Do a prefix search for the given name and return a list of matches.""" ... -def get_all_people() -> List[Person]: +def get_all_people() -> list[Person]: """Return a list of all people in the address book.""" ... -def get_person(person_id: int) -> Optional[Person]: - """Return the Person with the given id.""" +def get_person(person_id: int) -> Person | None: + """Return the Person with the given id, or None if not found.""" ... def save() -> None: diff --git a/stubs/pythonista_stubs/dialogs.pyi b/stubs/pythonista_stubs/dialogs.pyi index 379ae4e..5a3263c 100644 --- a/stubs/pythonista_stubs/dialogs.pyi +++ b/stubs/pythonista_stubs/dialogs.pyi @@ -4,7 +4,7 @@ functions and their parameters, to be used for static analysis and autocompletio import datetime from collections.abc import Sequence -from typing import Any, Literal, Protocol, TypeAlias, TypeVar +from typing import Any, Literal, Protocol, TypeAlias, TypedDict, TypeVar from PIL.Image import Image as PILImage @@ -13,10 +13,6 @@ from PIL.Image import Image as PILImage from .console import _HudIcon from .ui import Image as UIImage -class TextField: - AUTOCAPITALIZE_SENTENCES: int = ... - # ... other autocapitalization types - class ListDataSource: items: list[dict[str, Any]] = ... @@ -69,15 +65,15 @@ def hud_alert(message: str, icon: _HudIcon = "success", duration: float = 1.8) - # Dialog Functions # ----------------------------------------------------------------------------- class StrConvertible(Protocol): - def __str__(self) -> str: ... + def __str__(self) -> str: ... # noqa: PYI029 -T = TypeVar('T', bound=StrConvertible) +_T = TypeVar("_T", bound=StrConvertible) def list_dialog( title: str = "", - items: list[T] | None = None, + items: list[_T] | None = None, multiple: bool = False, -) -> list[T] | None: +) -> list[_T] | None: """Presents a list of items and returns the one(s) that were selected. When the dialog is cancelled, None is returned. The `items` list can @@ -93,7 +89,7 @@ def list_dialog( Defaults to False. Returns: - Optional[Union[Any, List[Any]]]: The selected item(s), or None if the + Any | list[Any] | None: The selected item(s), or None if the dialog was canceled. """ @@ -120,46 +116,57 @@ def edit_list_dialog( Defaults to True. Returns: - Optional[List[Any]]: The modified list of items, or None if the + list[Any] | None: The modified list of items, or None if the dialog was cancelled. """ ... -# Field dictionaries are complex, so we'll type-hint them with a specific type alias. -_FieldType: TypeAlias = Literal[ - "switch", - "text", - "url", - "email", - "password", - "number", - "check", - "datetime", - "date", - "time", -] -_FieldDict: TypeAlias = dict[str, Any] -_SectionTuple: TypeAlias = tuple[str, list[_FieldDict], str | None] +class _BaseFieldDict(TypedDict, total=False): + key: str | None + title: str | None + tint_color: str | None + icon: str | UIImage | None + +# Optional keys specific to text-like fields +class TextFieldDict(_BaseFieldDict, total=False): + type: Literal["text", "url", "email", "password", "number"] + placeholder: str | None + autocorrection: bool | None + autocapitalization: int | None + +# If you want to be more specific about value types for different field types: +class SwitchFieldDict(_BaseFieldDict, total=False): + type: Literal["switch", "check"] + value: bool + +class DateTimeFieldDict(_BaseFieldDict, total=False): + type: Literal["datetime", "date", "time"] + value: datetime.datetime + +# Union type for all possible field dictionaries +FormFieldDict: TypeAlias = SwitchFieldDict | TextFieldDict | DateTimeFieldDict + +_SectionTuple: TypeAlias = tuple[str, list[_BaseFieldDict], str | None] def form_dialog( title: str = "", - fields: list[_FieldDict] | None = None, + fields: list[FormFieldDict] | None = None, sections: list[_SectionTuple] | None = None, ) -> dict[str, Any] | None: """Presents a form dialog with customizable data input fields. Args: title (str, optional): The title of the dialog. Defaults to "". - fields (List[Dict[str, Any]], optional): A list of field dictionaries for + fields (list[FormFieldDict] | None, optional): A list of field dictionaries for a single-section form. Use `sections` for multiple sections. Defaults to None. - sections (List[Tuple[str, List[Dict[str, Any]], Optional[str]]], optional): + sections (list[_SectionTuple] | None, optional): A list of tuples, where each tuple represents a section. Defaults to None. Returns: - Optional[Dict[str, Any]]: A dictionary of values for each field, + dict[str, Any] | None: A dictionary of values for each field, or None if the dialog was cancelled. """ @@ -178,17 +185,17 @@ def text_dialog( Args: title (str, optional): The title of the dialog. Defaults to "". text (str, optional): The initial text in the editor. Defaults to "". - font (Union[Tuple[str, int], Tuple[str], str], optional): + font (tuple[str, int] | tuple[str] | str, optional): The font and size. Defaults to ('', 16). - autocorrection (Optional[bool], optional): Whether auto-correction + autocorrection (bool | None, optional): Whether auto-correction should be enabled. Defaults to None. autocapitalization (int, optional): The auto-capitalization behavior. Defaults to ui.AUTOCAPITALIZE_SENTENCES. - spellchecking (Optional[bool], optional): Whether spell checking + spellchecking (bool | None, optional): Whether spell checking should be enabled. Defaults to None. Returns: - Optional[str]: The edited text, or None if the dialog was cancelled. + str | None: The edited text, or None if the dialog was cancelled. """ ... @@ -200,7 +207,7 @@ def date_dialog(title: str = "") -> datetime.datetime | None: title (str, optional): The title of the dialog. Defaults to "". Returns: - Optional[datetime.datetime]: A datetime.datetime object with the selected + datetime.datetime | None: A datetime.datetime object with the selected date, or None if the dialog was cancelled. """ @@ -213,7 +220,7 @@ def time_dialog(title: str = "") -> datetime.datetime | None: title (str, optional): The title of the dialog. Defaults to "". Returns: - Optional[datetime.datetime]: A datetime.datetime object with the selected + datetime.datetime | None: A datetime.datetime object with the selected time, or None if the dialog was cancelled. """ @@ -226,7 +233,7 @@ def datetime_dialog(title: str = "") -> datetime.datetime | None: title (str, optional): The title of the dialog. Defaults to "". Returns: - Optional[datetime.datetime]: A datetime.datetime object with the selected + datetime.datetime | None: A datetime.datetime object with the selected date and time, or None if the dialog was cancelled. """ @@ -239,7 +246,7 @@ def duration_dialog(title: str = "") -> float | None: title (str, optional): The title of the dialog. Defaults to "". Returns: - Optional[float]: The selected duration in seconds, or None if the + float | None: The selected duration in seconds, or None if the dialog was cancelled. """ @@ -288,7 +295,7 @@ def pick_document(types: list[str] = ["public.data"]) -> str | None: file types that should be selectable. Defaults to ['public.data']. Returns: - Optional[str]: The path to the selected temporary file, or None if + str | None: The path to the selected temporary file, or None if the dialog was cancelled. """ diff --git a/stubs/pythonista_stubs/editor.pyi b/stubs/pythonista_stubs/editor.pyi index 952506e..e44e8a3 100644 --- a/stubs/pythonista_stubs/editor.pyi +++ b/stubs/pythonista_stubs/editor.pyi @@ -1,18 +1,18 @@ -""" -This is a stub file for the `editor` module, providing type hints for its +"""This is a stub file for the `editor` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import Optional, Tuple, Literal +from typing import Literal, TypeAlias # We'll use a minimal stub for the ui.View type from the ui module. class View: ... -def get_path() -> Optional[str]: - """Returns the absolute file path of the script that is currently open in the editor. +def get_path() -> str | None: + """Returns the absolute path of the script that is currently open in the editor. Returns: - Optional[str]: The absolute file path, or None if no script is open. + str | None: The absolute file path, or None if no script is open. + """ ... @@ -21,38 +21,42 @@ def get_text() -> str: Returns: str: The full text content of the editor. + """ ... -def get_selection() -> Optional[Tuple[int, int]]: +def get_selection() -> tuple[int, int] | None: """Returns the selected range as a tuple of the form (start, end). The `start` and `end` values are character indices. Returns: - Optional[Tuple[int, int]]: The start and end indices of the selection, + tuple[int, int] | None: The start and end indices of the selection, or None if no file is currently open. + """ ... -def get_line_selection() -> Optional[Tuple[int, int]]: +def get_line_selection() -> tuple[int, int] | None: """Returns the range of all lines that are part of the current selection. Returns: - Optional[Tuple[int, int]]: The start and end indices of the line selection, + tuple[int, int] | None: The start and end indices of the line selection, or None if no file is currently open. + """ ... -def set_selection(start: int, end: Optional[int] = None, scroll: bool = False) -> None: +def set_selection(start: int, end: int | None = None, scroll: bool = False) -> None: """Sets the selected range in the editor. Args: start (int): The starting character index of the selection. - end (Optional[int], optional): The ending character index of the selection. + end (int | None, optional): The ending character index of the selection. If None, the caret is positioned at `start` with no text selected. scroll (bool, optional): If True, scrolls the view to make the selection visible. Defaults to False. + """ ... @@ -66,20 +70,22 @@ def replace_text(start: int, end: int, replacement: str) -> None: start (int): The starting character index of the range to replace. end (int): The ending character index of the range to replace. replacement (str): The new text to insert. + """ ... -def make_new_file(name: Optional[str] = None, content: Optional[str] = None) -> None: +def make_new_file(name: str | None = None, content: str | None = None) -> None: """Creates a new file and opens it in the editor. If a file with the given name already exists, a numeric suffix is automatically appended. Args: - name (Optional[str], optional): The desired name for the new file. + name (str | None, optional): The desired name for the new file. Defaults to None. - content (Optional[str], optional): The initial content of the new file. + content (str | None, optional): The initial content of the new file. If omitted, an empty file is created. Defaults to None. + """ ... @@ -88,24 +94,30 @@ def open_file(name: str, new_tab: bool = False) -> None: Args: name (str): The path to the file. It can be relative to the script - library’s root directory or an absolute path. The .py extension + library's root directory or an absolute path. The .py extension can be omitted. new_tab (bool, optional): If True, the file is opened in a new tab. Defaults to False. + """ ... -def apply_ui_theme(ui_view: View, theme_name: Optional[str] = None) -> None: +def apply_ui_theme(ui_view: View, theme_name: str | None = None) -> None: """Styles a ui.View (and its descendants) with the given UI theme. Args: ui_view (ui.View): The view to be styled. - theme_name (Optional[str], optional): The name of the theme. If None, + theme_name (str | None, optional): The name of the theme. If None, the currently selected theme is used. Defaults to None. + """ ... -def present_themed(ui_view: View, theme_name: Optional[str] = None, **kwargs) -> None: +def present_themed( + ui_view: View, + theme_name: str | None = None, + **kwargs, # noqa: ANN003 +) -> None: """Styles a ui.View and presents it. This function combines `apply_ui_theme()` and `ui.View.present()`. @@ -113,19 +125,25 @@ def present_themed(ui_view: View, theme_name: Optional[str] = None, **kwargs) -> Args: ui_view (ui.View): The view to be styled and presented. - theme_name (Optional[str], optional): The name of the theme. If None, + theme_name (str | None, optional): The name of the theme. If None, the currently selected theme is used. Defaults to None. + **kwargs: Keyword arguments are passed on to ui.View.present(), + except for title_bar_color and title_color, which are set + automatically based on the theme. + + + """ ... -_AnnotationStyle = Literal["success", "warning", "error"] +_AnnotationStyle: TypeAlias = Literal["success", "warning", "error"] def annotate_line( lineno: int, text: str = "", style: _AnnotationStyle = "warning", expanded: bool = True, - filename: Optional[str] = None, + filename: str | None = None, scroll: bool = False, ) -> None: """Annotates a line of code in the editor with a label. @@ -137,20 +155,22 @@ def annotate_line( the annotation. Defaults to 'warning'. expanded (bool, optional): If False, only an icon is shown; tapping shows the text. Defaults to True. - filename (Optional[str], optional): The path to the file to annotate. + filename (str | None, optional): The path to the file to annotate. If None, the file currently open in the editor is used. Defaults to None. scroll (bool, optional): If True, scrolls to the annotated line. Defaults to False. + """ ... -def clear_annotations(filename: Optional[str] = None) -> None: +def clear_annotations(filename: str | None = None) -> None: """Removes all annotations that were added via `annotate_line()`. Args: - filename (Optional[str], optional): The path to the file from which to + filename (str | None, optional): The path to the file from which to clear annotations. If None, the file currently open is used. Defaults to None. + """ ... diff --git a/stubs/pythonista_stubs/keyboard.pyi b/stubs/pythonista_stubs/keyboard.pyi index c3d4cf8..4be0006 100644 --- a/stubs/pythonista_stubs/keyboard.pyi +++ b/stubs/pythonista_stubs/keyboard.pyi @@ -1,27 +1,23 @@ -""" -This is a stub file for the `keyboard` module, providing type hints for its +"""This is a stub file for the `keyboard` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import List, Literal, Optional, Tuple +from typing import Literal, TypeAlias -# These are imported from the `ui` module, which is part of Pythonista. -class View: - def __init__(self, *args, **kwargs): ... - def add_subview(self, view: "View") -> None: ... - def remove_subview(self, view: "View") -> None: ... - def present(self, style: str = "sheet", animated: bool = True) -> None: ... +from .ui import View # ----------------------------------------------------------------------------- # Functions # ----------------------------------------------------------------------------- -_Appearance = Literal["dark", "light"] -_Mode = Literal["current", "minimized", "expanded"] +_Appearance: TypeAlias = Literal["dark", "light"] +_Mode: TypeAlias = Literal["current", "minimized", "expanded"] def backspace(times: int = 1) -> None: """Delete backwards in the current document. + Args: times (int, optional): The number of characters to delete. Defaults to 1. + """ ... @@ -33,7 +29,7 @@ def get_document_id() -> str: """Return a unique identifier (UUID) for the current document.""" ... -def get_input_context() -> Tuple[str, str]: +def get_input_context() -> tuple[str, str]: """Return a 2-tuple with the text immediately before and after the cursor.""" ... @@ -41,11 +37,13 @@ def get_selected_text() -> str: """Return the currently selected text or an empty string.""" ... -def get_text_replacements() -> Optional[List[Tuple[str, str]]]: +def get_text_replacements() -> list[tuple[str, str]] | None: """Return a list of text replacements. + Returns: - Optional[List[Tuple[str, str]]]: A list of (phrase, shortcut) tuples, + list[tuple[str, str]] | None: A list of (phrase, shortcut) tuples, or None if not running in the keyboard. + """ ... @@ -73,10 +71,13 @@ def play_input_click() -> None: """Play an input click sound.""" ... -def set_view(view: Optional[View] = None, mode: _Mode = "current") -> None: +def set_view(view: View | None = None, mode: _Mode = "current") -> None: """Sets a custom ui.View as the keyboard's UI. + Args: view (ui.View, optional): The view to display. Pass None to close. - mode (str, optional): The presentation mode ('minimized', 'expanded', or 'current'). + mode (str, optional): The presentation mode, one of 'minimized', + 'expanded', or 'current'. + """ ... diff --git a/stubs/pythonista_stubs/keychain.pyi b/stubs/pythonista_stubs/keychain.pyi index bbee4fc..7e0c993 100644 --- a/stubs/pythonista_stubs/keychain.pyi +++ b/stubs/pythonista_stubs/keychain.pyi @@ -5,11 +5,12 @@ This module provides simple access to secure password storage. Note: The keychain is not shared between apps, so you cannot use this to access passwords stored in Safari's keychain, for example. + """ -from typing import Optional, List, Tuple, Any +from typing import Any -def get_password(service: str, account: str) -> Optional[str]: +def get_password(service: str, account: str) -> str | None: """Get a password from the keychain. Args: @@ -19,6 +20,7 @@ def get_password(service: str, account: str) -> Optional[str]: Returns: The password as a string, or `None` if no password is found for the given service and account. + """ ... @@ -32,6 +34,7 @@ def set_password(service: str, account: str, password: str) -> None: service: The name of the service to associate with the password. account: The name of the user account. password: The password to be stored. + """ ... @@ -43,6 +46,7 @@ def delete_password(service: str, account: str) -> None: Args: service: The name of the service. account: The name of the user account. + """ ... @@ -54,4 +58,4 @@ def reset_keychain() -> None: """ ... -def get_services() -> List[Tuple[Any, Any]]: ... +def get_services() -> list[tuple[Any, Any]]: ... diff --git a/stubs/pythonista_stubs/linguistictagger.pyi b/stubs/pythonista_stubs/linguistictagger.pyi index 5393eac..39d73bc 100644 --- a/stubs/pythonista_stubs/linguistictagger.pyi +++ b/stubs/pythonista_stubs/linguistictagger.pyi @@ -1,10 +1,9 @@ -""" -This is a stub file for the `linguistictagger` module, providing type hints for +"""This is a stub file for the `linguistictagger` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import List, Literal, Tuple +from typing import Literal, TypeAlias # ----------------------------------------------------------------------------- # Constants @@ -20,7 +19,7 @@ SCHEME_SCRIPT: str = ... # ----------------------------------------------------------------------------- # Functions # ----------------------------------------------------------------------------- -_Scheme = Literal[ +_Scheme: TypeAlias = Literal[ "Token Type", "Lexical Class", "Name Type", @@ -33,13 +32,16 @@ _Scheme = Literal[ def tag_string( string: str, scheme: _Scheme, -) -> List[Tuple[str, str, Tuple[int, int]]]: +) -> list[tuple[str, str, tuple[int, int]]]: """Tag a given string according to the scheme. + Args: string (str): The text to be tagged. scheme (str): The tagging scheme to use. + Returns: - List[Tuple[str, str, Tuple[int, int]]]: A list of (tag, substring, range) + list[tuple[str, str, tuple[int, int]]]: A list of (tag, substring, range) tuples. + """ ... diff --git a/stubs/pythonista_stubs/location.pyi b/stubs/pythonista_stubs/location.pyi index c048adb..3fac8f1 100644 --- a/stubs/pythonista_stubs/location.pyi +++ b/stubs/pythonista_stubs/location.pyi @@ -16,7 +16,7 @@ def get_location() -> dict[str, float] | None: """Return the most recently obtained location data. Returns: - Optional[Dict[str, float]]: A dictionary with 'longitude', 'latitude', + dict[str, float] | None: A dictionary with 'longitude', 'latitude', and 'timestamp' keys, or None. """ diff --git a/stubs/pythonista_stubs/motion.pyi b/stubs/pythonista_stubs/motion.pyi index 883b058..cdf2341 100644 --- a/stubs/pythonista_stubs/motion.pyi +++ b/stubs/pythonista_stubs/motion.pyi @@ -1,10 +1,7 @@ -""" -This is a stub file for the `motion` module, providing type hints for its +"""This is a stub file for the `motion` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import Tuple - # ----------------------------------------------------------------------------- # Functions # ----------------------------------------------------------------------------- @@ -16,18 +13,20 @@ def stop_updates() -> None: """Stop monitoring the device's motion sensors.""" ... -def get_gravity() -> Tuple[float, float, float]: +def get_gravity() -> tuple[float, float, float]: """Return the gravity vector (x, y, z).""" ... -def get_user_acceleration() -> Tuple[float, float, float]: +def get_user_acceleration() -> tuple[float, float, float]: """Return the acceleration the user is giving to the device.""" ... -def get_attitude() -> Tuple[float, float, float]: +def get_attitude() -> tuple[float, float, float]: """Return the attitude of the device (roll, pitch, yaw).""" ... -def get_magnetic_field() -> Tuple[float, float, float, float]: - """Return the magnetic field vector with respect to the device (x, y, z, accuracy).""" +def get_magnetic_field() -> tuple[float, float, float, float]: + """Return the magnetic field vector with respect to the device: + (x, y, z, accuracy). + """ ... diff --git a/stubs/pythonista_stubs/notification.pyi b/stubs/pythonista_stubs/notification.pyi index 07a6a55..ba84dc0 100644 --- a/stubs/pythonista_stubs/notification.pyi +++ b/stubs/pythonista_stubs/notification.pyi @@ -1,29 +1,29 @@ -""" -This is a stub file for the `notification` module, providing type hints for its +"""This is a stub file for the `notification` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import Dict, List, Optional, Union +from typing import TypeAlias # ----------------------------------------------------------------------------- # Functions # ----------------------------------------------------------------------------- -_Action = Dict[str, Union[str, bool]] -_Trigger = Dict[str, Union[int, float, bool]] +_Action: TypeAlias = dict[str, str | bool] +_Trigger: TypeAlias = dict[str, int | float | bool] def schedule( - message: Optional[str] = None, + message: str | None = None, delay: float = 0, - sound_name: Optional[str] = None, - action_url: Optional[str] = None, - title: Optional[str] = None, - subtitle: Optional[str] = None, - attachments: Optional[List[str]] = None, - trigger: Optional[_Trigger] = None, - actions: Optional[List[_Action]] = None, - identifier: Optional[str] = None, + sound_name: str | None = None, + action_url: str | None = None, + title: str | None = None, + subtitle: str | None = None, + attachments: list[str] | None = None, + trigger: _Trigger | None = None, + actions: list[_Action] | None = None, + identifier: str | None = None, ) -> str: """Schedule a notification. + Args: message (str, optional): The main text of the notification. delay (float, optional): The time in seconds until delivery. Defaults to 0. @@ -32,19 +32,23 @@ def schedule( action_url (str, optional): The URL to launch when the notification is tapped. title (str, optional): The title of the notification. subtitle (str, optional): The subtitle of the notification. - attachments (List[str], optional): A list of file paths to attach. + attachments (list[str], optional): A list of file paths to attach. trigger (dict, optional): A dictionary for more complex triggers. - actions (List[dict], optional): Definitions for custom action buttons. + actions (list[dict], optional): Definitions for custom action buttons. identifier (str, optional): An optional identifier for the notification. + Returns: str: The identifier of the scheduled notification. + """ ... def cancel(identifier: str) -> None: """Cancel a previously scheduled notification. + Args: identifier (str): The identifier of the notification to cancel. + """ ... @@ -52,14 +56,16 @@ def cancel_all() -> None: """Cancel all previously scheduled notifications.""" ... -def get_scheduled() -> List[str]: +def get_scheduled() -> list[str]: """Return a list of scheduled notification identifiers.""" ... def remove_delivered(identifier: str) -> None: """Remove a specific delivered notification from Notification Center. + Args: identifier (str): The identifier of the notification to remove. + """ ... diff --git a/stubs/pythonista_stubs/objc_util.pyi b/stubs/pythonista_stubs/objc_util.pyi index cb74d7c..432f5f6 100644 --- a/stubs/pythonista_stubs/objc_util.pyi +++ b/stubs/pythonista_stubs/objc_util.pyi @@ -16,7 +16,7 @@ from typing import ( ) # A type variable for the decorator to preserve function signatures. -F = TypeVar("F", bound=Callable) +_F = TypeVar("_F", bound=Callable) class ObjCClass: """Wrapper for an Objective-C class. @@ -202,7 +202,7 @@ def uiimage_to_png(img: ObjCInstance) -> bytes: """ ... -def on_main_thread(func: F) -> F: +def on_main_thread(func: _F) -> _F: """Decorator to call a function on the UIKit main thread. This is typically used to decorate another function, but can also be used @@ -234,7 +234,6 @@ def sel(name: str) -> ctypes.c_void_p: class CGPoint(ctypes.Structure): """Core Graphics point structure.""" - _fields_ = ... x: float y: float def __init__(self, x: float = 0.0, y: float = 0.0) -> None: ... @@ -242,7 +241,6 @@ class CGPoint(ctypes.Structure): class CGSize(ctypes.Structure): """Core Graphics size structure.""" - _fields_ = ... width: float height: float def __init__(self, width: float = 0.0, height: float = 0.0) -> None: ... @@ -250,7 +248,6 @@ class CGSize(ctypes.Structure): class CGVector(ctypes.Structure): """Core Graphics vector structure.""" - _fields_ = ... dx: float dy: float def __init__(self, dx: float = 0.0, dy: float = 0.0) -> None: ... @@ -258,7 +255,6 @@ class CGVector(ctypes.Structure): class CGRect(ctypes.Structure): """Core Graphics rectangle structure.""" - _fields_ = ... origin: CGPoint size: CGSize def __init__( @@ -270,7 +266,6 @@ class CGRect(ctypes.Structure): class CGAffineTransform(ctypes.Structure): """Core Graphics affine transformation matrix.""" - _fields_ = ... a: float b: float c: float @@ -290,7 +285,6 @@ class CGAffineTransform(ctypes.Structure): class UIEdgeInsets(ctypes.Structure): """UIKit edge insets structure.""" - _fields_ = ... top: float left: float bottom: float @@ -306,7 +300,6 @@ class UIEdgeInsets(ctypes.Structure): class NSRange(ctypes.Structure): """Foundation range structure.""" - _fields_ = ... location: int length: int def __init__(self, location: int = 0, length: int = 0) -> None: ... diff --git a/stubs/pythonista_stubs/photos.pyi b/stubs/pythonista_stubs/photos.pyi index db956fa..0c50287 100644 --- a/stubs/pythonista_stubs/photos.pyi +++ b/stubs/pythonista_stubs/photos.pyi @@ -32,7 +32,7 @@ class Asset: """Fetch the asset's image data as a ui.Image object. Args: - size (Optional[tuple[int, int]]): The desired size of the returned image, + size (tuple[int, int] | None): The desired size of the returned image, specified as a tuple of (width, height). If None, the original image dimensions are used. crop (bool): If True, the image will be cropped to fit the specified @@ -130,7 +130,6 @@ class AssetCollection: # ----------------------------------------------------------------------------- _MediaType: TypeAlias = Literal["image", "video"] _CameraType: TypeAlias = Literal["rear", "front"] -_MapType: TypeAlias = Literal["standard", "satellite", "hybrid"] def capture_image(camera: _CameraType = "rear") -> PILImage | None: """Show a standard camera interface and return the captured image.""" @@ -203,10 +202,3 @@ def pick_asset( title: str = ..., multi: Literal[False] = ..., ) -> Asset | None: ... -def pick_asset( - assets: list[Asset] | AssetCollection | None = None, - title: str = "", - multi: bool = False, -) -> Asset | None | list[Asset]: - """Show a dialog with a grid of thumbnails for the given assets.""" - ... diff --git a/stubs/pythonista_stubs/reminders.pyi b/stubs/pythonista_stubs/reminders.pyi index db9a0cd..cd55f2d 100644 --- a/stubs/pythonista_stubs/reminders.pyi +++ b/stubs/pythonista_stubs/reminders.pyi @@ -1,10 +1,9 @@ -""" -This is a stub file for the `reminders` module, providing type hints for its +"""This is a stub file for the `reminders` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import List, Optional, Tuple, Literal, Union import datetime +from typing import Literal # ----------------------------------------------------------------------------- # Alarm Objects @@ -12,9 +11,9 @@ import datetime class Alarm: """Alarm objects represent an alarm associated with a reminder.""" - date: Optional[datetime.datetime] + date: datetime.datetime | None """The absolute date when the alarm is triggered.""" - location: Optional[Union[Tuple[str, float, float], Tuple[str, float, float, float]]] + location: tuple[str, float, float] | tuple[str, float, float, float] | None """The title, coordinates, and radius for a geo-location-based alarm. Represented as a 3- or 4-tuple: (title, latitude, longitude[, radius]). """ @@ -29,15 +28,15 @@ class Alarm: class Reminder: """Reminder objects represent a single reminder in a list.""" - def __init__(self, calendar: Optional["Calendar"] = None): ... + def __init__(self, calendar: Calendar | None = None): ... - alarms: List[Alarm] + alarms: list[Alarm] """A list of Alarm objects associated with this reminder.""" completed: bool """Whether the reminder has been completed (checked off) yet.""" - completion_date: Optional[datetime.datetime] + completion_date: datetime.datetime | None """The date when the reminder was completed, or None if not completed.""" - due_date: Optional[datetime.datetime] + due_date: datetime.datetime | None """The due date of the reminder.""" notes: str """Additional notes for the reminder.""" @@ -71,21 +70,24 @@ class Calendar: # Functions # ----------------------------------------------------------------------------- def get_reminders( - calendar: Optional[Calendar] = None, - completed: Optional[bool] = None, -) -> List[Reminder]: + calendar: Calendar | None = None, + completed: bool | None = None, +) -> list[Reminder]: """Return all reminders in the given Calendar (or all calendars). + Args: calendar (Calendar, optional): The calendar to get reminders from. Defaults to None. completed (bool, optional): Filters reminders by completion status. Defaults to None (all reminders). + Returns: - List[Reminder]: A list of Reminder objects. + list[Reminder]: A list of Reminder objects. + """ ... -def get_all_calendars() -> List[Calendar]: +def get_all_calendars() -> list[Calendar]: """Return a list of all available Calendar objects.""" ... @@ -93,29 +95,38 @@ def get_default_calendar() -> Calendar: """Return the Calendar that is used for new reminders by default.""" ... -def get_calendar(calendar_id: str) -> Optional[Calendar]: +def get_calendar(calendar_id: str) -> Calendar | None: """Return a specific Calendar by its unique identifier. + Args: calendar_id (str): The unique identifier of the calendar. + Returns: - Optional[Calendar]: The Calendar object, or None if not found. + Calendar | None: The Calendar object, or None if not found. + """ ... def delete_reminder(reminder: Reminder) -> bool: """Remove a Reminder from the database. + Args: reminder (Reminder): The Reminder object to remove. + Returns: bool: True if the removal was successful, False otherwise. + """ ... def delete_calendar(calendar: Calendar) -> bool: """Remove a Calendar from the database. + Args: calendar (Calendar): The Calendar object to remove. + Returns: bool: True if the removal was successful, False otherwise. + """ ... diff --git a/stubs/pythonista_stubs/shortcuts.pyi b/stubs/pythonista_stubs/shortcuts.pyi index e939662..e803a41 100644 --- a/stubs/pythonista_stubs/shortcuts.pyi +++ b/stubs/pythonista_stubs/shortcuts.pyi @@ -1,44 +1,50 @@ -""" -This is a stub file for the `shortcuts` module, providing type hints for its +"""This is a stub file for the `shortcuts` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import List, Literal, Optional +from typing import Literal, TypeAlias # ----------------------------------------------------------------------------- # Functions # ----------------------------------------------------------------------------- -_Action = Literal["run", "open", "exec"] +_Action: TypeAlias = Literal["run", "open", "exec"] def open_url(url: str) -> None: """Open a given URL using the system's default app. + Args: url (str): The URL to open. + """ ... def pythonista_url( path: str = "", action: _Action = "run", - args: Optional[str] = None, - argv: Optional[List[str]] = None, + args: str | None = None, + argv: list[str] | None = None, ) -> str: """Generates a pythonista3://... URL from a file name/path. + Args: path (str, optional): Path to the script. Defaults to ''. action (_Action, optional): The action to perform ('run', 'open', 'exec'). Defaults to 'run'. args (str, optional): A string of arguments to pass to the script. argv (List[str], optional): A list of arguments to pass to the script. + Returns: str: The generated Pythonista URL. + """ ... -def open_shortcuts_app(name: Optional[str] = None, shortcut_input: str = "") -> None: +def open_shortcuts_app(name: str | None = None, shortcut_input: str = "") -> None: """Open the Apple Shortcuts app and optionally run a named shortcut. + Args: name (str, optional): The name of the shortcut to run. shortcut_input (str, optional): Text input to pass to the shortcut. + """ ... diff --git a/stubs/pythonista_stubs/sound.pyi b/stubs/pythonista_stubs/sound.pyi index 94d7ddc..080c29a 100644 --- a/stubs/pythonista_stubs/sound.pyi +++ b/stubs/pythonista_stubs/sound.pyi @@ -1,9 +1,8 @@ -""" -This is a stub file for the `sound` module, providing type hints for its +"""This is a stub file for the `sound` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import Callable, Optional, Tuple, Mapping +from collections.abc import Callable, Mapping # ----------------------------------------------------------------------------- # Functions @@ -14,16 +13,19 @@ def play_effect( pitch: float = 1.0, pan: float = 0.0, looping: bool = False, -) -> Optional["Effect"]: +) -> Effect | None: """Play the sound effect with the given name. + Args: name (str): The name of the sound effect or a file path. volume (float, optional): The volume of the effect (0.0-1.0). pitch (float, optional): The pitch of the effect. Defaults to 1.0. pan (float, optional): The stereo position (-1.0 to 1.0). Defaults to 0.0. looping (bool, optional): Whether the effect should loop. Defaults to False. + Returns: - Optional[Effect]: An Effect object, or None if too many effects are playing. + Effect | None: An Effect object, or None if too many effects are playing. + """ ... @@ -31,7 +33,7 @@ def stop_all_effects() -> None: """Stop all sound effects that are currently playing.""" ... -def stop_effect(effect: "Effect") -> None: +def stop_effect(effect: Effect) -> None: """Stop playback of the given sound effect.""" ... @@ -50,6 +52,7 @@ class Effect: """Represents a sound effect that is currently playing. Effect objects are returned from `play_effect()`. """ + def stop(self) -> None: """Stop playback of the sound effect.""" ... @@ -67,9 +70,9 @@ class Effect: @pitch.setter def pitch(self, value: float) -> None: ... @property - def position(self) -> Tuple[float, float, float]: ... + def position(self) -> tuple[float, float, float]: ... @position.setter - def position(self, value: Tuple[float, float, float]) -> None: ... + def position(self, value: tuple[float, float, float]) -> None: ... @property def volume(self) -> float: ... @volume.setter @@ -80,6 +83,7 @@ class Effect: # ----------------------------------------------------------------------------- class Player: """Provides an interface for playing audio files from disk.""" + def __init__(self, file_path: str): ... def play(self) -> None: """Start playing audio.""" @@ -92,12 +96,11 @@ class Player: def pause(self) -> None: """Stop playing audio, but keep the current playback position.""" ... - current_time: float """The current playback position in seconds.""" duration: float """The duration of the audio track (read-only).""" - finished_handler: Optional[Callable[[], None]] + finished_handler: Callable[[], None] | None """A function that is called when the player finishes playing.""" number_of_loops: int """The number of times the audio track should be repeated.""" @@ -111,11 +114,14 @@ class Player: # ----------------------------------------------------------------------------- class Recorder: """High-level methods for recording audio files from the microphone.""" + def __init__(self, file_path: str): ... - def record(self, duration: Optional[float] = None) -> None: + def record(self, duration: float | None = None) -> None: """Start recording audio from the microphone. + Args: duration (float, optional): The number of seconds to record. + """ ... @@ -126,12 +132,11 @@ class Recorder: def pause(self) -> None: """Pause recording audio.""" ... - current_time: float """The current duration of the active recording.""" recording: bool """Whether the recorder is currently recording.""" - meters: Mapping[str, Tuple[float, float]] + meters: Mapping[str, tuple[float, float]] """The current average and peak power (read-only). Example: {'average': (-35.3, -30.1), 'peak': (-5.2, -8.2)} """ @@ -141,7 +146,8 @@ class Recorder: # ----------------------------------------------------------------------------- class MIDIPlayer: """Simple playback functions for MIDI (.mid) files.""" - def __init__(self, file_path: str, sound_bank_path: Optional[str] = None): ... + + def __init__(self, file_path: str, sound_bank_path: str | None = None): ... def play(self) -> None: """Start playback.""" ... @@ -149,7 +155,6 @@ class MIDIPlayer: def stop(self) -> None: """Stop playback.""" ... - current_time: float """The current playback position.""" duration: float diff --git a/stubs/pythonista_stubs/speech.pyi b/stubs/pythonista_stubs/speech.pyi index 9721d4f..8b9cbfd 100644 --- a/stubs/pythonista_stubs/speech.pyi +++ b/stubs/pythonista_stubs/speech.pyi @@ -1,31 +1,30 @@ -""" -This is a stub file for the `speech` module, providing type hints for its +"""This is a stub file for the `speech` module, providing type hints for its functions and their parameters, to be used for static analysis and autocompletion. """ -from typing import Dict, List, Optional, Tuple - # ----------------------------------------------------------------------------- # Functions # ----------------------------------------------------------------------------- -def get_synthesis_languages() -> List[str]: +def get_synthesis_languages() -> list[str]: """Return a list of all language/locale identifiers available for speech synthesis. """ ... -def get_recognition_languages() -> List[str]: +def get_recognition_languages() -> list[str]: """Return a list of all language/locale identifiers available for speech recognition. """ ... -def say(text: str, language: Optional[str] = None, rate: float = 0.5) -> None: +def say(text: str, language: str | None = None, rate: float = 0.5) -> None: """Speak the given text. + Args: text (str): The text to be spoken. language (str, optional): The language as a BCP-47 code (e.g. 'en-US'). rate (float, optional): The speech rate (0.0 slowest, 1.0 fastest). + """ ... @@ -38,17 +37,22 @@ def is_speaking() -> bool: ... def recognize( - file_path: str, language: Optional[str] = None -) -> List[Tuple[str, List[Dict]]]: + file_path: str, + language: str | None = None, +) -> list[tuple[str, list[dict]]]: """Transcribe spoken text in the given audio file. + Args: file_path (str): The path to the audio file. language (str, optional): The locale identifier (e.g. 'en-US'). + Returns: List[Tuple[str, List[Dict]]]: A list of possible transcriptions. + Raises: RuntimeError: If speech recognition fails. ValueError: If the language parameter is invalid. IOError: If the audio file cannot be read. + """ ... diff --git a/stubs/pythonista_stubs/ui.pyi b/stubs/pythonista_stubs/ui.pyi index 514819d..123b0cc 100644 --- a/stubs/pythonista_stubs/ui.pyi +++ b/stubs/pythonista_stubs/ui.pyi @@ -2,119 +2,136 @@ from typing import Literal, TypeAlias _RenderingMode: TypeAlias = Literal["automatic", "always_original", "always_template"] +AUTOCAPITALIZE_NONE: int = ... +AUTOCAPITALIZE_WORDS: int = ... +AUTOCAPITALIZE_SENTENCES: int = ... +AUTOCAPITALIZE_ALL: int = ... + class Image: """Represents an image that can be displayed in the user interface.""" - + @classmethod def from_data(cls, image_data: bytes, scale: float | None = None) -> Image: """Create an image from binary image data. - + Args: image_data: Binary image data (PNG, JPEG, etc.) scale: Scale factor for high-resolution displays (optional) - + Returns: New Image object + """ ... - + @classmethod def named(cls, image_name: str) -> Image | None: """Create an image from a built-in or local image file. - + Args: image_name: Name of built-in image (no extension) or path to local file - + Returns: Image object, or None if image not found + """ ... - + @property def scale(self) -> float: """The scale factor of the image (readonly).""" ... - + @property def size(self) -> tuple[float, float]: """The dimensions of the image as (width, height) tuple (readonly).""" ... - + def clip_to_mask(self, x: float, y: float, width: float, height: float) -> None: """Use this image as a mask for subsequent drawing operations. - + Args: x: X coordinate of the clipping rectangle y: Y coordinate of the clipping rectangle width: Width of the clipping rectangle height: Height of the clipping rectangle + """ ... - + def draw( - self, - x: float | None = None, - y: float | None = None, - width: float | None = None, - height: float | None = None + self, + x: float | None = None, + y: float | None = None, + width: float | None = None, + height: float | None = None, ) -> None: """Draw the image in the current drawing context. - + Args: x: X coordinate (optional) y: Y coordinate (optional) width: Width to draw (optional, uses image width if None) height: Height to draw (optional, uses image height if None) + """ ... - + def draw_as_pattern(self, x: float, y: float, width: float, height: float) -> None: """Fill a rectangle with this image as a repeating pattern. - + Args: x: X coordinate of the rectangle y: Y coordinate of the rectangle width: Width of the rectangle height: Height of the rectangle + """ ... - + def resizable_image( - self, top: float, left: float, bottom: float, right: float + self, + top: float, + left: float, + bottom: float, + right: float, ) -> Image: """Create a 9-patch resizable version of this image. - + Args: top: Top inset left: Left inset bottom: Bottom inset right: Right inset - + Returns: New resizable Image object + """ ... - + def show(self) -> None: """Display the image in the console output.""" ... - + def to_png(self) -> bytes: """Convert the image to PNG format. - + Returns: PNG image data as bytes + """ ... - + def with_rendering_mode(self, mode: _RenderingMode) -> Image: """Create a new image with the specified rendering mode. - + Args: mode: The rendering mode to use - + Returns: New Image object with the specified rendering mode + """ ...