I use jedi-vim for completion and it does the thing pretty well. But for some reason I have troubles with completion for parent objects.
For example:
class A:
variable = 1
class B(A):
# Won't find any pattern here, only __builtin__.vars
var # here I hit <C-space>
Is there any settings I should add in my .vimrc or it's just how jedi works? I also dig some issue tracker and didn't find something useful.
Speaking as the author of Jedi: This is something that has never really been supported in Jedi. It might have worked, but it was definitely never tested. Please add an issue to the tracker.
It's a bit similar to https://github.com/davidhalter/jedi/issues/585. This is something that isn't completable in a "normal" way. It's rather something that, because of its semantics, can (should?) be enabled.
It works very well for me.
But I use a different version of the Jedi.
My bundle is here: https://github.com/FBruynbroeck/jedi-vim
(Attention, at the end of the class B, you wrote a ';' instead of ':')
Related
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.
For example:
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render('data.html', items = [])
It yields the following Pylint error:
warning (W0223, abstract-method, MainHandler) Method 'data_received' is abstract in class 'RequestHandler' but is not overridden
I understand that somehow it wants me to override this data_received method, but I do not understand why, and what it is for?
This is actually a problem with Pylint that's sort of unavoidable with the nature of Python.
The RequestHandler class has a lot of methods that act as hooks you can override in order to do different things, but only some of those hooks may actually be called, depending on your application's code. To make sure you're implementing everything you're supposed to when you're using certain functionality, the default data_received implementation throws a NotImplementedError that will get triggered when you do something that expects your class to have a custom implementation.
Normally this isn't any kind of issue because Python lets you have code paths that fail and doesn't throw any errors. Because Pylint tries to "help" make sure you've done everything you're supposed to, it's seeing that NotImplementedError throw and is warning you that you could trigger it depending on what you do.
The real problem is that because Python is an interpreted language, it's hard for a tool like Pylint to look at your code and make sure it's "safe". Python gives you a lot of flexibility and power, but in turn you bear the burden of keeping your program's logic straight in your head and knowing what possible problems are actually problems, and what aren't.
Luckily, Pylint is aware of its own limitations and gives you nice tools to disable extraneous warnings. Add the comment line
# pylint: disable=W0223
right before your class definition and the warning should stop popping up for this instance while leaving everything else alone.
I am running into the same issue as the OP, except my PyCharm (2018.3.4) seems not to be using Pylint, but its own inspection engine. I managed to solve a similar issue with the similar trick as R Phillip Castagna suggested:
# noinspection PyAbstractClass
class XyzRequestHandler(tornado.web.RequestHandler):
def prepare(self):
print('-' * 100)
self.set_header('Access-Control-Allow-Origin', '*')
def print_n_respond(self, result):
response = json.dumps(result)
print('responding with:\n', response)
print()
self.write(response)
Here is a list of PyCharm's inspections.
Introduction
Pydev is a great eclipse plugin that let us write python code easily.
It can even give autocompletion suggestion when I do this:
from package.module import Random_Class
x = Random_Class()
x. # the autocompletion will be popped up,
# showing every method & attribute inside Random_Class
That is great !!!
The Problem (And My Question)
However, when I don't use explicit import, and use __import__ for example, I can't have the same autocompletion effect.
import_location = ".".join(('package', 'module'))
__import__(import_location, globals(), locals(), ['*'])
My_Class = getattr(sys.modules[import_location], 'Random_Class')
x = My_Class()
x. # I expect autocompletion, but nothing happened
Question: is there any way (in pydev or any IDE) to make the second one also
show autocompletion?
Why do I need to do this?
Well, I make a simple MVC framework, and I want to provide something like load_model, load_controller, and load_view which is still work with autocompletion (or at least possible to work)
So, instead of leave users do this (although I don't forbid them to do so):
from applications.the_application.models.the_model import The_Model
x = The_Model()
x. # autocompletion works
I want to let users do this:
x = load_model('the_application', 'the_model')()
x. # autocompletion still works
The "applications" part is actually configurable by another script, and I don't want users to change all of their importing model/controller part everytime they change the configuration. Plus, I think load_model, load_controller, and load_view make MVC pattern shown more obvious.
Unexpected Answer
I know some tricks such as doing this (as what people do with
web2py):
import_location = ".".join(('package', 'module'))
__import__(import_location, globals(), locals(), ['*'])
My_Class = getattr(sys.modules[import_location], 'Random_Class')
x = My_Class()
if 0:
from package.module import Random_Class
x = Random_Class()
x. # Now autocompletion is going to work
and I don't expect to do this, since it will only add unnecessary
extra work.
I don't expect any don't try to be clever comments. I have enough of them
I don't expect dynamic import is evil comments. I'm not a purist.
I don't expect any just use django, or pylons, or whatever comments. Such as comments even unrelated to my question.
I have done this before. This may be slightly different from your intended method, so let me know if it doesn't apply.
I dynamically import different modules that all subclass a master class, using similar code to your example. Because the subclassing module already imports the master, I don't need to import it in the main module.
To get highlighting, the solution was to import the master class into the main module first, even though it wasn't used directly. In my case it was a good fallback if the particular subclass didn't exist, but that's an implementation detail.
This only works if your classes all inherit from one parent.
Not really an answer to my own question. However, I can change the approach. So, instead of provide "load_model()", I can use relative import. Something like this:
from ..models.my_model import Model_Class as Great_Model
m = Great_Model()
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.
I know what's the standard way to document functions, classes and modules, but how do I document packages - do I put a docstring in __init__.py, or something else?
Yes, just like for a function or class comment, the first item in the __init__.py file should be a comment string:
"""
This is the xyz package.
"""
Now if you import the package, and use help(package), you will see your docstring. See more here: http://www.python.org/dev/peps/pep-0257/
See PEP257
A package may be documented in the module docstring of the __ init __.py file in the package directory.
Documenting is a good idea, so long as you don't document something obvious in your code
Try to understand that most people reading your source will understand python, so commenting or documenting lines like this is pointless:
a = 1 #this assigns 1 to a
But commenting or documenting a rather complicated function or class is a good idea.
General rule of thumb: Imagine the next person to work on your code is a Axe wielding maniac and they know where you live.
That way you will always leave "helpful" comments/doc's