facebook / pyre-check Goto Github PK
View Code? Open in Web Editor NEWPerformant type-checking for python.
Home Page: https://pyre-check.org/
License: MIT License
Performant type-checking for python.
Home Page: https://pyre-check.org/
License: MIT License
macOS Sierra 10.12.6
using python's installed with brew:
❯ pip3 install pyre-check
Collecting pyre-check
Could not find a version that satisfies the requirement pyre-check (from versions: )
No matching distribution found for pyre-check
❯ pip3.6 install pyre-check
Collecting pyre-check
Could not find a version that satisfies the requirement pyre-check (from versions: )
No matching distribution found for pyre-check
❯ pip2 install pyre-check
Collecting pyre-check
Could not find a version that satisfies the requirement pyre-check (from versions: )
No matching distribution found for pyre-check
You are using pip version 9.0.3, however version 10.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
❯ ll $(which pip3)
lrwxr-xr-x 1 leigh.schrandt admin 31B Apr 22 00:29 /usr/local/bin/pip3 -> ../Cellar/python/3.6.5/bin/pip3
❯ ll $(which pip2)
lrwxr-xr-x 1 leigh.schrandt admin 36B Apr 23 15:47 /usr/local/bin/pip2 -> ../Cellar/python@2/2.7.14_3/bin/pip2
similar to #5
The documentation shows pyre init
generates a .pyre_configuration
, but there is no information on how to set the values, or what configs exist.
For example, I don't know how to exclude a particular directory, and by default pyre recursively checks a virtualenv in my project root, spitting out a ton of errors in standard libraries. For example
venv/lib/python3.6/site-packages/pip/_internal/configuration.py:212:12 Undefined name [18]: Global name `pip` is undefined.
My company already has a largely type checked code base and requires all new modules to type-check,
so we'd like to require pyre-strict
on all new modules/existing code
There is some legacy code that doesn't type-check and it would be nice to be able to configure that on a per-file basis.
Is there a way to do this currently and if not would this be something appropriate for this project?
PEP 484 defines an optional syntax for supporting type annotations for Python 2 code, and PEP 526 also refers to support for Python 2 by way of stub files.
Is there any chance that Pyre will support type-checking Python 2-compatible code?
If not, it would be good to more explicitly document the supported versions of Python on the web site or in the documentation.
src/foo.py
:
#!/usr/bin/env python3
from typing import List
def f(s: str) -> List[int]:
return [ch for ch in s]
assert f("foo") == ["f", "o", "o"]
The code should fail typechecking, since f
returns a List[str]
but is annotated as returning List[int]
.
Output from pyre and mypy respectively:
$ pyre check
No type errors found
$ mypy src
src/foo.py:4: error: List comprehension has incompatible type List[str]; expected List[int]
Hi,
I am trying out pyre, but the incremental mode does not seem to be detecting changes after the first run.
Here is the sample file I am using
# my_lib/sample.py
class Foo:
def __init__(self) -> None:
self.prop_ = "bar"
class Bar:
def __init__(self, foo: Foo) -> None:
self.prop = "hello " + foo.prop
When I run pyre
the first time, I get the error as expected, but even if I update the file, the server seems to using the old state of the file.
$ pyre
ƛ Server not running at `.`. Starting...
ƛ Server initializing...
ƛ Found 1 type error!
my_lib/sample.py:8:31 Undefined attribute [16]: `Foo` has no attribute `prop`.
$ sed -i -e 's/foo\.prop/foo.prop_/' my_lib/sample.py
$ pyre
ƛ Waiting for server...
ƛ Found 1 type error!
my_lib/sample.py:8:31 Undefined attribute [16]: `Foo` has no attribute `prop`.
$ pyre check
ƛ No type errors found
Restarting the server or using check
works, but I could not find a way to use the incremental mode yet.
Any idea?
Thanks.
$ cat .pyre_configuration
{
"binary": "/home/daniel/.asdf/installs/python/3.6.2/bin/pyre.bin",
"source_directories": [
"."
],
"typeshed": "/home/daniel/.asdf/installs/python/3.6.2/lib/pyre_check/typeshed/stdlib/"
}
$ uname -r
4.16.8-1-ARCH
$ sysctl fs.inotify
fs.inotify.max_queued_events = 16384
fs.inotify.max_user_instances = 128
fs.inotify.max_user_watches = 100000
$ lsof | grep inotify | wc -l
1468
❯ pyre check
ƛ Found 1 type error!
test.py:5:4 Incompatible return type [7]: Expected `str` but got `None`.
❯ cat test.py
a: int = None
def foobar() -> str:
return None
Why is a:int = None
valid?
(venv) C:\progr\py3\pyre>pip3 install pyre-check
Collecting pyre-check
Could not find a version that satisfies the requirement pyre-check (from versions: )
No matching distribution found for pyre-check
Just so interested as the news pop up, I tried to install pyre-check immediately , but on the first run, it shows up a weird error on syntax error and after a while searching, I found out this only supports 3.6+ at the moment - when my version is 3.5.
Maybe should add one line or two on README that pyre only support 3.6+ for now? That would definitely helpful for newcomers.
Btw, I'm installing Python 3.6 to test it out,
Thanks for the great tool!
My project has an executable script that has no extension, it just has #!/usr/bin/env python3
at the top.
Currently pyre provides no way to check it. It would be great if it could do one of:
This code clearly has a type error (and fails at runtime: TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'str'
):
def foo(x : int) -> str:
return str(x ** x)
x = foo('hi')
running pyre check
, however, returns No type errors found
... Not sure how to find my pyre
version ... I just installed it via pip
10.0.1 with Python 3.6.5. I get the same error when x
isn't used within foo
, which was the original code (which, of course, doesn't actually fail because x
isn't used) that I was trying with pyre
:
def foo(x : int) -> str:
return 'hi'
x = foo('hi')
Here's a program that throws a type error when there is not one (AFAICS?):
import boto3
def bug() -> str:
boto3
return "bananas"
Throws:
$ pyre restart
ƛ No server running
ƛ Server not running at `.`. Starting...
ƛ Server initializing...
ƛ No servers running
ƛ Found 1 type error!
bug.py:5:4 Undefined name [18]: Global name `boto3` is undefined.
boto3
is clearly not undefined.
I pip installed pyre onto a virtual environment my Ubuntu 16.04 machine and attempting to run the pyre command is immediately met with a syntax error. Error message below
Traceback (most recent call last):
File "/home/emilior/Desktop/showdown/dev_work/env/bin/pyre", line 7, in <module>
from pyre_check.pyre import main
File "/home/emilior/Desktop/showdown/dev_work/env/lib/python3.5/site-packages/pyre_check/__init__.py", line 22, in <module>
from . import buck
File "/home/emilior/Desktop/showdown/dev_work/env/lib/python3.5/site-packages/pyre_check/buck.py", line 11, in <module>
from . import log
File "/home/emilior/Desktop/showdown/dev_work/env/lib/python3.5/site-packages/pyre_check/log.py", line 64
_terminate: bool = False
Hi, this tool looks promising but I am puzzled to see no references or comparisons to https://github.com/python/mypy. Could you share your reasons for developing a new typechecker instead of contributing to mypy?
It is very common for functions to return a type or None. In typescript you can say string | null
and the checker will warn you where you forgot to defend against potential null instances. How do you indicate that something may be a type or None
?
Are there any plans for a type definition repository, like http://definitelytyped.org/ for TypeScript? This would likely improve community adoption dramatically.
Currently the documentation says that stubs can be added via a *.pyi
file in the same folder as the source. A different mechanism may be needed for handling libraries (e.g. for TypeScript you can add a library with npm install --save leaflet
and then import the types with npm install --save @types/leaflet
).
Trying to run Pyre on Zulip, I get the following errors (among many others):
zthumbor/loaders/helpers.py:64:11 Undefined name [18]: Global name `six` is undefined.
zthumbor/loaders/helpers.py:64:20 Undefined name [18]: Global name `six` is undefined.
zthumbor/loaders/helpers.py:70:11 Undefined name [18]: Global name `six` is undefined.
zthumbor/loaders/helpers.py:70:20 Undefined name [18]: Global name `six` is undefined.
This puzzles me because six
is in typeshed -- which Pyre is supposed to refer to, right? In fact, here's the relevant import line:
from six.moves.urllib.parse import urlparse, parse_qs
and indeed that module, and those names within it, are there in typeshed.
I don't have any good ideas for what's going wrong in this instance. If there isn't an obvious (to you as the Pyre developers) thing that this could be, I can try refining out a minimal repro case.
Running make test
on OS X results in a bunch of errors from temporary paths.
This is primarily for continuous integration, so that check fails (does not return 0) if there are errors. Adding an configuration value to make it fail in case of errors would solve the issue.
After running and killing pyre a few times it appears I'm left with processes tailing server.stdout. Is this expected?
Ians-MacBook-Air:pymuscle iandanforth$ pyre
ƛ Server not running at `.`. Starting...
ƛ Server initializing...
ƛ Found 1 type error!
foo.py:2:4 Incompatible return type [7]: Expected `int` but got `float`.
Ians-MacBook-Air:pymuscle iandanforth$ pyre stop
ƛ No servers running
ƛ No server running
Ians-MacBook-Air:pymuscle iandanforth$ pyre kill
ƛ No server running
Ians-MacBook-Air:pymuscle iandanforth$ ps aux | grep pyre
iandanforth 78480 0.0 0.0 4267744 416 ?? S 12:28PM 0:00.00 tail -f ./.pyre/server/server.stdout
iandanforth 78460 0.0 0.0 4276960 416 ?? S 12:28PM 0:00.00 tail -f ./.pyre/server/server.stdout
iandanforth 78439 0.0 0.0 4268768 416 ?? S 12:28PM 0:00.00 tail -f ./.pyre/server/server.stdout
iandanforth 78389 0.0 0.0 4276960 416 ?? S 12:28PM 0:00.00 tail -f ./.pyre/server/server.stdout
iandanforth 78348 0.0 0.0 4267744 416 ?? S 12:27PM 0:00.01 tail -f ./.pyre/server/server.stdout
iandanforth 80211 0.0 0.0 4267752 672 s000 R+ 12:37PM 0:00.01 grep pyre
iandanforth 80145 0.0 0.0 4275936 452 s000 S 12:37PM 0:00.01 tail -f ./.pyre/server/server.stdout
iandanforth 79700 0.0 0.0 4267744 452 ?? S 12:35PM 0:00.01 tail -f ./.pyre/server/server.stdout
iandanforth 79053 0.0 0.0 4268768 416 ?? S 12:31PM 0:00.00 tail -f ./.pyre/server/server.stdout
iandanforth 78988 0.0 0.0 4275936 416 ?? S 12:30PM 0:00.01 tail -f ./.pyre/server/server.stdout
iandanforth 78624 0.0 0.0 4267744 416 ?? S 12:28PM 0:00.00 tail -f ./.pyre/server/server.stdout
iandanforth 78585 0.0 0.0 4276960 416 ?? S 12:28PM 0:00.00 tail -f ./.pyre/server/server.stdout
iandanforth 78567 0.0 0.0 4268768 416 ?? S 12:28PM 0:00.01 tail -f ./.pyre/server/server.stdout
iandanforth 78549 0.0 0.0 4277984 416 ?? S 12:28PM 0:00.00 tail -f ./.pyre/server/server.stdout
iandanforth 78531 0.0 0.0 4267744 416 ?? S 12:28PM 0:00.00 tail -f ./.pyre/server/server.stdout
iandanforth 78510 0.0 0.0 4267744 416 ?? S 12:28PM 0:00.00 tail -f ./.pyre/server/server.stdout
python
: 3.5.2, 3.6.5
pyre
: 0.0.7 (from pip list
)
typeshed
: python/typeshed@226f055
Note: I'm not sure whether this is an expected consequence of # pyre-strict
, though it doesn't seem to match any of the documented differences from strict mode.
Given:
# pyre-strict
import pathlib
from typing import NamedTuple
# Also reproduces with class style syntax under Python 3.6
Complex = NamedTuple('Complex', (
('real', float),
('imaginary', float),
))
pathlib.Path('.')
Complex(4, 2)
Then pyre
emits:
$ pyre --typeshed /path/to/typeshed/ check
ƛ Found 2 type errors!
args.py:12:0 Too many arguments [19]: Call `pathlib.Path.__init__` expects 1 positional argument, 2 were provided.
args.py:14:0 Too many arguments [19]: Call `args.Complex.__init__` expects 1 positional argument, 3 were provided.
I'm guessing that this happens because neither pathlib.Path
nor the generated NamedTuple
class define an __init__
method, meaning that pyre
finds the definition on object
.
If you use return
in a generator, an incorrect TypeError is generated:
$ cat srcdir/genreturn.py
from typing import Iterable
def gen(x: int) -> Iterable[int]:
for i in range(x):
if i > 10:
return
else:
yield i
$ pyre --source-directory srcdir/ check
ƛ Setting up a .pyre_configuration file may reduce overhead.
ƛ Found 1 type error!
srcdir/genreturn.py:6:12 Incompatible return type [7]: Expected `Iterable[int]` but got `None`.
$ python --version
Python 3.7.0b4
$ pip freeze | grep pyre # related minor bug: "pyre --version" throws a TypeError
pyre-check==0.0.5
I looked through the website and in the repo, but I didn't find a list of configuration options for the .pyre_configuration
directory. The getting started guide mentions setting some config settings after running pyre init
, but I can't see to find anything other than that.
I just tried out Pyre on a work-in-progress library, and I'm getting a "global name is undefined" error. The global name in question is the top-level namespace of the library. I installed the library into my virtual environment with pip install -e
and am running Python 3.6.5.
bob@localhost:~/code/play/foo|⇒ git clone [email protected]:madedotcom/photon-pump.git
Cloning into 'photon-pump'...
</snip>
bob@localhost:~/code/play/foo|⇒ pip install -r photon-pump/requirements.txt
Collecting aiodns>=1.1.1 (from -r photon-pump/requirements.txt (line 1))
</snip>
bob@localhost:~/code/play/foo|⇒ pip install -r photon-pump/requirements-test.txt
Collecting aioresponses (from -r photon-pump/requirements-test.txt (line 1))
</snip>
bob@localhost:~/code/play/foo|⇒ cd photon-pump
bob@localhost:~/code/play/foo/photon-pump|master
⇒ pip install -e .
Obtaining file:///home/bob/code/play/foo/photon-pump
</snip>
Installing collected packages: photon-pump
Running setup.py develop for photon-pump
Successfully installed photon-pump
bob@localhost:~/code/play/foo/photon-pump|master
⇒ pip install pyre-check
Collecting pyre-check
Using cached https://files.pythonhosted.org/packages/e4/96/72a7048e5f340678c6eb48163b7bdc49926cdac2dff8bb5d935563e50b7f/pyre_check-0.0.5-py3-none-manylinux1_x86_64.whl
Installing collected packages: pyre-check
Successfully installed pyre-check-0.0.5
bob@localhost:~/code/play/foo/photon-pump|master
⇒ pyre --source-directory photonpump check
ƛ Setting up a .pyre_configuration file may reduce overhead.
ƛ Found 35 type errors!
photonpump/conversations.py:93:35 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:94:47 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:95:37 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:97:20 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:99:37 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:107:16 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:290:64 Incompatible parameter type [6]: Expected `Credential` but got `None`.
photonpump/conversations.py:292:18 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:292:35 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:300:14 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:308:15 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:309:34 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:347:64 Incompatible parameter type [6]: Expected `Credential` but got `None`.
photonpump/conversations.py:349:18 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:349:36 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:607:15 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:612:16 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:654:25 Incompatible parameter type [6]: Expected `UUID` but got `None`.
photonpump/conversations.py:673:14 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:691:15 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:692:34 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:698:12 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:701:17 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:704:28 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:707:28 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:709:16 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:716:12 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:738:25 Incompatible parameter type [6]: Expected `UUID` but got `None`.
photonpump/conversations.py:746:14 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:751:15 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:752:34 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:789:15 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/conversations.py:794:16 Undefined name [18]: Global name `photonpump` is undefined.
photonpump/messages.py:231:56 Incompatible parameter type [6]: Expected `typing.Optional[bytes]` but got `bytearray`.
photonpump/messages.py:278:8 Incompatible return type [7]: Expected `EventRecord` but got `typing.Union[Event, EventRecord]`.
bob@localhost:~/code/play/foo/photon-pump|master⚡
Hi,
I installed the pyre-check package using pip install, and tried starting it in a directory. The first time I started it worked fine, but after closing vscode the server shut down. I tried rebooting it it and kept getting this error:
ƛ Server not running at `.`. Starting...
ƛ Client exited with error code -5:
I removed all the init files in the directory, tried doing a new pyre init and keep getting the same error as soon as I try starting the server.
This is on a mac, Python 3.6, with the latest osx and visual studio code insider edition.
python
: 3.5.2, 3.6.5
pyre
: 0.0.7 (from pip list
)
typeshed
: python/typeshed@226f055
I would expect the following file to be free from errors:
# pyre-strict
import datetime
import dateutil.parser
def expect_datetime(dt: datetime.datetime) -> None:
print(dt)
expect_datetime(dateutil.parser.parse('2018-01-01'))
Yet pyre
reports an issue stemming from the return type of dateutil.parser.parse
(which is stubbed in the typeshed and should return a datetime.datetime
):
$ pyre --typeshed /path/to/typeshed/ --search-path /path/to/typeshed/third_party/ check
ƛ Found 1 type error!
dt.py:9:16 Incompatible parameter type [6]: Expected `datetime.datetime` but got `unknown`.
Running Pyre on a Django app (namely Zulip), I get a lot of error messages like this:
zerver/apps.py:12:4 Undefined name [18]: Global name `django` is undefined.
zerver/apps.py:21:11 Undefined name [18]: Global name `django` is undefined.
zerver/apps.py:22:12 Undefined name [18]: Global name `django` is undefined.
OK, I see in #27 that this is a funny way of saying Pyre can't find the module django
. But this message is completely baffling -- most of all, because the name django
doesn't appear on any of those lines!
Instead, the lines are
cache.clear()
...
if settings.POST_MIGRATION_CACHE_FLUSHING:
post_migrate.connect(flush_cache, sender=self)
The real issue, I'm guessing, is that cache
and settings
and post_migrate
are all imported from various submodules of django
.
The way mypy :P would handle this is to give an error on the actual import. If for some reason you want to only give an error if the import is actually used (but if it isn't used, wouldn't it be better to just remove the import?), it could be on the line where it's used... but the message should mention an identifier that's actually on the line it refers to.
$ python3.6 --version
Python 3.6.5
$ uname -a
Linux lahg 4.16.13-1-ARCH #1 SMP PREEMPT Thu May 31 23:29:29 UTC 2018 x86_64 GNU/Linux
$ python3.6 -m pip install pyre-check --user
Collecting pyre-check
Could not find a version that satisfies the requirement pyre-check (from versions: )
No matching distribution found for pyre-check
$ pip3.6 install pyre-check --user
Collecting pyre-check
Could not find a version that satisfies the requirement pyre-check (from versions: )
No matching distribution found for pyre-check
Similar to #11
When trying to typecheck mypy under pyre, I got a ton of type errors having to do with some of our visitors. I reduced it down to:
from typing import TypeVar, Generic
T = TypeVar('T')
class NodeVisitor(Generic[T]):
def visit_foo(self) -> T:
pass
class NodeVisitor(Generic[T]):
def visit_foo(self) -> T:
pass
# Works
class Bar(NodeVisitor[int]):
def visit_foo(self) -> int:
return 10
# Inconsistent override [15]: `visit_foo` overloads method defined in `foo.NodeVisitor` inconsistently.
class Foo(NodeVisitor[None]):
def visit_foo(self) -> None:
pass
Specializing the type parameter to int
works, but specializing it to None
fails.
So this is a really weird issue. This strange error seems to only be raised if...
Any
types.py
If any of those things are not true, the error doesn't happen.
Here's a complete test example:
vagrant@precise64:~$ python3.6 -m venv pyretest
vagrant@precise64:~$ cd pyretest/
vagrant@precise64:~/pyretest$ . bin/activate
(pyretest) vagrant@precise64:~/pyretest$ pip install pyre-check
... snip ...
Successfully installed pyre-check-0.0.7
(pyretest) vagrant@precise64:~/pyretest$ mkdir test
(pyretest) vagrant@precise64:~/pyretest$ cd test
(pyretest) vagrant@precise64:~/pyretest/test$ touch __init__.py
(pyretest) vagrant@precise64:~/pyretest/test$ vim types.py
(pyretest) vagrant@precise64:~/pyretest/test$ cat types.py
class Foo:
pass
class Any(Foo):
pass
(pyretest) vagrant@precise64:~/pyretest/test$ pyre check
ƛ Order is cyclic:
Edges:
... snip ...
Trace: `_ast.Delete` -> `_ast.stmt` -> `_ast.AST` -> `typing.Any` -> `types.Foo` -> `typing.Any`
Uncaught exception:
AnalysisTypeOrder.Cyclic
Raised at file "format.ml" (inlined), line 242, characters 35-52
Called from file "format.ml", line 469, characters 8-33
Called from file "format.ml", line 484, characters 6-24
ƛ Client exited with error code 1:
If the name of the file is something other than types.py, no error:
(pyretest) vagrant@precise64:~/pyretest/test$ mv types.py foo.py
(pyretest) vagrant@precise64:~/pyretest/test$ pyre check
ƛ No type errors found
If the name of the class is something other than "Any", no error:
(pyretest) vagrant@precise64:~/pyretest/test$ mv foo.py types.py
(pyretest) vagrant@precise64:~/pyretest/test$ vim types.py
(pyretest) vagrant@precise64:~/pyretest/test$ cat types.py
class Foo:
pass
class _Any(Foo):
pass
(pyretest) vagrant@precise64:~/pyretest/test$ pyre check
ƛ No type errors found
Or if the class Any
is a top-level class (i.e., not a subclass), no error:
(pyretest) vagrant@precise64:~/pyretest/test$ vim types.py
(pyretest) vagrant@precise64:~/pyretest/test$ cat types.py
class Foo:
pass
class Any:
pass
(pyretest) vagrant@precise64:~/pyretest/test$ pyre check
ƛ No type errors found
I have installed pyre-check in my pyenv virtualenv VSCode project.
Pyre is able to catch an error if I run it through the CLI, but the VSCode extension does not seem to be catching anything. There is no output in any of the problem/bug prompts either.
Here is an image describing the issue. VSCode doesn't show anything, but the CLI catches the error.
{
"binary": "/Users/christophepouliot/.pyenv/versions/spotify-discow-sync/bin/pyre.bin",
"source_directories": [
"."
],
"typeshed": "/Users/christophepouliot/.pyenv/versions/3.6.2/envs/spotify-discow-sync/lib/pyre_check/typeshed/stdlib/"
}
If I do pyre restart
in the CLI the VSCode linting will catch the error, but then if I change it to return a string it still lints it as an error. If I pyre restart
again it still shows an error (although I am returning a string and not an int, which is correct). If I close/reopen VSCode at this point the linting error goes away. Changing it back to returning an int shows no error again until I pyre restart
, and then this all starts again.
I added a .watchmanconfig but that did not help (Is this needed? I dont see it mentioned)
VSCode 1.23.1
Python 3.6.2 with pyenv virtualenv
VSCode Python version set to /Users/christophepouliot/.pyenv/versions/spotify-discow-sync/bin/python
Hey there, this is likely similar to my previous question-- sorry if it's annoying! :-)
I use gevent
in my project, and when running pyre check
I get the following error:
ƛ Found 1 type error!
mud/game.py:150:12 Undefined name [18]: Global name `gevent` is undefined.
I'm using a virtual environment, so I'm not sure if that should be specified as a location to look up libraries.. or if external libraries are supported. If there is a code comment I can add to hint "stop looking in this direction" that might also be helpful.
Thanks for making pyre-check!
python
: 3.5.2, 3.6.5
pyre
: 0.0.7 (from pip list
)
Given a file thing.py
:
def outer() -> str:
def inner(x: int, y: str) -> str:
return x
return inner(42, None)
outer()
# Copy of 'inner' to prove that it errors at the top level
def outer_inner(x: int, y: str) -> str:
return x
outer_inner(42, None)
I'd expect to get errors from the bad types in the nested inner
function. For reference, here's what mypy
(0.600) outputs:
$ mypy thing.py
thing.py:3: error: Incompatible return value type (got "int", expected "str")
thing.py:4: error: Argument 2 to "inner" has incompatible type "None"; expected "str"
thing.py:10: error: Incompatible return value type (got "int", expected "str")
thing.py:12: error: Argument 2 to "outer_inner" has incompatible type "None"; expected "str"
Yet while pyre
does not find errors in the top level equivalent function outer_inner
, it doesn't emit any errors about the nested function:
$ pyre check
ƛ Found 1 type error!
thing.py:2:4 Incompatible return type [7]: Expected `str` but got `int`.
It seems like pyre doesn't currently support PEP 561. In short, when looking for type annotations for imported packages, it should include packages in standard package locations that have a py.typed
marker file (with some additional complications). mypy currently implements the PEP.
Thanks!
I've got a base folder for my project, and I create the virtual env within it. I would like to scan the entire folder, but exclude the venv
folder I've created.
I wasn't able to see any suggestions in the pyre --help
list that matched what I was looking for.
Would it be expected to run pyre on each of the subfolders?
A variable of type List[Any]
should be compatible with an argument of type Sequence[str]
, because List
is a subtype of Sequence
and Any
is a subtype of anything, but pyre rejects it:
$ cat srcdir/seqany.py
from typing import Any, List, Sequence
def f1(lst: Sequence[str]) -> None:
pass
def f2() -> None:
lst: List[Any] = []
f1(lst)
$ pyre --source-directory srcdir/ --verbose check
...
srcdir/seqany.py:8:7 Incompatible parameter type [6]: Expected `Sequence[str]` but got `List[typing.Any]`.
When running the checking, if an external library is imported and has no type definition, it throws the following error:
Undefined name [18]: Global name `...` is undefined.
However, the docs only cover errors 14/15 and 16.
It would be useful to know what to do in this case, especially when it's a custom library with no type definitions, or how to configure pyre to silence the error.
In pyre-check/scripts/filesystem.py
, the systemfind
utility is run via the subprocess
module:
pyre-check/scripts/filesystem.py
Line 121 in 71d5d5b
find
is passed the -regextype
argument, but the BSD find
utility included with macOS does not understand this argument. The result is a slightly cryptic error:
$ pyre
ƛ Shared source directory is stale, updating...find: -regextype: unknown primary or operator
ƛ pyre was unable to locate a source directory. Ensure that your project is built and re-run pyre.
I haven't thoroughly tested, but it looks like the -regextype
argument can be removed for the regex used here. The -xtype
argument gives a similar error, but I believe it can be changed to type
since the behavior is the same for -type f
.
Making those two changes resolves the issue for me.
OS: OSX 10.13.2
Python: 3.6.4 (in pipenv managed virtual environment)
VSCode: 1.23.1
After installing the extension I get the following error in the 'Output' window within VSCode
[Error - 11:58:11] Starting client failed
Launching server using command pyre failed.
Running pyre
within the virtual env completes successfully and detects the sample type error.
Why does basic
type check?
import random
import string
def gen(allowed_chars: string, length: int) -> str:
''.join([random.choice(allowed_chars) for _ in range(1, length)])
def basic(length: int) -> str:
gen(string.ascii_letters + string.digits, length)
❯ pyre check
ƛ Found 1 type error!
source/lib/random_string.py:6:4 Incompatible return type [7]: Expected `str` but got `None`.
I tried strict mode on the module to no effect (unsurprisingly since its about Any
, not None
).
Does pyre have an equivalent to mypy's reveal_type(expr)
, which when checked displays the type of expr
? If not, this is a feature request and if so a documentation one :)
Do you plan adding support of binaries for Windows OS?
❯ cat Pipfile
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[dev-packages]
isort = "*"
yapf = "*"
pre-commit = "*"
pytest = "*"
pylama = "*"
codecov = "*"
coverage = "*"
pytest-cov = "*"
"boto3" = "*"
rope = "*"
[requires]
python_version = "3.6"
❯ pyre check
ƛ Found 1 type error!
source/lib/step_functions_client.py:14:0 Undefined import [21]: Could not find a module corresponding to import `boto3`.
When I run Pyre in an Emacs shell or compilation window the output starts with a bunch of gobbledygook:
�[?7l�[0G�[K�[1A�[?25l ƛ�[0m Waiting for server...�[0G�[K ƛ�[0m Finding external sources in `/Users/guido/src/mypy`...�[0G�[K ƛ�[0m Finding external sources in `/Users/guido/v36/lib/pyre_check/typeshed/stdlib`...�[0G�[K ƛ�[0m Parsing 1303 stubs and external sources...�[0G�[K ƛ�[0m Parsing 116 sources in `/Users/guido/src/mypy/mypy`...�[0G�[K ƛ�[0m Unable to parse 1 paths�[0G�[K ƛ�[0m Building type environment...�[0G�[K ƛ�[0m Adding environment information to shared memory...�[0G�[K ƛ�[0m Inferring protocol implementations...�[0G�[K ƛ�[0m Checking...�[0G�[K ƛ�[0m Processed 115 of 115 sources�[0G�[K�[31m ƛ�[0m Found 571 type errors!
�[?7h�[?25h�[?7hmypy/applytype.py:21:15 Incompatible parameter type [6]: Expected `typing.Sized` but got `Optional[List[mypy.types.TypeVarDef]]`.
``
Is there a way to disable this, or can you make it more Emacs-friendly? (Most utilities that do this these days somehow use a convention that Emacs shell mode understands, like ending each status line with `\r`, but Pyre seems to be using its own convention.)
The best I've been able to do is `pyre --noninteractive` but that just switches to a more traditional logging format; it feels there should be a flag to just silence it.
The following code produces some type mismatches (see comments inside the list comprehension at the end).
from typing import Iterable, Tuple, List
import time
class Record(object):
def __init__(
self,
parents: List[int] = [],
tags: List[str] = [],
owners: List[str] = [],
):
self.parents = parents
self.tags = tags
self.owners = owners
def _insert(*records: Iterable[Record],
name='records') -> Tuple[str, List[str]]:
query = 'foo'
values = [[
r.parents, # Error: [Pyre] Undefined attribute [16]: `Iterable[typing.Any]` has no attribute `parents`.
r.tags, # Error: [Pyre] Undefined attribute [16]: `Iterable[typing.Any]` has no attribute `tags`.
r.owners, # Error: [Pyre] Undefined attribute [16]: `Iterable[typing.Any]` has no attribute `owners`.
] for r in records]
return query, values
I fiddled with this for a while, but I couldn't find a solution. Is this a bug, or am I doing it the wrong way?
pyre
: 0.0.7 (from pip list
)
While the documentation does note that pyre
can be run either as a server or as a one-off check, pyre
's behaviour when a user misunderstands this leads to further confusion for the user rather than
Specifically, consider the following:
$ python3 -m venv venv
$ . venv/bin/activate
$ pip install pyre-check python-dateutil
$ cat thing.py
import dateutil.parser
$ pyre
ƛ Server not running at `.`. Starting...
ƛ Server initializing...
ƛ Found 1 type error!
thing.py:1:0 Undefined import [21]: Could not find a module corresponding to import `dateutil.parser`.
(Consider that the user might have more than just the one type error at this point, and that they therefore might not have actually seen the lines about starting a server)
At this point the user might realise (after reviewing the docs for third party stubs, or finding #43 (comment) etc.) that they need to add --search-path
to enable the third party stubs:
$ pyre --search-path=path/to/typeshed/third-party
thing.py:1:0 Undefined import [21]: Could not find a module corresponding to import `dateutil.parser`.
This output is quite confusing. The user believes that they have corrected for the lack of search-path
, yet are still seeing errors.
It would have been useful on the second run, which appears to only check with the running server for its results and not alter the search-path
to have errored about the search-path
being specified but unused.
An ideal error might be something like this:
$ pyre --search-path=path/to/typeshed/third-party
Pyre server is already running with a different search path.
To change the search path in use, run
pyre --search-path=path/to/typeshed/third-party restart
$
This would help the user better understand their interactions with pyre
as a client-server program as well as provide a solution to their immediate problem.
I'm assuming that the client is able to detect what search path is being used by the server and thus only emit this message when the search path is different. That would allow tooling to specify the (unchanged) search path on the command line. There is still a potential for some confusion from users around this, I'd be in favour of always erroring about unusable parameters if there's no way to check their current values.
I'd be in favour of something like this applying to all the command line options that experience a similar behaviour (i.e: are currently accepted but might not actually be used).
[root@c7-linpe-build ~]# pip3 install pyre-check
Collecting pyre-check
Downloading https://files.pythonhosted.org/packages/e4/96/72a7048e5f340678c6eb48163b7bdc49926cdac2dff8bb5d935563e50b7f/pyre_check-0.0.5-py3-none-manylinux1_x86_64.whl (7.7MB)
100% |████████████████████████████████| 7.7MB 3.5MB/s
Installing collected packages: pyre-check
Successfully installed pyre-check-0.0.5
[root@c7-linpe-build ~]# pyre
Traceback (most recent call last):
File "/usr/bin/pyre", line 7, in
from pyre_check.pyre import main
File "/usr/lib/python3.4/site-packages/pyre_check/init.py", line 151
**normals,
^
SyntaxError: invalid syntax
[root@c7-linpe-build ~]# rpm -qi python34
Name : python34
Version : 3.4.8
Release : 1.el7
[root@c7-linpe-build ~]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
The following code passes typechecking:
# pyre-strict
from typing import TypeVar
T = TypeVar('T')
def coerce(x: T) -> int:
1 + 'foo'
return x
In general it seems that functions with types involving generics are not typechecked.
For comparison, mypy produces the following errors:
poly.py:6: error: Unsupported operand types for + ("int" and "str")
poly.py:7: error: Incompatible return value type (got "T", expected "int")
Following #27, I added the site-packages folder in my conda env to the "search_path" in my .pyre-configuration
. This seems to have resolved my package lookup issues, but now pyre is unable to find top-level functions in numpy
:
"Undefined attribute [16]: Module numpy
has no attribute zeros
."
The relevant code looks like:
import numpy
...
a = np.zeros(b)
(failure points to the last line)
Python 3.6.5 :: Anaconda, Inc.
Ubuntu 16.04.4 LTS
Pyre version 0.0.6
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.