@rb I haven't had any issues with iPadOS17.
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 bosco
-
RE: Segmentation fault using dialogs
@cvp I agree!!! I almost give up on this forum. I hope your continued presence here indicates that your health is headed in the right direction.
-
RE: "What SSH Key Format Does Pythonista Require? Getting 'not a valid ec private key file' Error"
@FloMaster I'm also not an expert with SSH, but are you using the full path to the key file? You might try this.
client.connect('IP', username='florian', key_filename=os.path.expanduser('~/path to key'))
Pythonnista uses a very old version of paramiko.
-
RE: Segmentation fault using dialogs
@LankyDonkey
You may be able to run your dialogs in a new thread and save the @ui.in_background for the playback.from threading import Thread, current_thread def _in_background(fn, *args, **kwargs): d1 = Thread(target=fn, args=args) d1.start() def in_background(fn): def run(*args, **kwargs): def _run(): return fn(*args, **kwargs) if current_thread().name.startswith('Dummy'): return _in_background(_run) else: return(fn(*args, **kwargs)) return run @in_background def search_button_tapped(self,sender):
-
RE: Segmentation fault using dialogs
@LankyDonkey Hello!
You may want to try with a @ui.in_background decorator.@ui.in_background def search_button_tapped(self,sender): form_list_of_sections = [] search_dicts = []
Also, I have created a more complete dialogs replacement that might work for you here:
https://gist.github.com/sbbosco/cb44f88960c16a33704cc9f92980a113You can test the replacement module with this script:
import sys, os, time from datetime import datetime import ui import dialogs # from uidialogs import dialogs """ test for modified dialog module: https://gist.github.com/sbbosco/cb44f88960c16a33704cc9f92980a113 """ today = datetime.now() sections = [('Special Filters', [{'key': 'limit', 'title': 'Artist Limit (0 for None):', 'type': 'number', 'value': '30'}, {'key': 'switch', 'title': 'Switch: ', 'type': 'switch', 'value': True }, {'key': 'date', 'title': 'Date: ', 'type': 'datetime', 'format': '%m-%d-%Y %H:%m', 'style': 'inline', 'value': today }, {'key': 'country_count', 'title': 'Country Count: ', 'type': 'check'}, {'key': 'best_artists', 'title': 'Best Artists: ', 'type': 'check'}, {'key': 'best_albums', 'title': 'Best Albums: ', 'type': 'check'}, {'key': 'best_genres', 'title': 'Best Genres: ', 'type': 'check'}, {'key': 'best_years', 'title': 'Best Years: ', 'type': 'check'}, {'key': 'best_decades', 'title': 'Best Decades: ', 'type': 'check'}, {'key': 'one_hit_wonders', 'title': 'One Hit Wonders: ', 'type': 'check'} ]), ('Year Range', [{'key': 'year_from', 'title': 'Year From:', 'type': 'number', 'value': '1990'}, {'key': 'year_to', 'title': 'Year To: ', 'type': 'number', 'value': '2022'}, {'key': 'one_song', 'title': 'One Song: ', 'type': 'check', 'value': False}, {'key': 'missing_song_info', 'title': 'Missing Song Info:', 'type': 'check', 'value': False}, {'key': 'song_info', 'title': 'Song Info:', 'type': 'check', 'value': False}, {'key': 'sub_and', 'title': 'Subgenre AND:', 'type': 'check', 'value': False}, {'key': 'xmas', 'title': 'Include Xmas Songs?', 'type': 'check', 'value': False}, {'key': 'pos_from', 'title': 'Pos From: ', 'type': 'number', 'value': ''}, {'key': 'pos_to', 'title': 'Pos To:', 'type': 'number', 'value': ''}, {'key': 'missing_pos', 'title': 'Missing Pos:', 'type': 'check', 'value': False}, {'key': 'us_pos_from', 'title': 'US Pos From: ', 'type': 'number', 'value': ''}, {'key': 'us_pos_to', 'title': 'US Pos To:', 'type': 'number', 'value': ''}]), ('Rating', [{'title': '3', 'type': 'check', 'value': True}, {'title': '4', 'type': 'check'}, {'title': '5', 'type': 'check'}]), ('Speed', [{'title': 'S5', 'type': 'check'}, {'title': 'S4', 'type': 'check'}, {'title': 'S3', 'type': 'check'}, {'title': 'S2', 'type': 'check'}, {'title': 'S1', 'type': 'check'}, {'title': 'Missing', 'type': 'check'}]), ('Popularity', [{'title': '[10]', 'type': 'check'}, {'title': '[9]', 'type': 'check'}, {'title': '[8]', 'type': 'check'}, {'title': '[7]', 'type': 'check'}, {'title': '[6]', 'type': 'check'}, {'title': '[5]', 'type': 'check'}, {'title': '[4]', 'type': 'check'}, {'title': '[3]', 'type': 'check'}, {'title': '[2]', 'type': 'check'}, {'title': '[1]', 'type': 'check'}, {'title': '[0]', 'type': 'check'}]), ('Charts', [{'title': '50s', 'type': 'check'}, {'title': '60s', 'type': 'check'}, {'title': '70s', 'type': 'check'}, {'title': '80s', 'type': 'check'}, {'title': '90s', 'type': 'check'}, {'title': '2000s', 'type': 'check'}, {'title': '2010s', 'type': 'check'}, {'title': '2020s', 'type': 'check'}]), ('Genres', [{'title': 'Rock', 'type': 'check'}, {'title': 'Pop', 'type': 'check'}, {'title': 'Indie', 'type': 'check'}, {'title': 'Rap', 'type': 'check'}, {'title': 'Thrash', 'type': 'check'}, {'title': 'Country', 'type': 'check'}, {'title': 'Dance', 'type': 'check'}, {'title': 'Disco', 'type': 'check'}, {'title': 'Soul', 'type': 'check'}, {'title': 'Post-punk', 'type': 'check'}, {'title': 'Punk', 'type': 'check'}]), ('Sub Genres', [{'title': 'Aor', 'type': 'check'}, {'title': 'Modernindie', 'type': 'check'}, {'title': 'Modernrock', 'type': 'check'}, {'title': 'Summer', 'type': 'check'}, {'title': 'Classicrock', 'type': 'check'}, {'title': 'Northernsoul', 'type': 'check'}, {'title': 'Indierock', 'type': 'check'}, {'title': 'Drumnbass', 'type': 'check'}, {'title': 'Funk', 'type': 'check'}, {'title': 'Hairmetal', 'type': 'check'}, {'title': 'Blues', 'type': 'check'}, {'title': 'Reggae', 'type': 'check'}, {'title': 'Breakdance', 'type': 'check'}, {'title': 'Garage', 'type': 'check'}, {'title': 'Heavymetal', 'type': 'check'}, {'title': 'House', 'type': 'check'}, {'title': 'Cheese', 'type': 'check'}, {'title': 'Billy', 'type': 'check'}, {'title': 'Grime', 'type': 'check'}, {'title': 'Rare', 'type': 'check'}, {'title': 'Yachtrock', 'type': 'check'}, {'title': 'Synthpop', 'type': 'check'}]), ('Occasions', [{'title': 'Christmas', 'type': 'check'}, {'title': 'Bonfire', 'type': 'check'}, {'title': 'Halloween', 'type': 'check'}, {'title': 'Birthday', 'type': 'check'}]), ('Tempo', [{'title': 'Slow', 'type': 'check'}, {'title': 'Normal', 'type': 'check'}, {'title': 'Fast', 'type': 'check'}, {'title': 'Not slow', 'type': 'check'}])] def display(playlist_filter): result = dialogs.datetime_dialog(title='Date', done_button_title='Done', style='inline') print('result', result) print('form dialog standard') diag = dialogs.form_dialog(title = 'Song Filter', sections=sections) print('done') return diag @ui.in_background def button_tapped(sender): #result = display(None) result = dialogs.form_dialog(title = 'Song Filter', sections=sections) if result: print(result['year_to']) print(result['switch']) print(result['date']) print(result['3']) dialogs.alert('Result', 'Success') else: dialogs.alert('Result', 'Failed') if __name__ == '__main__': view = ui.View() view.name = 'Dialog Test' button = ui.Button(title='Tap me!') button.background_color = 'gray' button.tint_color = 'white' button.frame = (10, 10, 200, 100) button.action = button_tapped view.add_subview(button) view.present('fullscreen')
-
RE: Segmentation fault using dialogs
@omz @LankyDonkey @shinyformica
I have created a new issue here: Pythonista-Issues #707. -
RE: Segmentation fault using dialogs
@LankyDonkey Issue #1 is fixed in the latest update.
I thought I had the built in form dialog fixed with one line of code
c.cells = None
, but scrolling down to 'New Genre' it still crashes.I'll look at issue #2 in my version.
-
RE: Segmentation fault using dialogs
@LankyDonkey I'm glad it's working for you. There is an updated version.
-
RE: Segmentation fault using dialogs
@LankyDonkey I'm going to create an entry here https://github.com/omz/Pythonista-Issues/issues later today or tomorrow. I'll also create a new topic in this forum and mention @omz.
In the mean time, I may have a solution for you. I created an alternate form dialog module that you may want to try here: uidiaglogs.py
I'm still working on it. You'll want to hit the return key when modifying the Search field to dismiss the keyboard. It has never crashed when using this module.You can put uidialogs.py in the current folder and modify the import statement in your scripts.
#import dialogs from uidialogs import dialogs
-
RE: Segmentation fault using dialogs
@LankyDonkey Can you confirm that this script crashes when you run it multiple times after scrolling down?
#inport gc #gc.disable() import time, pprint import dialogs import objc_util retaincells = {} try_fix = False """ Dupicate issue: set try_fix = False run script scroll to RATING section, select 3, click Done or scroll unitl RATING section is a the top of the view. (larger phone may require more scrolling. rerun script It will usually crash when run the 2nd or 3rd time. """ def cleanup(): for key in retaincells.keys(): print(2, key) objc_util.release_global(retaincells[key].objc_instance) sections = [('Special Filters', [{'key': 'limit', 'title': 'Artist Limit (0 for None):', 'type': 'number', 'value': '30'}, {'key': 'country_count', 'title': 'Country Count: ', 'type': 'check'}, {'key': 'best_artists', 'title': 'Best Artists: ', 'type': 'check'}, {'key': 'best_albums', 'title': 'Best Albums: ', 'type': 'check'}, {'key': 'best_genres', 'title': 'Best Genres: ', 'type': 'check'}, {'key': 'best_years', 'title': 'Best Years: ', 'type': 'check'}, {'key': 'best_decades', 'title': 'Best Decades: ', 'type': 'check'}, {'key': 'one_hit_wonders', 'title': 'One Hit Wonders: ', 'type': 'check'} ]), ('Year Range', [{'key': 'year_from', 'title': 'Year From:', 'type': 'number', 'value': '1990'}, {'key': 'year_to', 'title': 'Year To: ', 'type': 'number', 'value': '2022'}, {'key': 'one_song', 'title': 'One Song: ', 'type': 'check', 'value': False}, {'key': 'missing_song_info', 'title': 'Missing Song Info:', 'type': 'check', 'value': False}, {'key': 'song_info', 'title': 'Song Info:', 'type': 'check', 'value': False}, {'key': 'sub_and', 'title': 'Subgenre AND:', 'type': 'check', 'value': False}, {'key': 'xmas', 'title': 'Include Xmas Songs?', 'type': 'check', 'value': False}, {'key': 'pos_from', 'title': 'Pos From: ', 'type': 'number', 'value': ''}, {'key': 'pos_to', 'title': 'Pos To:', 'type': 'number', 'value': ''}, {'key': 'missing_pos', 'title': 'Missing Pos:', 'type': 'check', 'value': False}, {'key': 'us_pos_from', 'title': 'US Pos From: ', 'type': 'number', 'value': ''}, {'key': 'us_pos_to', 'title': 'US Pos To:', 'type': 'number', 'value': ''}]), ('Rating', [{'title': '3', 'type': 'check'}, {'title': '4', 'type': 'check'}, {'title': '5', 'type': 'check'}]), ('Speed', [{'title': 'S5', 'type': 'check'}, {'title': 'S4', 'type': 'check'}, {'title': 'S3', 'type': 'check'}, {'title': 'S2', 'type': 'check'}, {'title': 'S1', 'type': 'check'}, {'title': 'Missing', 'type': 'check'}]), ('Popularity', [{'title': '[10]', 'type': 'check'}, {'title': '[9]', 'type': 'check'}, {'title': '[8]', 'type': 'check'}, {'title': '[7]', 'type': 'check'}, {'title': '[6]', 'type': 'check'}, {'title': '[5]', 'type': 'check'}, {'title': '[4]', 'type': 'check'}, {'title': '[3]', 'type': 'check'}, {'title': '[2]', 'type': 'check'}, {'title': '[1]', 'type': 'check'}, {'title': '[0]', 'type': 'check'}]), ('Charts', [{'title': '50s', 'type': 'check'}, {'title': '60s', 'type': 'check'}, {'title': '70s', 'type': 'check'}, {'title': '80s', 'type': 'check'}, {'title': '90s', 'type': 'check'}, {'title': '2000s', 'type': 'check'}, {'title': '2010s', 'type': 'check'}, {'title': '2020s', 'type': 'check'}]), ('Genres', [{'title': 'Rock', 'type': 'check'}, {'title': 'Pop', 'type': 'check'}, {'title': 'Indie', 'type': 'check'}, {'title': 'Rap', 'type': 'check'}, {'title': 'Thrash', 'type': 'check'}, {'title': 'Country', 'type': 'check'}, {'title': 'Dance', 'type': 'check'}, {'title': 'Disco', 'type': 'check'}, {'title': 'Soul', 'type': 'check'}, {'title': 'Post-punk', 'type': 'check'}, {'title': 'Punk', 'type': 'check'}]), ('Sub Genres', [{'title': 'Aor', 'type': 'check'}, {'title': 'Modernindie', 'type': 'check'}, {'title': 'Modernrock', 'type': 'check'}, {'title': 'Summer', 'type': 'check'}, {'title': 'Classicrock', 'type': 'check'}, {'title': 'Northernsoul', 'type': 'check'}, {'title': 'Indierock', 'type': 'check'}, {'title': 'Drumnbass', 'type': 'check'}, {'title': 'Funk', 'type': 'check'}, {'title': 'Hairmetal', 'type': 'check'}, {'title': 'Blues', 'type': 'check'}, {'title': 'Reggae', 'type': 'check'}, {'title': 'Breakdance', 'type': 'check'}, {'title': 'Garage', 'type': 'check'}, {'title': 'Heavymetal', 'type': 'check'}, {'title': 'House', 'type': 'check'}, {'title': 'Cheese', 'type': 'check'}, {'title': 'Billy', 'type': 'check'}, {'title': 'Grime', 'type': 'check'}, {'title': 'Rare', 'type': 'check'}, {'title': 'Yachtrock', 'type': 'check'}, {'title': 'Synthpop', 'type': 'check'}]), ('Occasions', [{'title': 'Christmas', 'type': 'check'}, {'title': 'Bonfire', 'type': 'check'}, {'title': 'Halloween', 'type': 'check'}, {'title': 'Birthday', 'type': 'check'}]), ('Tempo', [{'title': 'Slow', 'type': 'check'}, {'title': 'Normal', 'type': 'check'}, {'title': 'Fast', 'type': 'check'}, {'title': 'Not slow', 'type': 'check'}])] xfilter = {'best_years': False, 'charts': [], 'countries': [], 'country_count': False, 'genres': [], 'missing_pos': None, 'missing_song_info': False, 'occasions': [], 'one_song': False, 'popularity': [], 'pos_from': None, 'pos_to': None, 'rating': [], 'song_info': False, 'special_filters': {'best_albums': False, 'best_artists': False, 'country_count': False, 'limit': '30', 'one_hit_wonders': False}, 'speeds': [], 'sub_and': False, 'subgenres': [], 'tempos': [], 'us_pos_from': None, 'us_pos_to': None, 'xmas': False, 'year_from': '1990', 'year_to': '2023'} def display(playlist_filter): cleanup() retaincells.clear() def tableview_cell_for_row(tv, section, row): sel_item = c.sections[section][1][row] key = sel_item['key'] cell = c.cells[section][row] retaincells[key] = cell objc_util.retain_global(cell.objc_instance) return cell if try_fix: print('form dialog semi-fix') c = dialogs._FormDialogController('Song Filter', sections, done_button_title='Done') c.tableview_cell_for_row = tableview_cell_for_row c.container_view.present('sheet') c.container_view.wait_modal() if c.was_canceled: diag = None else: diag = c.values c.container_view = None else: print('form dialog standard') diag = dialogs.form_dialog(title = 'Song Filter', sections=sections) print('done') time.sleep(1) return xfilter if __name__ == '__main__': result = display(None) print(result['year_to'])
-
RE: Segmentation fault using dialogs
@LankyDonkey I completely agree!
I thought I had a work around several times, but it still crashes. This test replacement for FilterDialog.py uses static filter data and returns static result data. It doesn't even return the results from the dialog.If you comment out this line
#c.tableview_cell_for_row = tableview_cell_for_row
and then scroll down in the dialog and select 'Speed: S4', it crashed for me every time.
import time, pprint import dialogs import emoji sections = [ ('Special Filters', [ {'key': 'limit', 'title': 'Artist Limit (00 for None): ', 'type': 'number', 'value': '30'}, {'key': 'country_count', 'title': 'Country Count: ', 'type': 'check'} ]), ('Year Range', [ {'key': 'year_from', 'title': 'Year From: ', 'type': 'number', 'value': '1990'}, {'key': 'year_to', 'title': 'Year To: ', 'type': 'number', 'value': '2022'}, {'key': 'one_song', 'title': 'One Song: ', 'type': 'check', 'value': False}, ]), ('Rating', [ {'title': '1', 'type': 'check'}, {'title': '2', 'type': 'check'}, {'title': '3', 'type': 'check'}, {'title': '4', 'type': 'check'}, {'title': '5', 'type': 'check'}, {'title': '6', 'type': 'check'}, {'title': '7', 'type': 'check'}, {'title': '8', 'type': 'check'}, {'title': '9', 'type': 'check'}, {'title': '10', 'type': 'check'}, {'title': '11', 'type': 'check'}, {'title': '12', 'type': 'check'} ]), ('Speed', [ {'title': 'S5', 'type': 'check'}, {'title': 'S4', 'type': 'check'} ]) ] filter = {'best_years': False, 'charts': [], 'countries': [], 'country_count': False, 'genres': [], 'missing_pos': None, 'missing_song_info': False, 'occasions': [], 'one_song': False, 'popularity': [], 'pos_from': None, 'pos_to': None, 'rating': [], 'song_info': False, 'special_filters': {'best_albums': False, 'best_artists': False, 'country_count': False, 'limit': '30', 'one_hit_wonders': False}, 'speeds': [], 'sub_and': False, 'subgenres': [], 'tempos': [], 'us_pos_from': None, 'us_pos_to': None, 'xmas': False, 'year_from': '1990', 'year_to': '2022'} retaincells = {} def display(playlist_filter): def tableview_cell_for_row(tv, section, row): sel_item = c.sections[section][1][row] key = sel_item['key'] cell = c.cells[section][row] retaincells[key] = cell return cell #diag = dialogs.form_dialog(title = 'Song Filter', sections=sections) c = dialogs._FormDialogController('Song Filter', sections, done_button_title='Done') c.tableview_cell_for_row = tableview_cell_for_row c.container_view.present('sheet') c.container_view.wait_modal() if c.was_canceled: return None else: diag = c.values c.container_view = None pprint.pprint(diag) time.sleep(2) return filter
I'm going to try to create a very simple script to duplicate the issue that we can show @omz
-
RE: Segmentation fault using dialogs
@bosco This is one change I would make.
class MyListDataSource(ui.ListDataSource): def __init__(self, items, *args, **kwargs ): ui.ListDataSource.__init__(self, items, *args, **kwargs) self.width = ui.get_screen_size()[0] self.refresh(items) def refresh(self, items): self.all_items = items['items'] self.quiz_mode = items['quiz_mode'] self.font_size=items['font_size'] #self.items = [f"{index+1}.{item['title']} {item['artist']} {item['year']} [{item['rating']}] [{item['timeplayed']}]" for index, item in enumerate(self.all_items)] self.items = [f"{item['title']} {item['artist']} {item['year']} {item['score']} {item['album']}" for index, item in enumerate(self.all_items)] class SongViewer(ui.View): def __init__(self,songs): # stuff... # define self.song_titles once self.song_titles = MyListDataSource(dict(items = self.songs, quiz_mode = False, context = None, font_size = self.font_size)) # more stuff... #!! @on_main_thread def refresh_playlist(self): if self.playlist_filter: self.songs = self.MDB.apply_filter_2(self.playlist_filter, None) self.db_songs = self.songs self.refresh_songs() def refresh_songs(self): # refresh datasource items self.song_titles.refresh(dict(items = self.songs, quiz_mode = self.quiz_mode, context = None, font_size = self.font_size)) # ui.ListDataSource will auto reload when items change # skip code below """ self.table.data_source = self.table.delegate = self.song_titles self.song_titles.action=self.cell_tapped self.info.text=f"\n{self.get_playlist_filter_string()}" self.table.reload() """
I've been testing by clicking the filter_button, changing the 'from year' and 'done'. Should that be enough to make it crash?
-
RE: Segmentation fault using dialogs
@LankyDonkey Great! I'll try your code.
Have you tried the global variable I put in my last post?I did get your code to crash a couple times. I'm going to be offline for a few hours, but I'll look at it later.
-
RE: Unable to use ObjCBlock in pythonista3.4
@cvp I'm sure you've written a lot more code then me in the last 16 months. :-)
-
RE: Segmentation fault using dialogs
@LankyDonkey Do you ever get the dialog error the first time or only after self.filter_data becomes more complex?
global keepme keepme = None def display(some_data): #add some data to sections global keepme keepme = form_list_of_sections print(form_list_of_sections) diag = dialogs.form_dialog(title="Filter", sections=form_list_of_sections) #format result data and return
-
RE: Segmentation fault using dialogs
@LankyDonkey
add @ui.in_backgroundclass MainViewer(ui.View): def __init__(self): self.filter_data = dict(genre="", year=None) self.filter_button.action=handle_filter @ui.in_background def handlefilter(self, sender): res = FilterDialog.display(self.filter_data) if res: self.filter_data = res
-
RE: Unable to use ObjCBlock in pythonista3.4
From a conversation 16 months ago.
https://forum.omz-software.com/topic/6622/correct-way-to-call-pythonista-script-from-within-a-shortcuts-workflow/31?_=1683898691464# coding: utf-8 from rubicon.objc import Block, ObjCClass, ObjCInstance, py_from_ns from rubicon.objc.runtime import objc_id pressure = None @Block def handler(altitudeData:ObjCInstance, err:ObjCInstance) -> None: nspressure = ObjCInstance(altitudeData).pressure global pressure pressure = py_from_ns(nspressure) """ def bhandler(_data) -> None: nspressure = ObjCInstance(_data).pressure global pressure pressure = py_from_ns(nspressure) handler_block = Block(bhandler, None, (objc_id)) """ def get_pressure(output=True): CMAltimeter = ObjCClass('CMAltimeter') NSOperationQueue = ObjCClass('NSOperationQueue') if not CMAltimeter.isRelativeAltitudeAvailable(): print('This device has no barometer.') return altimeter = CMAltimeter.new() main_q = NSOperationQueue.mainQueue #altimeter.startRelativeAltitudeUpdatesToQueue_withHandler_(main_q, handler_block) altimeter.startRelativeAltitudeUpdatesToQueue_withHandler_(main_q, handler) if output: print('Started altitude updates.') try: while pressure is None: pass finally: altimeter.stopRelativeAltitudeUpdates() if output: print('Updates stopped.') return pressure if __name__ == '__main__': result = get_pressure(output=False) print(result) del pressure