Skip to content

Commit

Permalink
beartype.claw docos x 1.
Browse files Browse the repository at this point in the history
This commit is the first in a commit chain documenting the
`beartype.claw` subpackage first introduced with @beartype 0.15.0 at our
official ReadTheDocs (RTD)-hosted site. Specifically, this commit drafts
various introductory sections outlining the gist of this subpackage.
(*Unhinged hinges!*)
  • Loading branch information
leycec committed Sep 28, 2023
1 parent ad6c58e commit e8654b3
Show file tree
Hide file tree
Showing 7 changed files with 654 additions and 516 deletions.
72 changes: 43 additions & 29 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@
induce migraines in 22% of the whole devops population. For your safety,
that document no longer exists. This is how much beartype cares.

**Beartype** is an `open-source <beartype license_>`__ `PEP-compliant
<beartype PEPs_>`__ `near-real-time <beartype FAQ_>`__ `pure-Python runtime type
checker <beartype ELI5_>`__ emphasizing efficiency, usability, and thrilling
puns.
**Beartype** is an `open-source <beartype license_>`__ `pure-Python <beartype
pure_>`__ `PEP-compliant <beartype PEPs_>`__ `near-real-time <beartype FAQ_>`__
`hybrid runtime-static <beartype hybrid_>`__ `third-generation <beartype
third_>`__ `type checker <beartype ELI5_>`__ emphasizing efficiency,
usability, unsubstantiated jargon we just made up, and thrilling puns.

.. #FIXME: Once we actually receive a sponsor at this tier, please remove this
.. #placeholder as well as the icon links below. kthx
Expand All @@ -55,21 +56,41 @@ puns.
# Install beartype.
$ pip3 install beartype
# Edit the "{your_package}.__init__" submodule with your favourite IDE.
$ vim {your_package}/__init__.py # <-- so, i see that you too vim
.. code-block:: python
from beartype.claw import beartype_this_package # <-- hype comes
beartype_this_package() # <-- hype goes
Beartype now implicitly type-checks *all* annotated classes, callables, and
variable assignments across *all* submodules of ``{your_package}``. Congrats.
This day all bugs die. :superscript:`...server slowly crashes`

Beartype also publishes a `plethora of APIs for fine-grained control over
type-checking <beartype APIs>`. For those who are about to QA, beartype salutes
you. Would you like to know more?

# So let's do this.
$ python3

.. code-block:: python
# ....................{ RAISE THE PAW }....................
# Manually enforce type hints across individual classes and callables.
# Do this only if you want a(nother) repetitive stress injury.
# Import the @beartype decorator.
>>> from beartype import beartype
>>> from beartype import beartype # <-- eponymous import; it's eponymous
# Annotate @beartype-decorated classes and callables with type hints.
>>> @beartype
>>> @beartype # <-- you too will believe in magic
... def quote_wiggum(lines: list[str]) -> None:
... print('{}\n\t— Police Chief Wiggum'.format("\n ".join(lines)))
# Call those callables with valid parameters.
>>> quote_wiggum(["Okay, folks. Show's over!", "Nothing to see here. Show's…",])
>>> quote_wiggum(["Okay, folks. Show's over!", " Nothing to see here. Show's…",])
“Okay, folks. Show's over!
Nothing to see here. Show's…”
— Police Chief Wiggum
Expand All @@ -87,8 +108,8 @@ puns.
list[str], as list item 0 value b'Oh, my God! A horrible plane crash!'
not str.
# ..................{ VALIDATORS }..................
# Squash bugs by refining type hints with validators.
# ....................{ MAKE IT SO }....................
# Squash bugs by refining type hints with @beartype validators.
>>> from beartype.vale import Is # <---- validator factory
>>> from typing import Annotated # <---------------- if Python ≥ 3.9.0
# >>> from typing_extensions import Annotated # <-- if Python < 3.9.0
Expand All @@ -111,9 +132,8 @@ puns.
typing.Annotated[list[str], Is[lambda lst: bool(lst)]], as value []
violates validator Is[lambda lst: bool(lst)].
# ..................{ AT ANY TIME }..................
# Type-check anything against any type hint –
# anywhere at anytime.
# ....................{ AT ANY TIME }....................
# Type-check anything against any type hint – anywhere at anytime.
>>> from beartype.door import (
... is_bearable, # <-------- like "isinstance(...)"
... die_if_unbearable, # <-- like "assert isinstance(...)"
Expand All @@ -125,10 +145,9 @@ puns.
violates type hint typing.Annotated[list[str], Is[lambda lst: bool(lst)]],
as list index 0 item 3405692655 not instance of str.
# ..................{ GO TO PLAID }..................
# Type-check anything in around 1µs (one millionth of
# a second) – including this list of one million
# 2-tuples of NumPy arrays.
# ....................{ GO TO PLAID }....................
# Type-check anything in around 1µs (one millionth of a second) – including
# this list of one million 2-tuples of NumPy arrays.
>>> from beartype.door import is_bearable
>>> from numpy import array, ndarray
>>> data = [(array(i), array(i)) for i in range(1000000)]
Expand Down Expand Up @@ -189,22 +208,9 @@ developed Python versions <Python status_>`__, `all Python package managers
:target: https://beartype.readthedocs.io/en/latest/?badge=latest
:alt: beartype Read The Docs (RTD) status
.. # ------------------( IMAGES ~ screenshot )------------------
.. |VSCode-Pylance-type-checking-setting| image:: https://user-images.githubusercontent.com/217028/164616311-c4a24889-0c53-4726-9051-29be7263ee9b.png
:alt: Disabling pyright-based VSCode Pylance type-checking
.. # ------------------( IMAGES ~ downstream )------------------
.. # Insert links to GitHub Sponsors funding at the icon level here, please!
.. # ------------------( SUBSTITUTIONS )------------------
.. # Non-breaking space, defined as a reST substitution substituting all "|_|"
.. # substrings with the non-breaking space Unicode character. Note that the
.. # ":trim:" directive silently removes all whitespace surrounding this "|_|".
.. # See also this StackOverflow answer strongly inspiring this substitution:
.. # https://stackoverflow.com/a/12145490/2809027
.. |_| unicode:: 0xA0
:trim:
.. # ------------------( LINKS ~ beartype : funding )------------------
.. _BETSE:
https://github.com/betsee/betse
Expand Down Expand Up @@ -292,6 +298,8 @@ developed Python versions <Python status_>`__, `all Python package managers
https://github.com/leycec
.. # ------------------( LINKS ~ beartype : rtd )------------------
.. _beartype APIs:
https://beartype.readthedocs.io/en/latest/api
.. _beartype RTD:
https://beartype.readthedocs.io
.. _beartype ELI5:
Expand All @@ -300,10 +308,16 @@ developed Python versions <Python status_>`__, `all Python package managers
https://beartype.readthedocs.io/en/latest/faq
.. _beartype PEPs:
https://beartype.readthedocs.io/en/latest/pep
.. _beartype hybrid:
https://beartype.readthedocs.io/en/latest/faq/#faq-hybrid
.. _beartype install:
https://beartype.readthedocs.io/en/latest/install
.. _beartype math:
https://beartype.readthedocs.io/en/latest/math
.. _beartype pure:
https://beartype.readthedocs.io/en/latest/faq/#faq-pure
.. _beartype third:
https://beartype.readthedocs.io/en/latest/faq/#faq-third
.. # ------------------( LINKS ~ github )------------------
.. _GitHub Actions:
Expand Down
77 changes: 72 additions & 5 deletions doc/src/api_claw.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,33 @@
Beartype Import Hooks
*********************

.. code-block:: text
**Beartype import hooks** enforce type hints across your entire app in two lines
of code with *no* runtime overhead. Do it for the new guy sobbing quietly in his
cubicle.

If it runs, we can type-check it.
— Arnold Bugenator in "Bugenator 2: Judgement Commit"
.. code-block:: python
# In your "{your_package}.__init__" submodule in a codebase far, far away...
from beartype.claw import beartype_this_package # <-- boilerplate for victory
beartype_this_package() # <-- yay! your team just won
**That's it.** That's beartype import hooks in ten seconds.
:superscript:`dyslexia notwithstanding` As the simplest of several import hooks
published by the :mod:`beartype.claw` subpackage, the
:func:`.beartype_this_package` function:

* Implicitly decorates *all* callables and classes in ``{your_package}`` by the
:func:`beartype.beartype` decorator. Rejoice, fellow mammals! You no longer
need to explicitly decorate anything by :func:`beartype.beartype` ever again.
Of course, you *can* if you want to – but there's no compelling reason to do
so and many compelling reasons *not* to do so. You have probably just thought
of five, but there are even more.
* Implicitly subjects *all* :pep:`526`\ -compliant annotated variable
assignments (e.g., ``muh_int: int = 'Pretty sure this isn't an integer, but
not sure.'``) to runtime type-checking performed by the
:func:`beartype.door.die_if_unbearable` function. More below.

The :mod:`beartype.claw` rabbit hole goes deep. Prepare to enter that hole.

.. # ------------------( TABLES OF CONTENTS )------------------
.. # Table of contents, excluding the above document heading. While the
Expand All @@ -35,6 +58,50 @@ Beartype Import Hooks

.. # ------------------( DESCRIPTION )------------------
Beartype Claw API
#################
Import Hooks Overview
#####################

Beartype import hooks implicitly perform both:

* Standard **runtime type-checking** (ala the :func:`beartype.beartype`
decorator).
* Standard **static type-checking** (ala mypy_ and pyright_) but **at runtime**
– which ain't standard.

Automate the :func:`beartype.beartype` decorator away today with magical import
hooks published by the :mod:`beartype.claw` subpackage! When you install import
hooks from beartype, you augment beartype from a :ref:`pure-runtime
second-generation type-checker <faq:third>` to a :ref:`hybrid runtime-static
third-generation type-checker <faq:hybrid>` – instantaneously.

Claw your way to the top of the bug heap threatening to drown your codebase in a
deluge of chittering carapaces, masticating mandibles, and probing probosci. The
bugginess you feel may be real, but so is the bug-mugging power of beartype.

Import Hooks API
################

Beartype import hooks come in two flavours:

* :ref:`Permanent import hooks <api_claw:permanent>` (i.e., side-effect-laden
import hooks whose effects permanently apply to *all* subsequently imported
packages and modules).
* :ref:`Idempotent import hooks <api_claw:idempotent>` (i.e., side-effect-free
import hooks whose effects are isolated to a specific block of code).

.. _api_claw:permanent:

Permanent Import Hooks
**********************

.. _api_claw:idempotent:

Idempotent Import Hooks
***********************

.. # FIXME: Revise signature up, please.
.. py:function::
beartyping( \
*, \
conf: beartype.BeartypeConf = beartype.BeartypeConf(), \
) -> None
46 changes: 45 additions & 1 deletion doc/src/api_decor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,33 @@
.. # Child reStructuredText (reST) document detailing the public-facing API of
.. # the @beartype.beartype decorator and associated data structures.
.. # ------------------( TODO )------------------
.. # FIXME: Split this overly large and increasingly unreadable document into
.. # the following two documents:
.. # * "api_decor.rst", containing *EVERYTHING* in this document up to but not
.. # including the "Beartype Configuration API" subsection.
.. # * "api_conf.rst", containing *EVERYTHING* in this document at and after the
.. # "Beartype Configuration API" subsection.
.. #
.. # Sadly, doing so appears to be currently infeasible. Why? Because Sphinx
.. # currently does *NOT* permit "py:module::" directives to be distributed
.. # across multiple documents. Ideally, the "api_conf.rst" document would be
.. # prefixed by a "py:module::" directive resembling:
.. # .. py:module:: beartype
.. # :noindexentry:
.. #
.. # Sadly, even Sphinx 7.0.1 fails to support that:
.. # /home/leycec/py/beartype/doc/src/api_conf.rst:12: ERROR: Error in "py:module" directive:
.. # unknown option: "noindexentry".
.. #
.. # .. py:module:: beartype
.. # :noindexentry:
.. #
.. # The ":noindexentry:" option is required to avoid indexing conflicts between
.. # the two documents while still preserving cross-references as expected.
.. #
.. # Consider submitting an upstream Sphinx feature request for this.
.. # ------------------( METADATA )------------------
.. # Fully-qualified name of the (sub)package described by this document,
.. # enabling this document to be externally referenced as :mod:`{name}`.
Expand Down Expand Up @@ -359,7 +386,7 @@ Come for the working examples. Stay for the wild hand-waving.
Configuration Mode
******************

*def* beartype.\ **beartype**\ (conf: beartype.BeartypeConf) ->
*def* beartype.\ **beartype**\ (\*, conf: beartype.BeartypeConf) ->
collections.abc.Callable[[T], T]

In configuration mode, :func:`.beartype` dynamically generates a new
Expand All @@ -384,6 +411,8 @@ too may cackle villainously as you feel the unbridled power of your keyboard.
Configuration: *because you know best*.

.. _api_decor:conf:

Beartype Configuration API
==========================

Expand All @@ -410,6 +439,21 @@ Beartype Configuration API
* Disable developer-specific debugging logic.
* Conditionally output color when standard output is attached to a terminal.

Beartype configurations may be passed as the optional keyword-only ``conf``
parameter accepted by *most* high-level runtime type-checking functions
exported by :mod:`beartype` – including:

* The :func:`beartype.beartype` decorator.
* The :func:`beartype.claw.beartype_all` import hook.
* The :func:`beartype.claw.beartype_package` import hook.
* The :func:`beartype.claw.beartype_packages` import hook.
* The :func:`beartype.claw.beartype_this_package` import hook.
* The :func:`beartype.claw.beartyping` import hook.
* The :func:`beartype.door.die_if_unbearable` type-checker.
* The :func:`beartype.door.is_bearable` type-checker.
* The :func:`beartype.door.TypeHint.die_if_unbearable` type-checker.
* The :func:`beartype.door.TypeHint.is_bearable` type-checker.

Beartype configurations are immutable objects memoized (i.e., cached) on the
unordered set of all passed parameters:

Expand Down
4 changes: 4 additions & 0 deletions doc/src/api_door.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ Procedural API
die_if_unbearable( \
obj: object, \
hint: object, \
*, \
conf: beartype.BeartypeConf = beartype.BeartypeConf(), \
) -> None
Expand Down Expand Up @@ -153,6 +154,7 @@ Procedural API
is_bearable( \
obj: object, \
hint: object, \
*, \
conf: beartype.BeartypeConf = beartype.BeartypeConf(), \
) -> bool
Expand Down Expand Up @@ -770,6 +772,7 @@ Object-oriented API
.. py:method::
die_if_unbearable( \
obj: object, \
*, \
conf: beartype.BeartypeConf = beartype.BeartypeConf(), \
) -> None
Expand Down Expand Up @@ -807,6 +810,7 @@ Object-oriented API
.. py:method::
is_bearable( \
obj: object, \
*, \
conf: beartype.BeartypeConf = beartype.BeartypeConf(), \
) -> bool
Expand Down

0 comments on commit e8654b3

Please sign in to comment.