after spending hours in googling, I learned a lot, but did not find any close topic to the following:
I am currently programming on dynamically created classes via a factory method. The reason is, that the method names should be populated according to a separate yaml-file. It comes down to this problem:
def create_class_with_dynamic_fuction_name(fun_name):
def fun(self):
print "Hello, I am fun"
class X:
pass
setattr(X, fun_name, fun)
return X
Kls1= create_class_with_dynamic_fuction_name('my_function_name')
kls1= Kls1()
kls1.my_function_name()
This code works. However, if you have this code in the editor of sypder (aka. Spider IDE, spyderlib), the autocomplete will not show my_function_name in its context box. Neither is it possible to inspect it via Ctrl+I for easy retrieval of the docstring-help.
The same problem arises, if a class is created with type(classname, (), clsdict). In that case, one only finds mro inside the autocomplete-context-menu.
Also I found, that it is not a problem of the closure pattern above. You can do
def create_class_with_static_function_name():
def fun(self):
print "Hello, I am fun"
class X:
my_function_name = fun
return X
Kls2= create_class_with_static_function_name()
kls2= Kls2()
kls2.my_function_name()
In such case, the my_function_name shows correctly up, but it is not what I aimed for.
Would be glad to here any suggestions to accomplish dynamic creation of classes with dynamic method names, which are correctly handled in spyder's autocompletion within the editor window.
(Spyder dev here) Sorry, it seems the completion library we use (called rope) can't do this kind of completions on dynamic classes and attributes.
You're welcome to ask on its mailing list about it, and if there's something we can do in our side, we'll be happy to help.
Related
I have been developing a full-stack application that checks for files and uploads them to a cloud. However, I have come across an interesting problem that I was not able to solve.
I have a problem with instantiating a class, as you will see below:
class UploadFastq:
def __int__(self,
some_list, some_str, some_obj, **kwargs):
self.some_list = some_list
self.some_obj = some_obj
self.some_str = some_str
def process(self):
self.some_methods_calling_processes()
...
As you can imagine, I have trimmed the original code for privacy concerns (company dictates, sorry). This class is to handle some-backend related processes, and arguments only contain back related variables. Also, this class is on the different py script, which imports again back-related functions.
Now, the problem is, when I import to another script and try to call and instantiate the class, something funny happens...
from lib.some_back_related_script import UploadFastq
uploads = UploadFastq(some_list=the_list,some_str=the_str,some_obj=the_obj)
uploads.process
OUTPUT:
TypeError: UploadFastq() takes no arguments
I have looked if there are indentation problems, I could not find any. (I am using PyCharm as IDE, and reformatting the file also did not solve)
I have also tried this on an another script(the gui script) and could partially solve it as:
from lib.some_back_related_script import UploadFastq
uploader = UploadFastq()
uploader.__int__( ##TODO how is this possible???)
some_list=the_list,some_str=the_str,some_obj=the_obj
)
However, on the script the class suppose to be called, "__init__" method did not solve the case, and produced this error:
TypeError: UploadFastq.__init__() takes exactly one argument (the instance to initialize)
At this point I am clueless about what is going on and how to solve it. I have experiencing something like this for first time. I also could not find this kind of problem on the internet. soo, I would be much grateful if you could explain how to approach the problem.
P.S.: I work as a bioinformatician/python developer for a quite time and I found many many solutions on this platform. But, this is actually my first question on the stackoverflow!!!
Cheers!
You mispelled the constructor name __init__ as __int__ :
def __int__(self, some_list, some_str, some_obj, **kwargs):
Thus the default constructor (which takes as arguments only the "instance to initialize") was called, and the interpreter is complaining about the given arguments.
TypeError: UploadFastq.__init__() takes exactly one argument (the instance to initialize)
I'm trying to get in the habit of writing docstrings, and one way I think I could force myself to do that would be by automatically having Eclipse insert an empty docstring when I type a class or a def statement. It's only 8 key presses but it seems handy to me.
Would creating my own Eclipse plugin be the best method?
Just for reference, I'd like it to look something like this (yes I know the function is silly, it's just a demo):
def timeInit():
'''
'''
return ti.time()
PyDev doesn't do that automatically, but you can do Ctrl+1 in the def line and select the option for it to generate the docstring for you (it'll include all params in the docstring).
Another option is creating a template (in preferences > pydev > editor > templates) which automatically comes with the docstring and then use it to create the method (or you can edit the existing def template.
I was trying to find out the methods of the pywin32 object of a userform ComboBox in Excel, but I honestly has no idea what I'm doing and got nowhere.
VBA Code (Sending combobox object to python):
Private Sub ComboBox1_Change()
s = test(ComboBox1)
End Sub
Python Code :
#xw.func
def test(obj):
print(obj._dict__)
So, the print above returned this :
{'_oleobj_': <PyIDispatch at 0x03957A90 with obj at 0x01218C8C>, '_username_': 'IMdcCombo', '_olerepr_': <win32com.client.build.LazyDispatchItem object at 0x03FB0FD0>, '_mapCachedItems_': {}, '_builtMethods_': {}, '_enum_': None, '_unicode_to_string_': None, '_lazydata_': (<PyITypeInfo at 0x03957B50 with obj at 0x0121919C>, <PyITypeComp at 0x03957B68 with obj at 0x012196F4>)}
I guess I was expecting to see the same methods/properties found in VBA, but I have no idea what to take from this.
Anyone knows a way to manipulate userform/controls directly from python using xlwings?
Specifically I'm looking for dynamically adding new controls to the userform, reading/modifying controls attributes, and ideally modifying their events, all through python.
I guess I was expecting to see the same methods/properties found in VBA, but I have no idea what to take from this.
You can take anything from this, but this isn't a real Combobox nor something from COM environment - it's just a "wrapper" object over a COM object, implemented via IDispatch interface, and it's possibily thanks to the win32com dependency.
Because of that there's no an "intellisense"-like feature, but you're still able to use properties/methods:
#xw.func
def test(obj):
# accesing method
obj.AddItem('Hello world!')
# accesing property
obj.Enabled = False
also you can pass an UserForm as obj to add a new control to it:
#xw.func
def test(obj):
# add new label
control = obj.Add('Forms.Label.1')
# accesing property
control.Caption = 'Hello world!'
When looking under the documentation for xlWings under the Shapethere does seem to be access to all properties.
Under missing features, you can find a workaround using .api to access all vba methods. Through this you could create and modify controls, just like you would do in VBA.
Also what you could do is using the macro(name)-function you could create functions in VBA to modify, create comboboxes and pass values to the function, i.e to create a combobox at position x, y , width, height and pass these parameters trough python.
As it seems, you cannot access events trough xlWings. But i've found IronPython, it uses the .NET interop facilities to access the excel object and events. As you can see under the documentation, you can work with the excel object as you would do in C#, VB.NETetc..
So as a conclusion, i would suggest you looking up the documentations of both. As they both reveal the excel object to python you should be able to do what you want with one of them.
When it comes to constructors, and assignments, and method calls, the PyCharm IDE is pretty good at analyzing my source code and figuring out what type each variable should be. I like it when it's right, because it gives me good code-completion and parameter info, and it gives me warnings if I try to access an attribute that doesn't exist.
But when it comes to parameters, it knows nothing. The code-completion dropdowns can't show anything, because they don't know what type the parameter will be. The code analysis can't look for warnings.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
peasant = Person("Dennis", 37)
# PyCharm knows that the "peasant" variable is of type Person
peasant.dig_filth() # shows warning -- Person doesn't have a dig_filth method
class King:
def repress(self, peasant):
# PyCharm has no idea what type the "peasant" parameter should be
peasant.knock_over() # no warning even though knock_over doesn't exist
King().repress(peasant)
# Even if I call the method once with a Person instance, PyCharm doesn't
# consider that to mean that the "peasant" parameter should always be a Person
This makes a certain amount of sense. Other call sites could pass anything for that parameter. But if my method expects a parameter to be of type, say, pygame.Surface, I'd like to be able to indicate that to PyCharm somehow, so it can show me all of Surface's attributes in its code-completion dropdown, and highlight warnings if I call the wrong method, and so on.
Is there a way I can give PyCharm a hint, and say "psst, this parameter is supposed to be of type X"? (Or perhaps, in the spirit of dynamic languages, "this parameter is supposed to quack like an X"? I'd be fine with that.)
EDIT: CrazyCoder's answer, below, does the trick. For any newcomers like me who want the quick summary, here it is:
class King:
def repress(self, peasant):
"""
Exploit the workers by hanging on to outdated imperialist dogma which
perpetuates the economic and social differences in our society.
#type peasant: Person
#param peasant: Person to repress.
"""
peasant.knock_over() # Shows a warning. And there was much rejoicing.
The relevant part is the #type peasant: Person line of the docstring.
If you also go to File > Settings > Python Integrated Tools and set "Docstring format" to "Epytext", then PyCharm's View > Quick Documentation Lookup will pretty-print the parameter information instead of just printing all the #-lines as-is.
Yes, you can use special documentation format for methods and their parameters so that PyCharm can know the type. Recent PyCharm version supports most common doc formats.
For example, PyCharm extracts types from #param style comments.
See also reStructuredText and docstring conventions (PEP 257).
Another option is Python 3 annotations.
Please refer to the PyCharm documentation section for more details and samples.
If you are using Python 3.0 or later, you can also use annotations on functions and parameters. PyCharm will interpret these as the type the arguments or return values are expected to have:
class King:
def repress(self, peasant: Person) -> bool:
peasant.knock_over() # Shows a warning. And there was much rejoicing.
return peasant.badly_hurt() # Lets say, its not known from here that this method will always return a bool
Sometimes this is useful for non-public methods, that do not need a docstring. As an added benefit, those annotations can be accessed by code:
>>> King.repress.__annotations__
{'peasant': <class '__main__.Person'>, 'return': <class 'bool'>}
Update: As of PEP 484, which has been accepted for Python 3.5, it is also the official convention to specify argument and return types using annotations.
PyCharm extracts types from a #type pydoc string. See PyCharm docs here and here, and Epydoc docs. It's in the 'legacy' section of PyCharm, perhaps it lacks some functionality.
class King:
def repress(self, peasant):
"""
Exploit the workers by hanging on to outdated imperialist dogma which
perpetuates the economic and social differences in our society.
#type peasant: Person
#param peasant: Person to repress.
"""
peasant.knock_over() # Shows a warning. And there was much rejoicing.
The relevant part is the #type peasant: Person line of the docstring.
My intention is not to steal points from CrazyCoder or the original questioner, by all means give them their points. I just thought the simple answer should be in an 'answer' slot.
I'm using PyCharm Professional 2016.1 writing py2.6-2.7 code, and I found that using reStructuredText I can express types in a more succint way:
class Replicant(object):
pass
class Hunter(object):
def retire(self, replicant):
""" Retire the rogue or non-functional replicant.
:param Replicant replicant: the replicant to retire.
"""
replicant.knock_over() # Shows a warning.
See: https://www.jetbrains.com/help/pycharm/2016.1/type-hinting-in-pycharm.html#legacy
You can also assert for a type and Pycharm will infer it:
def my_function(an_int):
assert isinstance(an_int, int)
# Pycharm now knows that an_int is of type int
pass
In general I want to disable as little code as possible, and I want it to be explicit: I don't want the code being tested to decide whether it's a test or not, I want the test to tell that code "hey, BTW, I'm running a unit test, can you please not make your call to solr, instead can you please stick what you would send to solr in this spot so I can check it". I have my ideas but I don't like any of them, I am hoping that there's a good pythonic way to do this.
You can use Mock objects to intercept the method calls that you do not want to execute.
E.g. You have some class A, where you don't want method no() to be called during a test.
class A:
def do(self):
print('do')
def no(self):
print('no')
A mock object could inherit from A and override no() to do nothing.
class MockA(A):
def no(self):
pass
You would then create MockA objects instead of As in your test code. Another way to do mocking would be to have A and MockA implement a common interface say InterfaceA.
There are tons of mocking frameworks available. See StackOverflow: Python mocking frameworks.
In particular see: Google's Python mocking framework.
Use Michael Foord's Mock
in your unit test do this:
from mock import Mock
class Person(object):
def __init__(self, name):
super(Person, self).__init__()
self.name = name
def say(self, str):
print "%s says \"%s\"" % (self.name, str)
...
#In your unit test....
#create the class as normal
person = Person("Bob")
#now mock all of person's methods/attributes
person = Mock(spec=person)
#talkto is some function you are testing
talkTo(person)
#make sure the Person class's say method was called
self.assertTrue(person.say.called, "Person wasn't asked to talk")
#make sure the person said "Hello"
args = ("Hello")
keywargs = {}
self.assertEquals(person.say.call_args, (args, keywargs), "Person did not say hello")
The big problem that I was having was with the mechanics of the dependency injection. I have now figured that part out.
I need to import the module in the exact same way in both places to successfully inject the new code. For example, if I have the following code that I want to disable:
from foo_service.foo import solr
solr.add(spam)
I can't seem to do this in the in my test runner:
from foo import solr
solr = mock_object
The python interpreter must be treating the modules foo_service.foo and foo as different entries. I changed from foo import solr to the more explicit from foo_service.foo import solr and my mock object was successfully injected.
Typically when something like this arises you use Monkey Patching (also called Duck Punching) to achieve the desired results. Check out this link to learn more about Monkey Patching.
In this case, for example, you would overwrite solr to just print the output you are looking for.
You have two ways to do this is no ,or minimal in the case of DI, modifications to your source code
Dependency injection
Monkey patching
The cleanest way is using dependency injection, but I don't really like extensive monkeypatching, and there are some things that are non-possible/difficult to do that dependency injection makes easy.
I know it's the typical use case for mock objects, but that's also an old argument... are Mock objects necessary at all or are they evil ?
I'm on the side of those who believe mocks are evil and would try to avoid changing tested code at all. I even believe such need to modify tested code is a code smell...
If you wish to change or intercept an internal function call for testing purpose you could also make this function an explicit external dependency set at instanciation time that would be provided both by your production code and test code. If you do that the problem disappear and you end up with a cleaner interface.
Note that doing that there is not need to change the tested code at all neither internally nor by the test being performed.