omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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.


    Shortcut to run a script located in Working Copy's dir?

    Pythonista
    2
    12
    270
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • cvp
      cvp @bensaccount last edited by cvp

      @bensaccount said

      I'm guessing this only works if the script is located in Pythonista's directory.

      I think that's true. Perhaps find a way to start a Pythonista script which it-self starts the script of Working Copy.

      In Pythonista V3.3 we were able to start a script running in Python 2 which started a Python 3 interpreter like a wrench script does.

      #!python2
      # force this script to use Python 2 Interpreter so you can start
      # Python 3 Interpreter to run your iCloud script
      from objc_util import *	
      import sys
      arg = sys.argv
      # this script = arg[0]
      script = arg[1]
      path = '/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/' + script
      arg = arg[2:]	# other arguments
      I3=ObjCClass('PYK3Interpreter').sharedInterpreter()
      print(I3)
      # run a script like in wrench menu (path, args, reset env yes/no)
      #print(path,script)
      I3.runScriptAtPath_argv_resetEnvironment_(path, arg, True)
      
      1 Reply Last reply Reply Quote 0
      • cvp
        cvp @bensaccount last edited by cvp

        @bensaccount as we can't have two times the Pythonista Python 3 interpreter at the same time, I have tested with another thread. Here, an example with (I don't use Working Copy) starting via runScript another script in iCloud

        import sys
        import threading
        
        class my_thread_(threading.Thread):
        	def __init__(self,path,arg):
        		threading.Thread.__init__(self)
        		self.path = path
        		self.arg = arg
        
        	@on_main_thread	
        	def run(self):
        		from objc_util import ObjCClass
        		from time import sleep
        		sleep(1)
        		I3 = ObjCClass('PYK3Interpreter').sharedInterpreter()
        		# run a script like in wrench menu (path, args, reset env yes/no)
        		#print(path,script)
        		I3.runScriptAtPath_argv_resetEnvironment_(self.path, self.arg, True)
        
        arg = sys.argv
        # this script = arg[0]
        script = arg[1]
        path = '/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/' + script
        arg = arg[2:]	# other arguments
        my_thread = my_thread_(path,arg)
        my_thread.start()
        

        Execute this shortcut

        this shortcut

        B 1 Reply Last reply Reply Quote 0
        • B
          bensaccount @cvp last edited by bensaccount

          @cvp Thanks, having a launcher script in Pythonista's Documents dir fixes the issue! I think starting another interpreter may be unnecessary though, since I do want the script to run inside Pythonista, and using the same version of Python.

          Here's what I ended up using for my launcher script:

          dir = '/private/var/mobile/Containers/Shared/AppGroup/......'
          filename = 'app.py'
          
          import sys
          import os
          
          sys.path.append(dir)
          os.chdir(dir)
          
          with open(filename) as f:
              exec(f.read())
          

          This seems to work fine. And of course this could be altered to take arguments for directory and filename.

          I've run into a couple issues with Shortcuts now:

          1. If I use the Pythonista Run Script shortcut, I have to stop the shortcut manually afterwards, even if Pythonista is closed. Adding "Stop this shortcut" doesn't make a difference. It's not a huge deal, but it may be confusing for the client.
          2. Pythonista will happily run the script multiple times. Is there any way to tell Pythonista not to do this, or do I need to implement something manually, like a lock file? (Or is there a more reliable way to check if a script is running?)

          edit: Ah, I've found TPO's AppSingleLaunch util. Looks like it handles the issues with lock files sticking around when the app doesn't shut down properly, so I may try that.

          cvp 2 Replies Last reply Reply Quote 0
          • cvp
            cvp @bensaccount last edited by

            @bensaccount I didn't know this exec function.... Thanks for the info.

            1 Reply Last reply Reply Quote 0
            • cvp
              cvp @bensaccount last edited by

              @bensaccount I have tried successfully a shortcut with unique action

              alt text

              B 1 Reply Last reply Reply Quote 0
              • B
                bensaccount @cvp last edited by

                @cvp That's handy. So a separate launcher script file isn't needed.

                It can still launch multiple times though. I think I'll have to add TPO's util to my app to prevent that.

                B 1 Reply Last reply Reply Quote 0
                • B
                  bensaccount @bensaccount last edited by

                  I'm running into two problems with @TPO's AppSingleLaunch:

                  1. I'm using a NavigationView as my top-level view, which doesn't have a will_close function. It's immutable, so it won't let me monkey patch one in either. Is there another way to detect when the script is exiting?
                  2. I don't think the forced garbage collection is working. If I close the Python script and re-open it (which doesn't delete the lock file due to issue #1), the id it stores- the NavigationView's id- still exists. Even if I wait a while, gc.collect() won't collect it.
                  B 1 Reply Last reply Reply Quote 0
                  • B
                    bensaccount @bensaccount last edited by bensaccount

                    Hm, if I add a will_close method to my root View, it never gets called, I guess that's only called when you use .close().

                    The UIKit docs show a viewWillDisappear method for NavigationView, which does show up in __dir()__ for its objc object. Is there any way to set that via Python?

                    My temporary workaround is hide_close_button=True, so the app can only shutdown properly. But there's still the problem I mentioned earlier of AppSingleLaunch not working due to the NavigationView not getting cleaned up after closing. (edit: Though it's not a problem if the script always closes down properly)

                    cvp 1 Reply Last reply Reply Quote 0
                    • cvp
                      cvp @bensaccount last edited by

                      @bensaccount try to put a close button to top view of NavigationView

                      import ui
                      
                      view = ui.View()
                      navigationView = ui.NavigationView(view)
                      
                      # Add a close button
                      view.left_button_items = [ui.ButtonItem(title="Close", action=lambda x: navigationView.close())] 
                      
                      # Won't show the x-button
                      navigationView.present("sheet", hide_title_bar=True)
                      
                      B 1 Reply Last reply Reply Quote 0
                      • B
                        bensaccount @cvp last edited by

                        @cvp Thanks, looks like we had the same idea. I had just removed the close button, but I have to admit that hiding the title bar is tempting to reclaim some vertical space.

                        cvp 1 Reply Last reply Reply Quote 0
                        • cvp
                          cvp @bensaccount last edited by cvp

                          @bensaccount so you can intercept the root view closing, like a will_close

                          If it is not sufficient, I think that, in Objective C, we could intercept the delegate should_pop of the UINavigationBar, but more complex of course

                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post
                          Powered by NodeBB Forums | Contributors