PTVS IntelliSense not working for Built-in Function - python

class Class:
def __init__(self, path):
self._path = path
string = open(self._path, 'r'). #HERE
When I try to type read() intelliSense says no completions.
However, I know open() function returns file object, which has read() function. I want to see all supported function after typing a dot.
PyCharm shows me recommanded function list, but PTVS does not support.
I want to know this is casual things in PTVS or only happening to me.
My current Python Enviroment is Anaconda 4.3.0 (Python 3.5.3)
How can I fix it?

We've already fixed the specific case of open for our upcoming update (not the one that released today - the next one), but in short the problem is that you don't really know what open is going to return. In our fix, we guess one of two likely types, which should cover most use cases.
To work around it right now, your best option is to assign the result of open to a variable and force it to a certain type using an assert statement. For example:
f = open(self._path, 'r')
import io
assert isinstance(f, io.TextIOWrapper)
f = open(self._path, 'rb')
import io
assert isinstance(f, io.BufferedIOBase)
Note that your code will now fail if the variable is not the expected type, and that the code for Python 2 would be different from this, but until you can get the update where we embed this knowledge into our code it is the best you can do.

Related

Pycharm: Code documentation differs between seemingly equal installations

A colleague of mine and I edit code from the same repository. Its a Python application using psycopg2 as a database driver to speak to PostgreSQL clusters. We are both decently new at this, so good documentation and doc support by the IDE is paramount to prevent mistakes.
To have autocompletion of methods, classes, functions and the likes the IDE needs to know what type of objects the variables are. As sometimes it is difficult for the IDE to determine this itself, you can usually use annotations of the syntax
myvar = functioncall() # type: <Class/Data type>
This defines myvar as the type given at the end of the line, and enables the IDE to autocomplete methods in myvar from the class/data type given.
In the following line, Pycharm could not determine the type of value that the methods returns:
with psycopg2.connect(dsn) as conn:
I took a look into the definition of psycopg2.connect() using Ctrl+q, and I got this printout:
psycopg2
def connect(dsn: Any = None,
connection_factory: Any = None,
cursor_factory: Any = None,
**kwargs: Any) -> None
Plus the whole documentation about the parameters, and ending with the note:
< Python 3.9 (venv39selected) >
The Python version we both use is 3.9, and venv39selected is the name of the venv that I use.
So I could see why the IDE could not determine the data type of the return value of connect, it doesn't document a return type.
However, after complaining to my colleague about the problem, he showed me his Ctrl+q popup, and in that, the following is printed:
psycopg2
def connect(dsn: Any | None = ...,
connection_factory: Any | None = ...,
cursor_factory: Any | None = ...,
**kwargs: Any) -> connection | connection
So he seems to have a different popup than me, one that allows his IDE to find the right return type for the variable. In all program versions, our systems and installations are the same. Python 3.9 on Windows, the same packages inside the venv, psycopg2 in version 2.9.3.
However, and that is the most interesting part: You can use Ctrl+mouseclick to enter any method/function definition. Entering the function definition of the connect method shows the same exact code for both our IDEs, and both are without the return type!
So the documentation shown in the Ctrl+q popup must come from somewhere else than from parsing the code shown using Ctrl+click. But from where? Where is that configured?

Keeping alias types simple in Python documentation?

I'm trying to use the typing module to document my Python package, and I have a number of situations where several different types are allowable for a function parameter. For instance, you can either pass a number, an Envelope object (one of the classes in my package), or a list of numbers from which an Envelope is constructed, or a list of lists of numbers from which an envelope is constructed. So I make an alias type as follows:
NumberOrEnvelope = Union[Sequence[Real], Sequence[Sequence[Real]], Real, Envelope]
Then I write the function:
def example_function(parameter: NumberOrEnvelope):
...
And that looks great to me. However, when I create the documentation using Sphinx, I end up with this horrifically unreadable function signature:
example_function(parameter: Union[Sequence[numbers.Real], Sequence[Sequence[numbers.Real]], numbers.Real, expenvelope.envelope.Envelope])
Same thing also with the hints that pop up when I start to try to use the function in PyCharm.
Is there some way I can have it just leave it as "NumberOrEnvelope". Ideally that would also link in the documentation to a clarification of what "NumberOrEnvelope" is, though even if it didn't it would be way better than what's appearing now.
I had the same issue and used https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autodoc_type_aliases, introduced in version 3.3.
In your sphinx conf.py, insert this section. It does not seem to make much sense at the first sight, but does the trick:
autodoc_type_aliases = dict(NumberOrEnvelope='NumberOrEnvelope')
Warning: It only works in modules that start with from __future__ import annotation
Note: If there is a target in the documentation, type references even have a hyperlink to the definition. I have classes, documented elsewhere with autoclass, which are used as types of function parameters, and the docs show the nice names of the types with links.
Support for this appears to be in the works.
See Issue #6518.
That issue can be closed by the recent updates to Pull Request #8007 (under review).
If you want the fix ASAP, you can perhaps try using that build.
EDIT: This doesn't quite work, sadly.
Turns out after a little more searching, I found what I was looking for. Instead of:
NumberOrEnvelope = Union[Sequence[Real], Sequence[Sequence[Real]], Real, Envelope]
I found that you can create your own compound type that does the same thing:
NumberOrEnvelope = TypeVar("NumberOrEnvelope", Sequence[Real], Sequence[Sequence[Real]], Real, Envelope)
This displays in documentation as "NumberOrEnvelope", just as I wanted.

Python: tell my IDE what type an object is

When I write a function in Python (v2.7), I very often have a type in mind for one of the arguments. I'm working with the unbelievably brilliant pandas library at the movemement, so my arguments are often 'intended' to be pandas.DataFrames.
In my favorite IDE (Spyder), when you type a period . a list of methods appear. Also, when you type the opening parenthesis of a method, the docstring appears in a little window.
But for these things to work, the IDE has to know what type a variable is. But of course, it never does. Am I missing something obvious about how to write Pythonic code (I've read Python Is Not Java but it doesn't mention this IDE autocomplete issue.
Any thoughts?
I don't know if it works in Spyder, but many completion engines (e.g. Jedi) also support assertions to tell them what type a variable is. For example:
def foo(param):
assert isinstance(param, str)
# now param will be considered a str
param.|capitalize
center
count
decode
...
Actually I use IntelliJ idea ( aka pyCharm ) and they offer multiple ways to specify variable types:
1. Specify Simple Variable
Very simple: Just add a comment with the type information behind the definition. From now on Pycharm supports autcompletition! e.g.:
def route():
json = request.get_json() # type: dict
Source: https://www.jetbrains.com/help/pycharm/type-hinting-in-pycharm.html
2. Specify Parameter:
Add three quote signs after the beginning of a method and the idea will autocomplete a docstring, as in the following example:
Source: https://www.jetbrains.com/help/pycharm/using-docstrings-to-specify-types.html
(Currently on my mobile, going to make it pretty later)
If you're using Python 3, you can use function annotations. As an example:
#typechecked
def greet(name: str, age: int) -> str:
print("Hello {0}, you are {1} years old".format(name, age))
I don't use Spyder, but I would assume there's a way for it to read the annotations and act appropriately.
I don't know whether Spyder reads docstrings, but PyDev does:
http://pydev.org/manual_adv_type_hints.html
So you can document the expected type in the docstring, e.g. as in:
def test(arg):
'type arg: str'
arg.<hit tab>
And you'll get the according string tab completion.
Similarly you can document the return-type of your functions, so that you can get tab-completion on foo for foo = someFunction().
At the same time, docstrings make auto-generated documention much more helpful.
The problem is with the dynamic features of Python, I use Spyder and I've used a lot more of python IDEs (PyCharm, IDLE, WingIDE, PyDev, ...) and ALL of them have the problem you stated here. So, when I want code completion for help I just instantiate the variable to the type I want and then type ".", for example: suppose you know your var df will be a DataFrame in some piece of code, you can do this df = DataFrame() and for now on the code completion should work for you just do not forget to delete (or comment) the line df = DataFrame() when you finish editing the code.

How to get PyCharm to auto-complete code in methods?

When I'm using a 3rd party l
ibrary such as boto, PyCharm seems to be able to auto-complete quite nicely
However, as soon as I define a function of my own, auto-complete breaks down inside that function. I understand why, since I can't give the function any type information about its arguments, so it can't guess how to auto-complete. Is there a way around this issue?
Edit
I tried using the docstring (for Python 2), but still no auto-complete
def delete_oldest_backups(conn, backups_to_keep, backup_description):
"""
delete_oldest_backups(EC2Connection, int, string)
"""
(Also tried boto.ec2.connection.EC2Connection instead of just EC2Connection)
You can use type hints: http://www.jetbrains.com/pycharm/webhelp/type-hinting-in-pycharm.html
def some_method(self, conn):
"""
#type conn: EC2Connection
"""
conn.<autocomplete>
You can specify the type information about the parameters of the function using Python 3 parameter and return value annotations. If you're using Python 2, you can also specify information in the function's docstring. PyCharm understands the format used by docstrings of binary modules in the standard library, for example:
"""
foo(int, string) -> list
Returns the list of something
"""
In order for PyCharm to recognize an instance of an object and retrieve all its methods, we have to use the following statements. But I think that both is a terrible way of wasting programming and run time.
assert isinstance(instanceX, ClassOfInstanceX)
instanceX.{#list of method/properties appears}
Alternatively, you can also use the class name will recall the method or property everytime you want to invoke it and pass in the instance to the self parameter. But this is too verbose, for my liking, esp for nested class
ClassOfInstanceX.{#list of method/properties appears}
# then you will have...
ClassOfInstance.method(instanceX, args...)
You can install the library via pyCharm "package manager".
Go to Settings -> Project Interpreter -> Python Interpreters
And in the Packages list, click on install and search for the library you want to install
Once installed, auto-complete will be available on editor.
Hope this is what you are looking for.

Eclipse pydev auto-suggestions don't work in some cases

My question is probably stupid and I hope somebody has succeeded in solving this issue.
Sometimes I cannot see right suggestions in auto-completion box (Eclipse 3.5.2, PyDev 1.5.7). For example:
import email
fp = open('my.eml', 'rb')
msg = email.message_from_file(fp)
msg now is a Message object. And functions like get_payload() works fine.
msg.get_payload()
But I don't get get_payload() in auto-completion list.
I think PyDev has no idea of what msg is, so it doesn't know what to show.
Maybe I should import something else, not only email module?
Thanks in advance!
I struggled with this question quite a bit too, until I came across this link. I used the second solution suggested in that link, and it works like a charm.
Basically you need to insert assert isinstance(msg, Message) after you get msg from the function call.
Chances are, the current PyDev build hasn't gone to a point to be able to extract from a function (message_from_file() in your case) to know what kind of object it returns in order to provide auto-completion hinting.
See http://sourceforge.net/projects/pydev/forums/forum/293649/topic/3697707.
Edit: I believe there is interest in PyDev to support the new Python 3 function syntax, PEP 3107, which will solve some of your problems ... in the future.
I know #type in docstring works. As in:
from collections import deque
def foo(a):
''' code completion sample
#type a: deque
'''
return a.popleft() # Code completion will work here
I have not been able to find a way to do it inline within code (except in ways mentioned elsewhere where you simply pretend to assign the variable an instance of a type) as in:
from collections import deque
def foo(a):
''' code completion sample '''
if false: a = deque()
return a.popleft() # Code completion will also work here
But I'm not fond of this method because it probably imposes some performance / code size penalty. I don't know / haven't checked if Python is smart enough to remove this assignment during compile time.
Thanks to SiSoie, here's a link to page explaining possibilities.

Categories