Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Getting the parent of a dynamically method as a function
-
Sorry guys, appears I was not clear. But the code I posted works. But in the test_func, I want to be able to access the object that called the function.
I can pass a direct reference as below... But this is not good..import ui def test_func(obj, msg): ''' i would like to get a reference to the caller here being the btn. i am pretty sure the answer lies with the inspect module, but i cant figure it out. MAYBE, its even easier than that... well that would be great ''' print msg print obj.title btn = ui.Button(title = 'help') btn.msg = test_func btn.msg(btn, 'I am on to something...')
So in test_func, I would like to get access to ui object that called it.
-
@Olaf , not about actions. With this mechanism can extend ui elements eg ui.button , ui.TextField etc with your own methods/function dynamically. It can still be done, but if you need to access the object your are called from you are up the creek unless you explicitly pass the obj each time.
-
@Olaf , are you on 1.6 or 1.5? Both code samples I posted in this thread work.
-
@Phuket2 Did you see my reply above? Isn't that exactly what you are asking for? Why not? You have the reference to the button in the method without giving it as an argument every time you call it.
-
@Oscar , YES.....Exactly what I wanted. Sorry the syntax is not very clear to me. lambda etc... it Threw me off. But I did a few tests with your solution and worked perfectly. Late here now. But I will implement tomorrow. I am adding these funcs at runtime based on dicts. Not that difficult, I just want to get my head around your code. Easy for you, not for me 😱😬
But that little bit of code is powerful and opens up a lot in my mind.
One question, as stupid as it maybe, is it possible to express the same without the use of the Lambda? -
Other ways to bind a new method to an object instance (class not affected):
- Using types, really binding:
import types btn.msg = types.MethodType(test_func, btn)
- Using functools, just add the object to be always included as the first argument (like the lambda):
from functools import partial btn.msg = partial(test_func, btn)
-
@mikael beat me to it.. I was going to suggest partial if you prefer to not use lambda: https://docs.python.org/2/library/functools.html#functools.partial
-
Thanks everyone here for all the excellent feedback and help. Will have a go with types now. Looks straight fwd enough
-
@mikael , I was stumped there for a few mins because I am adding the extra functions from a dict. Where the k is method name and v is function/method (address).
But I did the below. It works. But not really understanding this well enough, just wanted to ask as you guys if this is seen as an acceptable way call it. As I say, it works great. Just want to be sure I haven't overlooked something
Thanks
for k,v in _extended_methods.iteritems(): setattr(ctl, k, types.MethodType(v, ctl)) #ctl. = types.MethodType(v, ctl)
-
Coming back to this...
Here is how I add functionality to built-in ui classes these days, using ProxyTypes.
import ui from proxy import ObjectWrapper class ButtonWrapper(ObjectWrapper): def __init__(self, obj): ObjectWrapper.__init__(self, obj) def msg(self, leader): print leader + ': ' + self.name button = ButtonWrapper(ui.Button(name = 'Wrapped ui.Button')) button.msg('Calling extra method')
-
@mikael said:
Coming back to this...
Here is how I add functionality to built-in ui classes these days, using ProxyTypes.
import ui
from proxy import ObjectWrapperclass ButtonWrapper(ObjectWrapper):
def init(self, obj):
ObjectWrapper.init(self, obj)
def msg(self, leader):
print leader + ': ' + self.namebutton = ButtonWrapper(ui.Button(name = 'Wrapped ui.Button'))
button.msg('Calling extra method')
@mikael, sorry just revisiting this. But is above complete? I just mean button is no longer considered a ui.View.
Sorry, I have a idea, I am just totally missing the point here -
I am heavily utilizing this in my current project, so I can confirm that it works. The only gotcha I have found is that you have to give
proxy_view.__subject__
instead of just the proxy_view to add_subview since, as you say, proxy_view is not descended from View. And likewise for ObjCInstance, if you are using objc_util. -
@Phuket2, that said, I think I understand what you are aiming for in your recent discussions, and agree that we are not there yet. Let me get back to this.
-
@mikael , ok. Sorry been a while since I looked at this. I just thought there was some magic happening that I was not getting
-
So, I think that one of the things we want is the ability to style UI components with inheritance. This is relatively straightforward and clean with the proxy approach:
# coding: utf-8 import ui from proxy import ObjectWrapper class DefaultStyle(ObjectWrapper): def __init__(self, obj): ObjectWrapper.__init__(self, obj) self.background_color = '#fff7ee' self.tint_color = 'black' class HighlightStyle(DefaultStyle): def __init__(self, obj): DefaultStyle.__init__(self, obj) self.tint_color = 'red' button = HighlightStyle(ui.Button()) button.title = 'Styled button' button.present()
-
@mikael , hmmm. I am having a bad day today. Nothing is working 😱
You can see below I have to
from peak.util.proxies import ObjectWrapper
I can't
from proxy import ObjectWrapperBut I am getting a no module named 'pkg_resources' error. Are you on v2 beta?
Could be something with the beta# coding: utf-8 import ui #from proxy import ObjectWrapper from peak.util.proxies import ObjectWrapper class DefaultStyle(ObjectWrapper): def __init__(self, obj): ObjectWrapper.__init__(self, obj) self.background_color = '#fff7ee' self.tint_color = 'black' class HighlightStyle(DefaultStyle): def __init__(self, obj): DefaultStyle.__init__(self, obj) self.tint_color = 'red' button = HighlightStyle(ui.Button()) button.title = 'Styled button' button.present()
-
Sorry, I have the proxies code in a different place, but it is the same code. And yes, I am on v2 beta.
-
@mikael said:
Sorry, I have the proxies code in a different place, but it is the same code. And yes, I am on v2 beta.
If you get time could you please show me the dir structure you have, I have tried modifying it, I just get the same error. I just tried moving the proxies.py up one level. As the init files in both dirs contain the same statement
import('pkg_resources').declare_namespace(name)
But still same error. -
I have proxies.py in the same directory, it does not need anything else. Could of course also be in site packages.
I guess this is partly why it would be so nice to have it "built in".
-
@mikael , mine is in site-packages. I installed it with stash. It's ok, I don't know what's going on. I will look into it. As I say, nothing is going smoothly today 😜
Have completely shut down my ipad. Didn't help