Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Static Typing & Type Checking Support #100

Merged
merged 49 commits into from
Dec 28, 2023
Merged

Static Typing & Type Checking Support #100

merged 49 commits into from
Dec 28, 2023

Conversation

AnonymouX47
Copy link
Owner

@AnonymouX47 AnonymouX47 commented Oct 5, 2023

  • Incorporates static typing & type checking.
  • Adds, updates, corrects and removes type hints across the library.
    • With the exception of the image and widget sub-packages as those should go through massive changes real soon, which should come along with static typing.
  • Modifies some interfaces for better static typing.
  • Eliminates runtime argument type validation.
  • Adds typing_extensions dependency.
  • Adds mypy dev dependency.
  • Adds a GitHub workflow for static type checking with mypy.

Background

I've always been quite on the opposing side concerning this - thus far, annotations have only for documentation purposes - but I've come to realize the potential benefits of proper static type checking, both to the project itself and to its users.

That said, I'm still quite reserved about this as I've also realized this area is quite a slippery slope. It's just a thin line between adequate type hinting for type checking and spending valuable time writing unreadable or non-concise code just to satisfy a static type checker... and I'm not and will never be willing to cross that line (at least, not within this project).

One must understand and always keep in mind that Python is not a statically-typed language and really wasn't designed from the ground to be used that way but I'm willing to employ static typing to the extent that it doesn't result in poorer design, implementation or performance than dynamic typing.

Personally, I tend to play to the strengths of whatever language I use, which in the case of Python (IMHO) is majorly the fact that it's highly dynamic (in most cases) and fosters design and implementation of that kind. I tend to use quite a lot of these aspects of Python where reasonably applicable but will now try to find compromises where and when feasible.

@AnonymouX47 AnonymouX47 added the typing Related to static typing or type checking label Oct 5, 2023
@AnonymouX47 AnonymouX47 added this to the 0.8.0 milestone Oct 5, 2023
- Add: Type annotations where explicitly needed.
- Add: Type annotations for response RE patterns and `bytes` versions
  of control sequences.
- Change: Define `Pm()` as a `def` function, instead of a lambda.
- Change: Refactor `x_parse_color()`.
- Change: Use `tuple` instead of `typing.Tuple`.
- Change: Re-organize some control sequences.
- Change: Make definition grouping comments more visible.
- Add: Ignore type checking errors where necessary.
- Change: Use `-1` as default value of `_tty_fd` i.e to indicate
  "no TTY", instead of `None`.
- Change: Remove type annotations where not explicitly required.
- Change: Correct and update type annotations.
- Change: Refactor some decorators where necessary.
- Change: Include `None` in the return type of all functions decorated
  with `@unix_tty_only`, for documentation purposes.
- Change: Correct and update type annotations.
- Change: Use `None` as default value of *fg* and *bg* parameters,
  instead of an empty tuple.
- Add: Variable annotations.
- Change: Improve readablility and logic.
- Change: Reduce re-use of variables.
- Change: Rename some variables for clarity.
- Add: `HEX_RGB_FMT` and `ColorType` in `.utils`.
- Add: Overload signatures for type-checking.
- Change: Simplify HEX string conversion.
- Change: Simplify return type annotation using a type alias.
- Change: Include overload signatures in the docstring.
- Add: Complete type annotations.
- Change: Specialize type checking error ignore comment.
- Add: Ignore type checking error for implicit `__class__` reference.
- Change: Refactor `AlignedPadding.get_padded_size()` for performance
  and remove the no-longer-needed type checking error ignore comment.
- Change: Specialize type checking error ignore comments.
- Change: Update type annotations.
- Change: Use `getattr()` instead of the attribute reference operator
  for abitrary function attributes.
- Change: Remove the no-longer-neccessary instance checks for arguments
  of:

  - set_cell_ratio()
  - set_query_timeout()

- Change: Update the functions' docstrings.
- Change: Update test for `set_cell_ratio()` and `get_cell_ratio()`.
@AnonymouX47
Copy link
Owner Author

Starting work on the Renderable API (.renderable), I realized the current design, especially of render argument and data namespaces, is very dynamic in nature and just can't be made to work with static type checking (at the moment).

Work on this PR will be on hold pending the redesign of the API in a separate PR. I've thought and planned out most, if not all aspects of the new design but the implementation and particularly, rewriting the tests will still take a while.

- Change: Update typing in `RenderableMeta`.
- Change: Update typing in `Renderable`.

  - Properly type-hint attributes.
  - Properly type-hint `frame_count`.
  - Properly type-hint `_init_render_(); define overload signatures.
  - Properly type-hint `_get_frame_count_()`.
  - Correct typing for retrieval of render data/args in `draw()`.

- Change: Correct `Renderable` and `RenderableMeta` types in `._types`.
- Change: Use actual class name instead of `__class__`.
- Add: Export `OptionalPaddingT` from `.renderable`.
- Add: `OptionalPaddingT` to `.renderable`'s docs.
- Add: `sphinx_toolbox.more_autodoc.typevars` sphinx extension.
- Add: `._associated` to indicate the association state of a namespace
  class.
- Change: Make `._RENDER_CLS` compatible with static typing.

  - Remove `None` as possible value.
  - No longer has a default value; simply undefined for unassociated
    namespace classes.

- Change: Update affected tests.
- Add: Type hints for attributes.
- Change: Update typing in:

  - `ArgsDataNamespaceMeta`
  - `ArgsDataNamespace`
  - `ArgsNamespaceMeta`
  - `ArgsNamespace`
  - `DataNamespaceMeta`
  - `DataNamespace`

- Change: Update existing attribute type hints.
- Change: Properly type-hint methods.
- Change: Update signatures of `__{get,set,del}attr__` methods:

  - Use complete signatures.
  - Rename parameter *attr* -> *name*.
  - Add parameter and return type hints.

- Change: Use actual class names instead of `__class__`.
- Change: `typing.Type` -> `type`.
- Add: Type hints for attributes.
- Change: Update typing in:

  - `RenderArgsData`
  - `RenderArgs`
  - `RenderData`

- Change: Update existing attribute type hints.
- Change: Properly type-hint methods.
- Change: Use actual class names instead of `__class__`.
- Change: `typing.Type` -> `type`.
- Change: Update render data subscription across `Renderable`.
- Change: Return instances of `RenderArgs` instead of `type(self)` in
  `.convert()` and `.update()`.
- Add: Note about `__getitem__()` return type.
- Change: `typing.NamedTuple` -> `typing_extensions.NamedTuple`.
- Chaneg: Use actual class name instead of `__class__`.
- Add: Mark `ArgsNamespace` as providing dataclass-like behavior.

  - Constructor arguments are checked against field definitions.
  - Fields are marked as read-only.
  - ... (maybe)

- Change: Mark `__setattr__()` as not to be called.

  Also results in an indirect type checking error for assignment to
  abitrary instance attributes.
- Add: Overload signatures for `RenderArgs.update()`.
- Add: Document *namespace* pseudo parameter.
- Change: Make the first argument of `.update()` positional-only.
  - Already dropped Python 3.7 support.
- Add: Type hints for private attributes.
- Change: Refactor cached frame retrieval and validation.

  - Significantly better performance.
  - More static typing friendly.

- Change: Properly type-hint methods.
- Add: `._renderable_data`.
- Add: Specify type of render data subscription result.
- Change: Use `._renderable_data` instead of subscripting
  `._render_data` all the time.
- Change: Call special method on the class, not instance.
- Change: Disable `type-abstract` mypy error for all subpackages that
  use `RenderArgs` and `RenderData`.
- Change: Remove some "type: ignore" comments.
- Change: Remove instance checks on arguments of functions, class
  contructors and methods, along with the corresponding `TypeError`s
  raised when invalid.

  - Instance checks are costly, especially when they fail (i.e evaluate
    to `False`).
  - Static typing is being incorporated.

I took a look across a number of stdlib modules written in pure Python
and most actually don't validate argument types. They just assume the
arguments are of the expected type and use as-is. Only the interfaces
implemented in C perform argument type validation.
- Change: Remove argument type validation tests.
- Change: Remove instance and shape checks for return values.

These are now achieved via static type checking.
- Change: Optimize `{RenderArgs,RenderData}.__getitem__()` for
  unashable argument types.
- Change: Import required functions directly from `.utils` at package
  top level.
- Change: Use `type(x) is bool` instead of `isinstance(x, bool)` since
  `bool` cannot be subclassed.
- Change: Optimize compatibility validation of argument namespaces in
  `RenderArgs` initialization.
- Change: Update the description of `TypeError`s raised by
  `{RenderArgs,RenderData}.__getitem__()`.
- Change: Update the generic description of `ValueError`s (raised by
  the `Renderable` and `RenderIterator` constructors).
- Add: "py.typed" file at package source top level and include as
  package data.
- Change: Update the guidelines for type annotations.
- Add: Make target for pre-commit checks.
- Add: GH workflow.
AnonymouX47 added a commit that referenced this pull request Dec 28, 2023
@AnonymouX47 AnonymouX47 merged commit 52fa555 into main Dec 28, 2023
21 checks passed
@AnonymouX47 AnonymouX47 deleted the typing branch December 28, 2023 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
typing Related to static typing or type checking
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant