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

Optional typing compatibility #336

Open
ASMfreaK opened this issue Jul 30, 2017 · 7 comments
Open

Optional typing compatibility #336

ASMfreaK opened this issue Jul 30, 2017 · 7 comments

Comments

@ASMfreaK
Copy link
Contributor

mypy complains about functions wrapped with plumbum.cli.Predicate:
error: Invalid type "..."
An example:

from plumbum import cli
@cli.Predicate
def GummyBear(n):
    if not n.startswith('gummybear'):
        raise ValueError('{} is not a gummybear!'.format(n))
    return n

class GummyConsumer(cli.Application):
    def main(self, bear: GummyBear):
        print('MUNCH MUNCH MUNCH')
$ mypy gummy.py
gummy.py:1: error: Cannot find module named 'plumbum'
gummy.py:1: note: (Perhaps setting MYPYPATH or using the "--ignore-missing-imports" flag would help)
gummy.py:9: error: Invalid type "gummy.GummyBear"

This should be made consistent

@ASMfreaK
Copy link
Contributor Author

ASMfreaK commented Jul 30, 2017

A quick hack that I'm using for now:

from plumbum import cli
class GummyBear(str):
    def __new__(cls, tids: str):
        if not n.startswith('gummybear'):
            raise ValueError('{} is not a gummybear!'.format(n))
        return n

class GummyConsumer(cli.Application):
    def main(self, bear: GummyBear):
        print('MUNCH MUNCH MUNCH')
$ python gummy_new.py gummybear
MUNCH MUNCH MUNCH
$ python gummy_new.py gummybe
Error: Argument of bear expected to be <class '__main__.GummyBear'>, not 'gummybe':
    ValueError('gummybe is not a gummybear!',)
------
Usage:
    gummy_new.py [SWITCHES] bear

Meta-switches
    -h, --help         Prints this help message and quits
    --help-all         Print help messages of all subcommands and quit
    -v, --version      Prints the program's version and quits

$ mypy gummy_new.py
gummy_new.py:2: error: Cannot find module named 'plumbum'
gummy_new.py:2: note: (Perhaps setting MYPYPATH or using the "--ignore-missing-imports" flag would help)

you can see it in my repo

@ASMfreaK ASMfreaK changed the title plumbum.cli.Predicate and mypy compatibility Optional typing compatibility Aug 25, 2017
@ASMfreaK
Copy link
Contributor Author

Traceback (most recent call last):
  File "gummy.py", line 12, in <module>
    GummyConsumer.run()
  File "plumbum/cli/application.py", line 480, in run
    ordered, tailargs = inst._validate_args(swfuncs, tailargs)
  File "plumbum/cli/application.py", line 431, in _validate_args
    positional[args_names.index(item)] = m.annotations[item]
ValueError: 'return' is not in list

This traceback is triggered if main() of cli.Application has a typed return i.e.:

class GummyConsumer(cli.Application):
    def main(self, bear: GummyBear) -> None:
        print('MUNCH MUNCH MUNCH')

This should be sorted out somehow for #334 for full typing information.

@henryiii
Copy link
Collaborator

henryiii commented Aug 27, 2017

I'm planning on looking at this eventually, but feel free to investigate, you might be faster!

I'm not sure what the fix would be; a function is not a type, so it is invalid for MyPy. Your workaround is of course reasonable, but don't know of a simpler way.

@henryiii
Copy link
Collaborator

Correction: the most recent problem should be an easy fix. Try the mypy branch.

@henryiii
Copy link
Collaborator

henryiii commented Aug 27, 2017

It might be possible for Predicate to transform:

@cli.Predicate
def GummyBear(n) -> str:
    if not n.startswith('gummybear'):
        raise ValueError('{} is not a gummybear!'.format(n))
    return n

to

GummyBear = type('GummyBear', str, '__new__':...)

@ASMfreaK
Copy link
Contributor Author

No, I don't think this will work. Mypy is very static and won't understand (at least for now) the runtime type creation. For now, we should use the class-__new__ workaround as mypy developers are yet to agree on decorators annotations (python/mypy#3157), so I guess this issue is blocked until they are done

@henryiii
Copy link
Collaborator

@ASMfreaK, yes, I played around with MyPy and realized that wouldn't work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants