• mikael

    @RocketBlaster05, from the docs:

    scene.run(scene, orientation=DEFAULT_ORIENTATION, frame_interval=1, anti_alias=False, show_fps=False, multi_touch=True)

    Runs the given Scene object. By default, the scene runs in the current device orientation, set the parameter to PORTRAIT or LANDSCAPE to force a specific orientation (and to disallow auto-rotation). Important: The orientation parameter has no effect on iPads starting with iOS 10 because it is technically not possible to lock the orientation in an app that supports split-screen multitasking.

    posted in Pythonista read more
  • mikael

    @halloleooo, from what I read, share extensions should have a 120 MB memory limit, not sure how much Pythonista takes.

    posted in Pythonista read more
  • mikael

    @alexsunnyx123, there is no keyboard shortcut in the product. People have used their own scripts to add a shortcut in the past. An example of commenting the current line by code is in the Pythonista docs, and I think you can add a shortcut for an external keyboard, but do not have the code handy.

    posted in Pythonista read more
  • mikael

    @halloleooo, you could explicitly write lines to a file at different points of your script, starting with a version that does nothing much, before adding the image handling.

    pathlib.Path.write_text is a convenient one-liner for this.

    posted in Pythonista read more
  • mikael

    @felciano, the only thing that comes to mind right away is to set the Working Copy repo to synchronise with an iCloud folder. Then you can create the share extension from the iCloud folder.

    posted in Pythonista read more
  • mikael

    @cvp, curious about the del bIO, what is it for?

    posted in Pythonista read more
  • mikael

    @ccc, what is the Django requirement that is a show-stopper for Pythonista?

    posted in Pythonista read more
  • mikael

    @groesch16, here’s a quick demo with meeting type selector at top and then a list of names to choose from:

    import ui
    
    
    meeting_types = ('EMS', 'Fire')
    
    # Names loaded from db
    
    members = (
        ('First', 'Last'),
        ('Another', 'Second'),
    )
    
    
    class Members(ui.ListDataSource):
        
        def __init__(self, members):
            super().__init__(members)
            self.members = members
        
        def tableview_cell_for_row(self, tableview, section, row):
            cell = ui.TableViewCell()
            first, last = self.members[row]
            cell.text_label.text = f"{last}, {first}"
            return cell 
        
        
    # UI elements   
    
    root = ui.View(name="Roll Call")
    
    meeting_selector = ui.SegmentedControl(
        segments=meeting_types,
        selected_index=0,
        frame=(0, 0, 100, 40), flex='W',
        background_color='grey',
    )
    
    table = ui.TableView(
        allows_multiple_selection=True,
        frame=(0, 40, 100, 60), flex='WH',
    )
    table.data_source = Members(members)
    
    save_button = ui.ButtonItem(title='Save')
    root.right_button_items = [save_button]
    
    # Process results
    def save_names_to_db(sender):
        selected_meeting_type = meeting_types[meeting_selector.selected_index]
        
        selected_names = [members[row] for _, row in table.selected_rows]
        
        # Save selected_names to db here
        print(f"Meeting: {selected_meeting_type}")
        print(f"Present: {selected_names}")
        
    save_button.action = save_names_to_db
    
    root.add_subview(meeting_selector)
    root.add_subview(table)
    
    root.present('fullscreen')
    

    posted in Pythonista read more
  • mikael

    @groesch16, my suggestion would be to have meeting type selection at the top, then a tableview with all names. You select those present, and click Save to save selected names to the database (and if you like, unselected names as ”not here”).

    If that sounds useful, I can do a quick demo for you.

    posted in Pythonista read more
  • mikael

    @groesch16, just to clarify my understanding before offering advice:

    You have 3 types of situations where you need a roll call. Does the group of people who could be present differ, or is it always the same?

    posted in Pythonista read more
  • mikael

    @groesch16, for your use case, a TableView could also be convenient. It supports multiple selection, so you could just scroll through the list and make selections (and correct mistakes), then press save.

    posted in Pythonista read more
  • mikael

    @groesch16, here’s as short as possible, but runnable as-is, example of how I would do this without extra counters, using a simple generator expression (get_member).

    I have left out last name, ”Not here” and db handling for brevity.

    import console
    import ui
    
    
    # Data
    
    members = (
        ('First', 'Last'),
        ('Another', 'Second'),
    )
    get_member = (member for member in members)
    
    present_members = 0
            
    # UI elements
    
    firstname_label = ui.Label(
        text_color='white',
        height=50, flex='W',
    )
    
    here_button = ui.Button(
        title="Here",
        y=50, height=50, flex='W',
        tint_color='white', background_color='grey',
    )
    
    # Logic
    
    def show_next_member():
        member = next(get_member, None)
        if member:
            first, last = member
            firstname_label.text = first
        else:
            console.alert('All members shown')
    
    show_next_member()  # First name shown at start
    
    def count_here(sender):
        global present_members
        present_members += 1
        sender.title = f'Here - {present_members}'
        show_next_member()
    
    here_button.action = count_here
    
    root = ui.View()
    root.add_subview(firstname_label)
    root.add_subview(here_button)
    
    root.present('fullscreen')
    

    posted in Pythonista read more
  • mikael

    @Drizzel, UI applications work just like on an iPad.

    posted in Pythonista read more
  • mikael

    @Ahab3030, button needs to have tint color set to be visible, recommend setting the background color as well.

    posted in Pythonista read more
  • mikael

    @timjhinton, also, if you have just four walls, would seem simpler to have a rectangle that defines the area inside the walls, and restrict player position to be within that rectangle (by making a ”tentative” change to the coordinates and using Rect.contains_point to check if it can be really applied). This has the additional benefit that the check code can be shared by all of the four buttons.

    (Thanks for a well-presented question!)

    posted in Pythonista read more
  • mikael

    @mr_w, there is something wonky about ImageView, at least based on some the issues that I have seen here in the forums.

    Without really fixing anything, here are a couple of things you could try to start with:

    • Put an on_main_thread decorator on the touch_began call
    • Use the ui4.gestures module instead of touch_began (pip install ui4 in stash)

    posted in Pythonista read more
  • mikael

    @kaan191, good to hear you are having fun! I have been a bit quiet here lately, which just means I have a ”hot Pythonista project” on that takes up most of my time.

    See below for the script I used to communicate with my Pi. I have it configured in Pythonista actions in three different modes:

    1. Move this file to Pi
    2. Move this directory to Pi
    3. Run this file on Pi – move the file, run it, and show the output in Pythonista.
    #coding: utf-8
    import paramiko
    import editor, console
    import os.path
    import sys
    
    console.clear()
    
    local_path = editor.get_path()
    remote_path = os.path.basename(local_path)
    local_dir_path = os.path.dirname(local_path)
    remote_dir_path = local_dir_path.split('/')[-1]
    
    print('Open SSH connection')
    s = paramiko.SSHClient()
    s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    s.connect(<local IP address>, 22, username=<username>, password=<password>, timeout=4)
    sftp = s.open_sftp()
    
    fixed_local_root = None
    fixed_remote_root = <target dir under root on Pi>
    try:
      sftp.mkdir(fixed_remote_root)
    except:
      pass # Ok if already exists
    
    if sys.argv[1] == 'dir':
      print('--- Send directory')
    
      #sftp.put(local_dir_path, remote_dir_path)
      #parent = os.path.split(local_dir_path)[1]
      prefix_len = len(local_dir_path)
      for walker in os.walk(local_dir_path):
        remote_sftp_path = remote_dir_path +  walker[0][prefix_len:]
        if remote_sftp_path.endswith('/'):
          remote_sftp_path = remote_sftp_path[:-1]
        try:
          pass
          #sftp.mkdir(os.path.join(remotepath, walker[0]))
        except:
          pass
        for file in walker[2]:
          print('put', os.path.join(walker[0],file), remote_sftp_path + '/' + file)
          #sftp.put(os.path.join(walker[0],file),os.path.join(remotepath,walker[0],file))
    else:
      print('--- Send file')
      sftp.put(local_path, remote_path)
    
    if sys.argv[1] == 'run':
    
      print('--- Run it')
      stdin, stdout, stderr = s.exec_command('python3 ' + remote_path)
      
      for line in stdout.readlines():
        print(line.rstrip('\n'))
      
      s.close()
      
      print('--- Done')
      
      for line in stderr.readlines():
        print('ERROR:', line.rstrip('\n'))
        
    print('--- Complete')
    

    posted in Pythonista read more
  • mikael

    I tried pytest again, and running this file in my project root directory lets me run all the tests in the tests directory:

    from pathlib import Path
    
    import pytest
    
    
    pytest.main(["-p", "no:faulthandler", str(Path(__file__).parent / "tests")])
    

    posted in Pythonista read more
  • mikael

    @Penguin-Master, <|> is the marker for positioning the cursor after the snippet is inserted, so it is not included in the result.

    posted in Pythonista read more
  • mikael

    @rxvan, the package that contains attr.s is installed with pip install attrs (note the s) and imported with attr (no s). There is also a package called attr which is also imported with attr but does not contain attr.s.

    Looks like you have the wrong one. Try removing that and installing attrs.

    posted in Pythonista read more
Internal error.

Oops! Looks like something went wrong!