• johnridesabike

    It seems to work as expected for me too. Here’s the output:

    Python: Noun
    is: Verb
    pretty: Adverb
    awesome: Adjective
    .: SentenceTerminator

    Pythonista 3.2, Default interpreter 3.6.1, iOS 11.4, iPad

    posted in Pythonista read more
  • johnridesabike

    @ihf It uses WordNik to download word definitions. However, it also includes a basic offline dictionary that it can fall back on if there's no API key or no internet connection. So depending on what you look up, you may not notice a difference. The offline dictionary is much more limited than WordNik though. If you look at a word definition and it says it came from American Heritage Dictionary or Wikitionary, then that means it downloaded that definition from WordNik.

    **Edit: **

    Just to clarify, here’s an example of a word that requires WordNik to view the definition: https://imgur.com/TGpHJtx

    Here’s what it looks like once you add an API key: https://imgur.com/4vSMCCl

    And also, I updated the GitHub releases with the latest version. It should have a better UI and some bugfixes.

    posted in Pythonista read more
  • johnridesabike

    I told myself I’d take a break for a bit, but I’ve been having too much fun putting together the iPad UI. I just updated my dev branch with a bunch of changes: https://github.com/johnridesabike/WordRoom/tree/working-copy

    I’m posting it now because I want to share my AdaptiveView class I came up with. I really wanted a UI that could dynamically change between compact mode for iPhones and iPad split-view, and regular mode for iPad full-screen. Here’s what it looks like:

    class AdaptiveView(ui.View):
        def __init__(self, nav_column, content_column):
            # Putting content_column inside a NavigationView is a hack to make its
            # title bar visible. We never invoke the NavigationView methods.
            self.content_column = content_column
            self.nav_column = nav_column
            # open_words will probably always just have one item, but it's
            # technically possible to have more than one open.
            self.open_words = []
            self.current_layout = None
            # background color is used as a border between the columns.
            self.background_color = 'lightgrey'
        def layout(self):
            # 678 is the width of an iPad pro app in 1/2 split mode.
            if self.width >= 678 and self.current_layout != 'regular':
            elif self.width < 678 and self.current_layout != 'compact':
        def compact(self):
            nav, content = self.subviews
            nav.x = self.x
            nav.width = self.width
            nav.height = self.height
            nav.flex = 'WH'
            content.hidden = True
            for word in self.open_words:
                nav.push_view(compact_word_view, False)
            self.current_layout = 'compact'
        def regular(self):
            nav, content = self.subviews
            nav.width = 320
            nav.height = self.height
            nav.flex = 'H'
            nav.x = self.x
            content.hidden = False
            content.flex = 'WHR'
            content.x = nav.width + 1
            content.width = self.width - nav.width - 1
            content.height = self.height
            if self.current_layout == 'compact':
                for word in self.open_words:
            self.current_layout = 'regular'
    if __name__ == '__main__':
        lookup_view = ui.load_view('lookup')
        nav_view = ui.NavigationView(lookup_view, flex='WH')
        word_view = ui.load_view('word')
        compact_word_view = ui.load_view('word')
        container = AdaptiveView(nav_view, word_view)

    Basically, if you already have two views for navigation and content, you can just load them into an AdaptiveView instance and it will display them according to the window width. You’ll need two instances of the content view (the “word_view” in my code), one to display in the right column and one to push in compact mode. If you open some content and then resize the window, this view will “smartly” move the content from one column to the other.

    I also tried making a “regular_narrow” layout for iPads in portrait mode, where just the content is displayed and the menu can slide out with a button. I wasn’t really happy with the way it looked though, and I didn’t take the time to implement features like gestures, so I didn’t include it.

    Edit: I’ve since discovered way of checking for the layout class that’s much better than comparing the width. You can use self.objc_instance.traitCollection().horizontalSizeClass() which returns 1 for compact and 2 for regular.

    posted in Pythonista read more
  • johnridesabike

    Based on ccc’s observation, it looks like your Jinja2 is only Python 2 compatible, but my code is all Python 3. Maybe try moving it to site-packages-2 instead of site-packages? Then it should only load when Python 2 code runs.

    Pythonista should have a built-in Jina2 module (at least it does for me). It’s located under Standard Library (3.6)/site-packages/jinja2/. If you don’t have that, then I’m not sure. The most up-to-date Jinja2 is supposedly compatible with 2 and 3. You can check your Jinja2 version by typing this in the console:

    import jinja2

    Other than that, I’m not sure. If it continues to be a problem, I might look into workarounds that don’t depend on using Jinja2.

    posted in Pythonista read more
  • johnridesabike

    @jsamlarose47 It looks like that error is coming from one of jinja2’s files. WordRoom uses Pythonista’s built-in jinja2 module to format the definition pages.

    I don’t know why jinja2 would throw a syntax error, but I did notice something in your error log. Your jinja2 is being loaded from your custom site-packages directory. When I import it on mine, it loads from the built-in Pythonista library.

    If you have a copy of jinja2 in your site-packages, you could try deleting or updating it and running WordRoom again.

    posted in Pythonista read more
  • johnridesabike

    Depending on what you're trying to do, a function like this might be what you need. For this code to work, you would have a button's action set to button_open_view, and new_view has a text field that you want to be set to the button's title. You can modify the details to fit your specific UI.

    def button_open_view(sender):
        # gets called when user selects an option from the first view
        new_view = ui.load_view('new_view')
        new_view['textfield'].text = sender.title

    posted in Pythonista read more
  • johnridesabike

    @TutorialDoctor I actually used your Pythonista Projects repo to learn a lot when I was just getting started, and I remember looking through the Bible app that was included in it. I hadn’t seen that redesigned version until now though. It looks pretty nice!

    posted in Pythonista read more
  • johnridesabike

    I figured some of ya’ll might be interested in this. For the last couple of weeks, I’ve been developing a dictionary app in Pythonista. Here’s the GitHub repo: https://github.com/johnridesabike/WordRoom

    Its main difference compared to other dictionary apps is that this is designed for you to write your own notes for the words you look up. It saves your notes and your look-up history. I’ve wanted an app like this for a long time, but I never found one that I liked. I finally decided to dive into Pythonista and make it for myself.

    Although I mainly designed the app for my own personal use, I tried to make it user-friendly for anyone else. Also, I did my best to document all of the code so other Pythonista users can take advantage of it. I hope people can find it useful!

    posted in Pythonista read more
  • johnridesabike

    Thanks, that makes sense. I might just try making my own datasource then.

    I was confused because in the documentation on ListDataSource.items, the link to the Image object goes to the PIL.Image module, not ui.Image. That’s what prompted me to try a PIL image in the first place. http://omz-software.com/pythonista/docs/ios/ui.html#ui.ListDataSource.items

    posted in Pythonista read more
  • johnridesabike

    I’m making a TableView with ListDataSource. Some of the items will have a named image, and some will not. In order to keep the item titles lined up neatly, I’m trying to give the items without images a default transparent image. However, it doesn’t seem to be working.

    Here’s roughly what the relevant piece of my code looks like:

    # item_list is a list of everything to go on the table
    # data_list is a dictionary that will go to ListDataSource
    for item in item_list:
        if check_for_star(item):
            img = ui.Image.named('iob:ios7_star_outline_24')
            img = PIL.Image.new('RGBA',(24,24), (255, 255, 255, 0))
        data_list.append({'title' : item, 'image' : img})
    view['tableview'].data_source = ListDataSource(data_list)

    The TableView displays as if the PIL images are None. I thought maybe it needs to be a ui.Image instead, so I tried doing this:

    img = ui.Image.from_data(PIL.Image.new('RGBA',(24,24), (255, 255, 255, 0)).toString())

    The img variable is still treated like None. Am I missing something? I can use img.show() with the PIL images and they look fine.

    In case this helps, here’s an example of what the output looks like. I want all of the title text to line up neatly.

    posted in Pythonista read more

Internal error.

Oops! Looks like something went wrong!