omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular
    1. Home
    2. iAmMortos

    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.


    • Profile
    • Following 0
    • Followers 0
    • Topics 4
    • Posts 15
    • Best 5
    • Controversial 0
    • Groups 0

    iAmMortos

    @iAmMortos

    5
    Reputation
    1016
    Profile views
    15
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    iAmMortos Unfollow Follow

    Best posts made by iAmMortos

    • RE: Easy, reusable code with this helper module

      I suppose it'd be a nice addition to have some kind of add_path_and_import option as well. I've actually not done programmatic importing before.

      posted in Pythonista
      iAmMortos
      iAmMortos
    • RE: Easy, reusable code with this helper module

      Yeesh, I need to keep a better eye out for emails from this site.

      Once you do the add_path_for, are you performing the actual import for my_cmd?

      import sharedlibs
      sharedlibs.add_path_for('my_cmd')
      import my_cmd
      

      As it works presently, my module doesn't do any importing, it just adds the predefined path in shared_libs.txt

      posted in Pythonista
      iAmMortos
      iAmMortos
    • RE: Easy, reusable code with this helper module

      It’s the same as adding a directory to your search path. So nothing is cached or saved or in need of reloading. The only thing that changes is when you add entries to the sharedlibs_list.txt file (which is on my favorites list for easy editing), which doesn’t require anything to be reloaded either since it’s not read until one of the functions in the sharedlibs module is actually invoked. No clutter in the site-packages :)

      posted in Pythonista
      iAmMortos
      iAmMortos
    • RE: Easy, reusable code with this helper module

      Good call. That’s a good fix.

      posted in Pythonista
      iAmMortos
      iAmMortos
    • Easy, reusable code with this helper module

      I found myself regularly wanting to copy modules I had already written into new projects. Things like Dice classes, confirmation views, or even a reusable color picker view. I wasn't about to put everything I thought was useful or reusable in the site-packages. I was aware, however, of the ability to add a directory to the sys.path so I could reference and import it, but in an app on iOS, this full path is very long and gross, and trying to use relative paths instead was almost equally undesirable. And what if the module I made gets renamed or moved? Now all those hard-coded references to its path in other modules need to be found and updated.

      I wrote this little helper module sharedlibs.py to simplify the process and dropped it in the site-packages folder.

      '''
      example use of this module:
      
      import sharedlibs
      sharedlibs.add_path_for('animated_image_view')
      from animated_image_view import AnimatedImageView
      '''
      
      import os
      import sys
      
      
      def get_app_root():
          # Returns the fully-qualified "root" directory of the Pythonista 3 app
      	end = 'Pythonista3/Documents'
      	cwd = os.getcwd()
      	return cwd.split(end)[0] + end
      	
      def add_path_for(*modules):
          # Adds the directory for the given library name to the search path so its contents can be imported.
      	_libs = _load_libs_dict()
      	for module in modules:
      		if module in _libs:
      			sys.path.append(get_app_root() + _libs[module])
      		else:
      			raise Exception('No such shared module: .%s' % module)		
      		
      # Prints a list of accessible libraries
      def list():
      	_libs = _load_libs_dict()
      	print('Available Shared Libraries:')
      	for key in _libs:
      		print('  %s: %s' % (key, _libs[key]))
      		
      def _load_libs_dict():
      	d = {}
      	print(__file__)
      	libs_path = '%s/sharedlibs_list.txt' % '/'.join(__file__.split('/')[:-1])
      	
      	with open(libs_path) as f:
      		lines = [l.strip() for l in f.readlines()]
      		for line in lines:
      			if line != '' and not line.startswith('#'):
      				k,v = line.split('=')
      				d[k] = v
      	return d
      
      				
      if __name__ == '__main__':
          # just print the available libraries
      	list()
      

      This module and a sharedlibs_list.txt file were both added to the site-packages and nothing else ever again.
      The sharedlibs_list.txt is simply a key-value pair file containing the short names of the libraries mapped to their paths relative to the Pythonista's app root. Something like this:

      animated_image_view=/UI/Views/AnimatedImageView
      brightness=/Utils/ColorBrightness
      config_file=/Utils/ConfigFile
      img_utils=/Utils/ImageUtils
      perm_utils=/Utils/PermutationUtils
      ui_drag=/UI/Draggable
      view_swap=/UI/ViewSwap
      word_utils=/Utils/WordUtils
      

      You'll notice you don't need the full path from your iOS device's actual root; the sharedlibs module treats the Pythonista3/Documents directory as your root since you can't really access much outside there anyway.
      Once Pythonista is restarted, the listed libraries will be accessible via the sharedlibs.add_path_for() function, which will add that library's directory to the search path.

      One single, clean place to define the locations of your reusable libraries for easy import anywhere.

      posted in Pythonista
      iAmMortos
      iAmMortos

    Latest posts made by iAmMortos

    • RE: Easy, reusable code with this helper module

      I suppose it'd be a nice addition to have some kind of add_path_and_import option as well. I've actually not done programmatic importing before.

      posted in Pythonista
      iAmMortos
      iAmMortos
    • RE: Easy, reusable code with this helper module

      Yeesh, I need to keep a better eye out for emails from this site.

      Once you do the add_path_for, are you performing the actual import for my_cmd?

      import sharedlibs
      sharedlibs.add_path_for('my_cmd')
      import my_cmd
      

      As it works presently, my module doesn't do any importing, it just adds the predefined path in shared_libs.txt

      posted in Pythonista
      iAmMortos
      iAmMortos
    • RE: Custom ui.View Instantiation Pattern

      Oooooh, maaaagic.
      Thank you! This is exactly the kind of improvement I've been looking for!

      posted in Pythonista
      iAmMortos
      iAmMortos
    • RE: "Run Pythonista Script" Widget: How to write script that can email selected photos from my phone's camera roll?

      Side note, Pythonista has some hooks in Shortcuts as well for kicking off scripts. So even if that's not the best route for this particular project, it's a REALLY powerful tool to keep in your back pocket.
      I have a shortcut called "Burn" that starts a Pythonista script that shows a fire gif and plays a rap air horn... so... lol

      posted in Pythonista
      iAmMortos
      iAmMortos
    • RE: Easy, reusable code with this helper module

      It’s the same as adding a directory to your search path. So nothing is cached or saved or in need of reloading. The only thing that changes is when you add entries to the sharedlibs_list.txt file (which is on my favorites list for easy editing), which doesn’t require anything to be reloaded either since it’s not read until one of the functions in the sharedlibs module is actually invoked. No clutter in the site-packages :)

      posted in Pythonista
      iAmMortos
      iAmMortos
    • RE: Easy, reusable code with this helper module

      Good call. That’s a good fix.

      posted in Pythonista
      iAmMortos
      iAmMortos
    • Easy, reusable code with this helper module

      I found myself regularly wanting to copy modules I had already written into new projects. Things like Dice classes, confirmation views, or even a reusable color picker view. I wasn't about to put everything I thought was useful or reusable in the site-packages. I was aware, however, of the ability to add a directory to the sys.path so I could reference and import it, but in an app on iOS, this full path is very long and gross, and trying to use relative paths instead was almost equally undesirable. And what if the module I made gets renamed or moved? Now all those hard-coded references to its path in other modules need to be found and updated.

      I wrote this little helper module sharedlibs.py to simplify the process and dropped it in the site-packages folder.

      '''
      example use of this module:
      
      import sharedlibs
      sharedlibs.add_path_for('animated_image_view')
      from animated_image_view import AnimatedImageView
      '''
      
      import os
      import sys
      
      
      def get_app_root():
          # Returns the fully-qualified "root" directory of the Pythonista 3 app
      	end = 'Pythonista3/Documents'
      	cwd = os.getcwd()
      	return cwd.split(end)[0] + end
      	
      def add_path_for(*modules):
          # Adds the directory for the given library name to the search path so its contents can be imported.
      	_libs = _load_libs_dict()
      	for module in modules:
      		if module in _libs:
      			sys.path.append(get_app_root() + _libs[module])
      		else:
      			raise Exception('No such shared module: .%s' % module)		
      		
      # Prints a list of accessible libraries
      def list():
      	_libs = _load_libs_dict()
      	print('Available Shared Libraries:')
      	for key in _libs:
      		print('  %s: %s' % (key, _libs[key]))
      		
      def _load_libs_dict():
      	d = {}
      	print(__file__)
      	libs_path = '%s/sharedlibs_list.txt' % '/'.join(__file__.split('/')[:-1])
      	
      	with open(libs_path) as f:
      		lines = [l.strip() for l in f.readlines()]
      		for line in lines:
      			if line != '' and not line.startswith('#'):
      				k,v = line.split('=')
      				d[k] = v
      	return d
      
      				
      if __name__ == '__main__':
          # just print the available libraries
      	list()
      

      This module and a sharedlibs_list.txt file were both added to the site-packages and nothing else ever again.
      The sharedlibs_list.txt is simply a key-value pair file containing the short names of the libraries mapped to their paths relative to the Pythonista's app root. Something like this:

      animated_image_view=/UI/Views/AnimatedImageView
      brightness=/Utils/ColorBrightness
      config_file=/Utils/ConfigFile
      img_utils=/Utils/ImageUtils
      perm_utils=/Utils/PermutationUtils
      ui_drag=/UI/Draggable
      view_swap=/UI/ViewSwap
      word_utils=/Utils/WordUtils
      

      You'll notice you don't need the full path from your iOS device's actual root; the sharedlibs module treats the Pythonista3/Documents directory as your root since you can't really access much outside there anyway.
      Once Pythonista is restarted, the listed libraries will be accessible via the sharedlibs.add_path_for() function, which will add that library's directory to the search path.

      One single, clean place to define the locations of your reusable libraries for easy import anywhere.

      posted in Pythonista
      iAmMortos
      iAmMortos
    • Custom ui.View Instantiation Pattern

      This is a pattern I've been using to instantiate custom Views that have accompanying pyui files with dynamic data. Just looking for some feedback or any constructive criticism to improve it or maybe just share the pattern if it can help someone else.

      Let's say I have a custom ui.View class called MyView. The pyui file that represents this View would be called my_view.pyui, and would set Custom Class to MyView in the main view properties. This view would contain a single Label component named lbl. I want to be able to instantiate this view with a constructor-like method that affects the contents of the View when it gets shown.

      The following pattern has made this possible in my_view.py:

      # my_view.py
      import ui
      
      class MyView(ui.View):
        def did_load(self):
          self.my_lbl = self['lbl']
      
        def init(self, text):
          '''
          since the ui.load_view() handles instantiating the actual View object, we can't access the true __init__
          method. So we'll call this one as part of our custom static load_view method.'''
          self.my_lbl.text = text
      
        @staticmethod
        def load_view(text):
          '''
          I particularly like this simple shortcut as it allows me to create instances of a custom class somewhere
          else without having to remember the name of its file. Much cleaner.
          This becomes our makeshift "constructor."'''
          v = ui.load_view()
          v.init(text)
          return v
      
      
      if __name__ == '__main__':
        # load MyView and initialize the view's label with text "Hello World!", then show the view.
        v = MyView.load_view("Hello World!")
        v.present()
      

      That wysiwyg UI editor in Pythonista is so stinkin' handy, and this pattern seems like a nice compromise between using the UI editor, and being able to create dynamic, flexible, and reusable views in a pythonic way.

      posted in Pythonista
      iAmMortos
      iAmMortos
    • RE: ui.ImageView contents not cropping to View bounds

      This I can do! Thanks for the tip!

      posted in Pythonista
      iAmMortos
      iAmMortos
    • RE: ui.ImageView contents not cropping to View bounds

      Oops. I goofed writing the post. But in my code, I am indeed using ui.CONTENT_SCALE_ASPECT_FILL. I've updated my original post.

      posted in Pythonista
      iAmMortos
      iAmMortos