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.
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.
Posts made by iAmMortos
-
RE: Easy, reusable code with this helper module
-
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 formy_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
-
RE: Custom ui.View Instantiation Pattern
Oooooh, maaaagic.
Thank you! This is exactly the kind of improvement I've been looking for!
-
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 -
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 thesharedlibs
module is actually invoked. No clutter in the site-packages :) -
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.
Thesharedlibs_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 thesharedlibs.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.
-
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 calledMyView
. Thepyui
file that represents thisView
would be calledmy_view.pyui
, and would set Custom Class toMyView
in the main view properties. This view would contain a singleLabel
component namedlbl
. I want to be able to instantiate this view with a constructor-like method that affects the contents of theView
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.
-
RE: ui.ImageView contents not cropping to View bounds
This I can do! Thanks for the tip!
-
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. -
ui.ImageView contents not cropping to View bounds
I have a
ui.ImageView
withcontent_mode = ui.CONTENT_SCALE_ASPECT_FILL
. The documentation implies that using this content mode will crop the parts of the image that fall outside the bounds of theImageView
.ui.CONTENT_SCALE_ASPECT_FILL
Scale the content to fill the size of the view. Some portion of the content may be clipped to fill the view’s bounds.However, the excess image simply overflows outside the bounds of the
View
, spilling over other elements, making me sad.Two questions:
- Is this a bug? Or is this the expected functionality of
ui.CONTENT_SCALE_ASPECT_FILL
? - If this is indeed the intended behavior, how do you crop a
ui.Image
simply?
Regarding question 2, I've gotten cropping to work using the
PIL.Image.crop()
, and converting that croppedPIL.Image
into aui.Image
, but this is expensive, and I need these images to be loaded quickly in real-time. - Is this a bug? Or is this the expected functionality of
-
RE: Overriding tint_color on an inherited ui.View?
Marvelous suggestions. Thank you!
I would love to know how they do this black magic
tint_color
buffoonery underneath. I'm always more and more impressed with what is possible within the bounds of this app. It's incredible.Thanks again.
-
Overriding tint_color on an inherited ui.View?
I was in the process of making a custom button
ui.View
with event hooks for button press as well as button release. I wanted to make a button that would trigger repeated actions when held down. That's all well and good and the eventing works fine, but I also tried to emulate, to the best of my ability, all the features thatui.Button
has, like allowing text and or an icon that makes use oftint_color
etc. This required overriding thedraw
method and inserting theset_needs_display()
calls in the appropriate places.Apparently, however, setting
tint_color
on aui.View
does not trigger theset_needs_display()
to redraw the view. I assumed thattint_color
was just a property onui.View
that, under the covers, did all the fancy things to make the view update itself by default, and that I would be able to override it in a reasonable manner to callsuper().tint_color.fset()
or something like that followed by aset_needs_display()
to redraw my view. After looking into it a little further,ui.View.tint_color
is just a plain old attribute. So in order for me to properly handle the redrawing of theView
I had to make new property getters and setters namedtint
that setstint_color
and callsset_needs_display()
.I really dislike this solution because now the API for my custom button is nonstandard and it makes me feel... dirty... lol
Am I misunderstanding how tint_color works/should work?
-
RE: MySQL Client
Using tommasoturchi's mysqldb connector, I'm doing this:
import mysqldb db = mysqldb.connect(host="my.host.com", user="user", passwd="pass", db="MyDBName", port=3306) cursor = db.cursor()
and I'm getting an error:
ord() expected string of length 1, but int found
all the way down in thenetwork.py
file atself._packet_number = ord(packet[3])
wassup with that?!
Thanks
-
RE: Creating Home Screen Icons
My scripts are organized into folders. The shortcut making page just asks for the script name, which I supplied, but it says it couldn't find that script. I tried the path from
The root directory (like "Utils/myscript") but it said, "can't find script "Utils.py".
How do you create an icon for scripts organized in folders?If I just type it into the web browser I can get it to work, though.