Skip to main content

Pretty comprehensive typehint evaluator, gives your Python functions that extra bit of zazz and illegibility they always needed.

Project description

exec_hints

Pretty comprehensive typehint evaluator to give you code that extra bit of zazz and illegibility it always needed

For all examples, here's the obvious prerequisite

from exec_hints import exec_hints, check_hints, _UnionType, Literal

Alternatively, you can just import exec_hints and use the module as a callable!

Let's start off small: you can specify a hint on an argument and it'll convert it

@exec_hints
def foo(arg:int):
    print(arg*arg)

foo('12')
>>> 144
@exec_hints
def foo(arg:set):
    print(arg, arg.issubset('123'))

foo('12')
>>> {'2', '1'} True
@exec_hints
def foo(arg:set[int]):
    print(arg, arg.issubset(range(10)))

foo('12')
>>> {1, 2} True

A single argument to dict will modify all values, 2 arguments means the first applies to keys, 2nd to values

@exec_hints
def foo(arg:dict[int]):
    print(arg, arg.keys())

foo({'a':'123',12:13.2})
>>> {'a': 123, 12: 13} dict_keys(['a', 12])

Works with Unions (more on that later)

@exec_hints
def foo(arg:set[int|str]):
    print(arg, arg.issubset(range(10)))

foo('1a2')
>>> {1, 'a', 2} False

If an iterable hint is provided with a number of arguments matching what was passed, each subhint will be applied to corresponding arguments

@exec_hints
def foo(arg:list[int,str,int]):
    print(arg, arg[::-1])

foo('1a2')
>>> [1, 'a', 2] [2, 'a', 1]

...and of course, we can nest these 😎

@exec_hints
def foo(arg:list[int,int|str,tuple[int|float|str]]):
    print(arg)

foo(('1','a',['1','2.67','b']))
>>> [1, 'a', (1, 2.67, 'b')]

If several options are given, it tries each in turn

@exec_hints
def foo(arg:list[int,int|str]|tuple[int|float|str]):
    print(arg)

#first fails because there are 2 subhints and 3 args provided
foo(['1','2.67','b'])
>>> (1, 2.67, 'b')
#first works!
foo(['1','2.67'])
>>> [1, '2.67']

You can pass your own functions in here, but they cant directly be used with | Blame Python, not me.

@exec_hints
def foo(arg:lambda x: x[::2]):
    print(arg)

foo('banana')
>>> bnn

There's a workaround for that tho! list|1 isnt supported by Python, so we have a class for that: Literal Accepts a callable or a literal (ok the class name isnt the best, accepting any suggestions) If it's callable, will try call on the arg, otherwise will just return itself

@exec_hints
def foo(arg:int|Literal(0)):
    print(arg)

foo('banana')
>>> 0

We can use it to chain builtins that wouldnt normally be allowed. Also note you can use it with [] syntax too

@exec_hints
def foo(arg:int|Literal[str.upper]):
    print(arg)

foo('banana')
>>> BANANA

This documentation would have to be a few miles long to cover all of this So here's a few examples:

@exec_hints
def foo(message:int|tuple[int]|list[0], dct:dict[int,tuple[str.lower]]):
    print(message)
    print(dct)

foo('a1',{'213':'BaNaNa','444':'BoBa'})
>>> [0, 0]
>>> {213: ('b', 'a', 'n', 'a', 'n', 'a'), 444: ('b', 'o', 'b', 'a')}

Uhh, it works on a lot of stuff :) Notably you can manipulate *args and **kwargs as normal. Works with defaults too, but it will try to apply the hint to the default provided

@exec_hints
def a(a,b:str.upper,c:tuple[int],d=12,*e:lambda x:map(str,x),f:int|Literal(-3)=3,**g:dict[str]):
    print(a,b,c,d,e,f,g)

a(1,'bb',['2','3'],4,5,banana=1,apple=2)
>>> 1 BB (2, 3) 4 ('5',) 3 {'banana': '1', 'apple': '2'}

You can typehint return values too 🎉

@exec_hints
def foo(arg:int|Literal(str.upper)) -> lambda x:tuple(reversed(x)):
    print(arg)
    return arg

print(foo('banana'))
>>> BANANA
>>> ('A', 'N', 'A', 'N', 'A', 'B')

Works with classes, including dataclasses. As of 0.1.4 it's a bit scuffed as the result is a function that calls the constructor of the class, but it works.

import exec_hints
from dataclasses import dataclass

@exec_hints
@dataclass
class Bot:
    alignment: bool
    serial: int
    name: str


print(Bot(123123, '12', 2))
>>> Bot(alignment=True, serial=12, name='2')

The check_hints function is useful for debugging or making sure your hints are correct. Works as you would expect it to similar to exec_hints, but will raise an error if the hint fails. Literal checks are also done via equality, or if the literal is callable, it will be called on the arg and checked for truthiness.

from exec_hints import check_hints

@check_hints
def foo(arg:int|Literal(str.upper)):
    print(arg)

foo('banana') # FAILS
foo('BANANA') # PASSES

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

exec_hints-0.1.4.tar.gz (6.0 kB view details)

Uploaded Source

Built Distribution

exec_hints-0.1.4-py2.py3-none-any.whl (5.3 kB view details)

Uploaded Python 2Python 3

File details

Details for the file exec_hints-0.1.4.tar.gz.

File metadata

  • Download URL: exec_hints-0.1.4.tar.gz
  • Upload date:
  • Size: 6.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.31.0

File hashes

Hashes for exec_hints-0.1.4.tar.gz
Algorithm Hash digest
SHA256 aa20466268e2b3e71b1ffc107521bf6f1ced4daec0b8c9ca059be2e2b1d99ce8
MD5 a683d4164ad32028166b3d7a77957741
BLAKE2b-256 72013f25aa3d4d5bef07777d239e2a49cf2a3f1e580708e3dbbc94d1b8764da5

See more details on using hashes here.

File details

Details for the file exec_hints-0.1.4-py2.py3-none-any.whl.

File metadata

  • Download URL: exec_hints-0.1.4-py2.py3-none-any.whl
  • Upload date:
  • Size: 5.3 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.31.0

File hashes

Hashes for exec_hints-0.1.4-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 c1a9bd34ffa7a5985552d97db39571874a58dc5cac56aa60fe5bffba58963ad1
MD5 657284b739f3ebb797ead393665c6ed6
BLAKE2b-256 6b26ea9f8806aa4132b92379b8527bc2b51c64eb6dc33492b18b3695a7091ea3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page