question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Popular value constraint

See original GitHub issue

Hello! I’m creating this issue to see how people feels about choosing the most popular constrains so we can agree which one are more important/urgent, feel free also to comment improve the list if you feel like I’m missing something. I’m gonna create some categories as well for visibility

String Constraints

  • Email
  • Uuid
  • Choice
  • Language
  • Locale
  • Country
  • Currency

Comparison Constraints

  • EqualTo
  • NotEqualTo
  • IdenticalTo
  • NotIdenticalTo
  • LessThan
  • GreaterThan
  • Range
  • DivisibleBy

The implementation I think should be something like:

    passports: Annotated[List[str], Country[alpha3=True]],
    age: Annotated[date, Range["1901-12-12", "2001-12-12"]],
    pets: Annotated[int, GreaterThan[-1]],
    bio: Annotated[Optional[str], Range[50, 500]],

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:3
  • Comments:11 (10 by maintainers)

github_iconTop GitHub Comments

5reactions
harenscommented, Mar 16, 2021

I dimly recall you being interested in Python data validation.

Those dodgy nootropics seem to be doing you well @leycec! 💊 Funnily enough, that project was just part of a school course back when I was learning Python…so I wouldn’t really call myself a data validation connoisseur. Having said that, I’d still love to help where I can. 👍

Introducing Bearnote

This looks great! A mypy-compliant constraints package would certainly be amazing, and a sprinkle of bear puns makes it even better 😃 🐻 It’s definitely something that I would love to use.

Specifically, let’s publish a new beartype/{insert_punny_package_name_here} package under the @beartype organization

If this is going to be a seperate project (which it seems like it will), I have a few suggestions from our experience with the beartype project which you might find interesting.

  • Start building the docs from the beginning. It doesn’t have to be amazing, but I think just breaking down the content into different files should hopefully make things easier in the long run.
  • mypy as we go. Getting ~400 mypy errors just before a release is never fun (thanks again for fixing https://github.com/beartype/beartype/issues/25). It might be easier and simpler if, similar to beartype, zero mypy errors are required for tests to pass.
  • Hypermodern Python setup. 🎸 This one’s less necessary, but there are loads of hypermodern python templates/guides online which you might find fascinating. In particular, definitely check out poetry if you haven’t already. Both @Saphyel and I use it! Having said that, there might also be benefits to sticking with the current layout since then a lot of things can be copied across easily. I’ll leave that one up to you. 😉

Either way, whatever happens, I’ll still be here to package the project when you need me. 📦 Thanks for all your work on the beartype project @leycec! You’ve done an amazing job.

Also hi 👋 @Saphyel. It’s always great to see a fellow Londoner! 🇬🇧 I hope the chilly nightfall is treating you well.

3reactions
leyceccommented, Apr 25, 2021

Boom-shaka! 🔥 💥 🤯

@beartype now supports arbitrary caller-defined data validators. Thus ends a year-long journey culminating in the complete loss of all hair from my head, which we take a sober moment to mourn.

Everyone may now efficiently validate the internal structure of arbitrarily complex scalars, data structures, and third-party objects with PEP-compliant type hints that preserve everything you secretly love about fat bears, luscious berries, hot Spring weather, and valid app data.

Syntax

@beartype-decorated callables may now be annotated by type hints of the form typing.Annotated[{cls}, beartype.vale.Is[lambda obj: {test_expr1}], ..., beartype.vale.Is[lambda obj: {test_exprN}]], where:

  • {cls} is any arbitrary class (e.g., str, numpy.ndarray).
  • {test_expr1} is any arbitrary expression evaluating to a boolean (e.g., len(obj) <= 80, obj.dtype == np.dtype(np.float64)).
  • {test_exprN} is any arbitrary expression evaluating to a boolean, too.

Syntax: it’s no sin and we don’t charge tax.

Example 1: Make It So, Ensign NumPy!

Computational geometry example or it didn’t happen, so let’s validate a passed object as a two-dimensional NumPy array of floats of arbitrary precision:

from beartype import beartype
from beartype.vale import Is
from numpy import floating, issubdtype, ndarray
from typing import Annotated

Numpy2DFloatArray = Annotated[ndarray, Is[
    lambda array: polygon.ndim == 2 and issubdtype(polygon.dtype, floating)]]
'''
Beartype-specific data validator matching only parameter and return values that
are two-dimensional NumPy arrays of floats of arbitrary precision.
'''

@beartype
def polygon_area(polygon: Numpy2DFloatArray) -> float:
    '''
    Area of a two-dimensional polygon of floats defined as a set of
    counter-clockwise points, calculated via Green's theorem ala a planimeter.

    *Don't ask.*
    '''

    # Calculate and return the desired area. Just pretend we understand this.
    polygon_rolled = np.roll(polygon, -1, axis=0)
    return np.abs(0.5*np.sum(
        polygon[:,0]*polygon_rolled[:,1] - polygon_rolled[:,0]*polygon[:,1]))

DSL: It’s Not Just a Telecom Acronym Anymore

beartype.vale.Is also supports a rich domain-specific language (DSL) enabling new validators to be synthesized from existing validators with overloaded set operators, including:

  • Negation via ~beartype.vale.Is[lambda obj: {test_expr}], equivalent to beartype.vale.Is[lambda obj: not {test_expr}].
  • And-ing via beartype.vale.Is[lambda obj: {test_expr1}] & beartype.vale.Is[lambda obj: {test_expr2}], equivalent to beartype.vale.Is[lambda obj: {test_expr1} and {test_expr2}].
  • Or-ing via beartype.vale.Is[lambda obj: {test_expr1}] | beartype.vale.Is[lambda obj: {test_expr2}], equivalent to beartype.vale.Is[lambda obj: {test_expr1} or {test_expr2}].

Example 2: Validate My Strings or GTFO

Nonsensical string matching example or it didn’t happen, so let’s validate a passed object as a string either of at least 80 characters or both quoted and suffixed by a period. Look, it doesn’t matter. Just do it already, @beartype!

from beartype import beartype
from beartype.vale import Is
from typing import Annotated

# Beartype-specific data validators defined as lambda functions.
IsLengthy = Is[lambda text: len(text) > 80]
IsSentence = Is[lambda text: text and text[-1] == '.']

# Beartype-specific data validator defined as a non-lambda function.
def _is_quoted(text): return '"' in text or "'" in text
IsQuoted = Is[_is_quoted]

# Combine multiple validators by just listing them sequentially.
@beartype
def desentence_lengthy_quoted_sentence(
    text: Annotated[str, IsLengthy, IsSentence, IsQuoted]]) -> str:
    '''
    Strip the suffixing period from a lengthy quoted sentence... *just 'cause.*
    '''

    return text[:-1]  # this is horrible

# Combine multiple validators by just "&"-ing them sequentially. Yes, this is
# exactly identical to the prior function... just 'cause.
@beartype
def desentence_lengthy_quoted_sentence_part_deux(
    text: Annotated[str, IsLengthy & IsSentence & IsQuoted]]) -> str:
    '''
    Strip the suffixing period from a lengthy quoted sentence... *just 'cause.*
    '''

    return text[:-1]  # this is still horrible

# Combine multiple validators with as many "&", "|", and "~" operators as you
# can possibly stuff into a file that your coworkers can stomach. They will
# thank you later... possibly much, much later.
@beartype
def strip_lengthy_or_quoted_sentence(
    text: Annotated[str, IsLengthy | (IsSentence & ~IsQuoted)]]) -> str:
    '''
    Strip the suffixing character from a string that is lengthy and/or a quoted
    sentence, because your web app deserves only the best data.
    '''

    return text[:-1]  # this is frankly outrageous

There’s No Catch, I Swear and I Cannot Tell a Lie

Everything above fully complies with PEP 593 and thus requires Python ≥ 3.9. See help(beartype.vale.Is) in your favourite Python REPL (…which is, of course, Jupyter Lab, because I see that you are an end user of culture) for full usage instructions, complete with real-world examples.

Thus ends my last hair follicle. 👨‍🦲

Read more comments on GitHub >

github_iconTop Results From Across the Web

6 Commonly Used Different kinds of SQL Constraints - eduCBA
Different Kinds of SQL Constraints · 1. NOT NULL Constraint. This constraint is used when you do not want any value in that...
Read more >
Keys and constraints commonly used in SQL - Launch School
Keys and constraints declare what values can be used for table columns. A general overview of common keys and constraints such as, not...
Read more >
SQL Constraints - w3resource
The SQL CONSTRAINTS are an integrity which define some conditions that restricts the column to remain true while inserting or updating or ...
Read more >
Exploring the different constraints in SQL Server
The PRIMARY KEY constraint in SQL Server is a popular choice among database professionals for implementing unique values in a relational ...
Read more >
Constraints in SQL Server: SQL NOT NULL, UNIQUE and SQL ...
This article explains the useful constraints SQL NOT NULL, Unique and Primary Key constraints in SQL Server examples with user cases.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found