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.
[Share Code] Implemented x-callback-url
-
was wanting to let you know that x_callback_url is no longer working with the most recent pythonista release woth python 3.6
-
In what way? Are you getting exceptions?
-
the callout works, the callback comes back to pythonista
however the swizzled handler doesnt fire -
no exceptions are showing, and the print statements ive put into the callback dont get called indicating that the swizzel method is not getting called or has changed
-
When it comes back, is the app still running? I.e anything you had printed to the console is still there?
-
I see that API is depreciated, so likely needs to be updated to use application:openURL:options: instead.
-
ended up using
openPythonistaURL:
instead of
application:openURL:sourceApplication:annotation:cheers D
-
@eddo888 what do you mean?
did you swizzleopenPythonistaURL:
instead of swizzling -[UIApplicationDelegate application:openURL:options:]
? -
here is my uodated and sligjtly modified x_callback_url.py
# coding: utf-8 import swizzle from objc_util import * import sys, re, os, argparse import ctypes, json, urllib, uuid, urllib import webbrowser def argue(): parser = argparse.ArgumentParser() parser.add_argument('-v', '--verbose', action='store_true', help='verbose mode') parser.add_argument('-t', '--test', action='store_true', help='run test') return parser.parse_args() def params(data): if len(data) == 0: return '' p = '&'.join( map( lambda x: '%s=%s'%(x,urllib.quote(data[x])), data.keys() ) ) return '?%s'%p def reverse(url): query = NSURLComponents.componentsWithURL_resolvingAgainstBaseURL_(nsurl(url), False) parameters = dict() if query.queryItems() is not None: for queryItem in query.queryItems(): parameters[str(queryItem.name())] = str(queryItem.value()) return parameters def open_url(url, handler): global _handler global _requestID _requestID = uuid.uuid1() _handler = handler x_success = urllib.quote('pythonista://?request=%s'%_requestID) url_with_uuid = url.replace('?','?x-success=%s&'%x_success) #sys.stderr.write('> %s\n'% url_with_uuid) webbrowser.open(url_with_uuid) def openPythonistaURL_(_self, _sel, url): url_str = str(ObjCInstance(url)) #sys.stderr.write('< %s\n'%url_str) global _call_me, _handler, _requestID if '?request=%s'%_requestID in url_str: url_str = url_str.replace('?request=%s&'%_requestID, '?') parameters = reverse(url_str) if _handler: _handler(parameters) return True elif _call_me in url_str: #print url_str parameters = reverse(url_str) x_parameters = dict() for x in [ 'x-source', 'x-success', 'x-error', 'x-cancel', 'x-script', ]: if x in parameters.keys(): x_parameters[x] = parameters[x] del parameters[x] #print '%s\n%s'%( # json.dumps(x_parameters), # json.dumps(parameters) #) if 'x-script' not in x_parameters.keys(): return try: import importlib mod = importlib.import_module( x_parameters['x-script'] ) res = str(mod.main(parameters)) url=x_parameters['x-success']+'?args=%s'%urllib.quote(res) except: error=str(sys.exc_info()[0]) url=x_parameters['x-error']+'?args=%s'%urllib.quote(error) #print url webbrowser.open(url) return True else: #print('original url=%s'%url_str) obj = ObjCInstance(_self) original_method = getattr(obj, 'original'+c.sel_getName(_sel), None) if original_method: _annotation = ObjCInstance(annotation) if annotation else None return original_method( ObjCInstance(app), ObjCInstance(url), ObjCInstance(source_app), _annotation ) return def test(): data={ 'statement' : 'select * from MyTable' } url='generaldb://x-callback-url/execute-select-statement' + params(data) print url def myhandler(parameters): print parameters for row in parameters['rows'].split('\n'): print row return open_url(url,myhandler) def setup(): global NSURLComponents, _call_me, _handler, _requestID _call_me = 'pythonista://x-callback-url' _handler = None _requestID = None NSURLComponents = ObjCClass('NSURLComponents') appDelegate = UIApplication.sharedApplication().delegate() # Do the swizzling cls = ObjCInstance(c.object_getClass(appDelegate.ptr)) swizzle.swizzle( cls, 'openPythonistaURL:', openPythonistaURL_ ) #print 'swizzled' return def main(): setup() args = argue() if args.test : test(); return print 'setup complete:'#, sys.argv #webbrowser.open('workflow://') return if __name__ == '__main__': main()
-
(fyi, you should wrap the code block with ```, to get proper syntax highlighting. reading the code w/out that is really difficult)
-
cheers thought i was in confluence not markdown :-)
-
def params(data): '?' + urllib.urlencode(data)
https://docs.python.org/2/library/urllib.html#urllib.urlencode
-
def params(data): if len(data) == 0: return '' p = '&'.join( map( lambda x: '%s=%s'%(x,urllib.quote(data[x])), data.keys() ) ) print data print urllib.urlencode(data) print p return '?%s'%p
yields
{'statement': 'select * from MyTable'} statement=select+%2A+from+MyTable statement=select%20%2A%20from%20MyTable
the client receiving the params preferrs %20 to +
-
@eddo888 In Python 3 you can do that using the
quote_via
parameter, likeurllib.parse.urlencode({...}, quote_via=urllib.parse.quote)
. However in Python 2 thequote_via
parameter doesn't exist yet. You can manually replace every+
with%20
, likeurllib.parse.urlencode({...}).replace("+", "%20")
. This should produce the same result and is much shorter than building the whole parameter string by hand. -
Thanks for taking the time to respond and guide, I hope you have a fun weekend. Cheers Dave
-
How do I use this and get arguments from workflow?
-
This awesome piece of code leads to the famous 404...
https://github.com/lukaskollmer/pythonista-scripts/blob/master/x-callback-url/x_callback_url.py
Someone stil has it available?
I'm trying to load a file from IAwriter to process it in phytonista...
-
-
@dc2 said:
I'm trying to load a file from IAwriter to process it in phytonista...
x-callback-url will not help you for that.
If you want to load a file into Pythonista, you have to share it to Pythonista script or to import it into Pythonista via "open external folder", if the app allows it.
-
@cvp Thanks, i think that sharing it as input in a script may be the way to go!
After trying to share the file to "Preview Markdown.py", I found that instead of the text, the path of the file is returned by appex.get_text()....
Somewhere the contents gets mixed up, probably in IAwriter...