omz:forum

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

    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 9
    • Posts 63
    • Best 11
    • Controversial 0
    • Groups 0

    mcriley821

    @mcriley821

    14
    Reputation
    1213
    Profile views
    63
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    mcriley821 Unfollow Follow

    Best posts made by mcriley821

    • RE: Dealing with a completion handler

      Found a better solution @cvp by digging in @JonB objc_hacks.

      import requests as r
      from bs4 import BeautifulSoup as soup
      from objc_util import *
      import notification
      import ctypes
      
      class _block_descriptor (Structure):
        _fields_ = [('reserved', c_ulong), ('size', c_ulong), ('copy_helper', c_void_p), ('dispose_helper', c_void_p), ('signature', c_char_p)]
      InvokeFuncType = ctypes.CFUNCTYPE(None, *[c_void_p, ctypes.c_int])
      class _block_literal(Structure):
        _fields_ = [('isa', c_void_p), ('flags', c_int), ('reserved', c_int), ('invoke', InvokeFuncType), ('descriptor', _block_descriptor)]
       
      
      def update_forum(_cmd,_comp):
      	comp=ObjCInstance(_comp)
      	blk=_block_literal.from_address(_comp)
      	blk.invoke(comp,1)
      	with open('most_recent.txt','rb') as f:
      		lst=f.readlines()
      		most_recent,count=lst[0][:-1],lst[1]
      	url='https://forum.omz-software.com/recent'
      	page=r.get(url)
      	page=soup(page.content,'html.parser')
      	newest=page.select('meta')[8]
      	content_name=newest.attrs.get('content')
      	content_name=bytes(content_name,'utf8')
      	post_count=newest.find_all('span')[2].attrs.get('title')
      	post_count=bytes(post_count,'utf8')
      	
      	if content_name != most_recent or post_count != count:
      		with open('most_recent.txt','wb') as f: 
      			f.writelines([content_name,
      			b'\n',
      			post_count])
      		notification.schedule(
      			message=f'Newest on the Forum: {content_name.decode()}',
      			action_url=url,
      			title='Pythonista Forum',
      			identifier='Forum_Updater'
      			)
      	#else:
      		#notification.schedule(
      			message='Nothing new...',
      			title='Pythonista Forum',
      			identifier='Forum_Updater'
      			)
      	return
      	
      scheduler=ObjCClass('NSBackgroundActivityScheduler').alloc().initWithIdentifier_('Scheduler')
      scheduler.setRepeats_(True)
      scheduler.setInterval_(10*60)
      scheduler.setTolerance_(60)
      scheduler.setQualityOfService_(25)
      
      block=ObjCBlock(update_forum,restype=None,argtypes=[c_void_p,c_void_p])
      scheduler.scheduleWithBlock_(block) 
      

      Sadly, it only works when in the app. It does free up the console though

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Module not found, after installing with pip in stash

      It’s likely that the module has dependencies that you haven’t installed, or that the module isn’t pure python. Both these problems will prevent you from using your module, but only the second one will prevent files from being downloaded to your phone.

      In the first case, find out the dependencies and install them too. In the second case, you’re kinda sol. You could try figuring out what the code does and rewrite it in python.

      More information like the error message and what module you’re trying to pip install would be helpful!

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Multiple dialog choices

      If you’re talking about a list dialog, just assign a variable when you call it.

      result = dialogs.list_dialog(title = 'Title', items = ['A', 'B', 'C'])
      

      If you want like a system dialog, you should use the console module.
      http://omz-software.com/pythonista/docs/ios/console.html#console.alert

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: If statement syntax error

      @OkieWolf this will throw an exception if the string can’t convert to a float. If you suspect that won’t happen, your code is fine. Otherwise my previous code would be more robust

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: If statement syntax error

      @OkieWolf
      try to format your code with the </> button, but from what I can tell, it looks like you’re missing a colon ':' after the conditions of the if statement

      Like so

      if sidea and sideb:#colon right here
          #do stuff
      
      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Reconnecting to WiFi

      You can use objc_util to check your connection type.

      from objc_util import * 
      
      
      NWPathEvaluator = ObjCClass('NWPathEvaluator')
      connection = NWPathEvaluator.sharedDefaultEvaluator()
      
      
      def isOnWifi():
      	info=connection.path()
      	if info.isExpensive():
      		#on cellular data
      		return False #Not on wifi
      	elif info.status() == 2:
      		#no connection
      		return False #Not on wifi
      	elif info.status() == 1:
      		#on wifi
      		return True #Wifi!
      	else:
      		return None #Unknown or Error 
      

      Will continue to see if there’s a way to retry a connection....

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Joystick UIControl ui wrapper?

      @mikael
      I just subclassed a ui.View object again and did some more stuff to check for changing the frame later with layout. Had to use layout or it wasn’t resizing correctly, or changing some of the attributes to make the stick/texture of the joystick not resize.

      I decided to start a github repo for Pythonista and posted it in there.

      https://github.com/mcriley821/Pythonista/blob/master/UIJoystick.py

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Setting widget font a little wonky in Pythonista3.3/iOS13

      The problem is that with iOS 13, you’re not supposed to load system fonts by name. It’s been advised against for a while by Apple, and iOS 13 will enforce it by returning Times New Roman after asking for a system font.

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Referring to ui.TextField

      @tmessers Just pass an argument called name to your make_textfield function and say name=name during the ui.TextField call.

      def make_textfield(text,frame,name):
          return ui.TextField(text=text,frame=frame,name=name)
      

      You can find all you’d need in

      http://omz-software.com/pythonista/docs/ios/ui.html#module-ui

      If I’m not mistaken, most ui objects (ui.Label, ui.TextView, etc) inherit the attributes of a ui.View (like name)

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Referring to ui.TextField

      Do you mean read the TextField text?

      user_typed = v['name_of_Textfield'].text
      

      Just make sure you name the TextField objects

      Edit: @cvp

      posted in Pythonista
      mcriley821
      mcriley821

    Latest posts made by mcriley821

    • What color space is this?

      I came across a weird difference of colors by passing in an un-normalized RGB tuple to the ui.set_color function. I was wanting just regular green (#00ff00) but instead I got a neon green.

      It happens anytime the green value is greater than 1 in the tuple. It stays the same after 2, so it’s almost as if it’s brightness is mapped from 1-> 2.

      What color space is this? I want to take full advantage of this in the color picker!

      import ui
      
      
      class Colors (ui.View):
      	def __init__(self, *args, **kwargs):
      		return super().__init__(self, *args, **kwargs)
      	
      	def draw(self):
      		neon = ui.Path.rect(5, 5, 100, 100)
      		ui.set_color((0, 2, 0))
      		neon.fill()
      		
      		normal = ui.Path.rect(110, 5, 100, 100)
      		ui.set_color(("#00ff00"))
      		normal.fill()
      
      
      example = Colors(bg_color="white")
      example.present() 
      
      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Touch Events outside of bounds

      @JonB @cvp
      Thank you for the suggestions! I ended up going the easy way and requiring to pass in the master view. Kept the TableView hidden on the master (and thus un-touchable) until the combobox is touched.

      posted in Pythonista
      mcriley821
      mcriley821
    • Touch Events outside of bounds

      Hello,

      I’m trying to make a custom UI view that allows the user to select an option from a drop down box (like a custom ComboBox).

      Everything seems to be working okay, until I actually try to select a row in the TableView. I know it has to do with the way that iOS does hit-testing for views, but I can’t think of an elegant way to get around this. The only thing I can think of is to customize the root view also (but I want to avoid that so I can simply import it to work with any view ootb).

      Essentially, the root view receives the location of the touch, and it then asks its subviews if they contain that touch in their bounds. The custom view then returns False since the touch isn’t in its bounds, although visually the touch is on the TableView.

      Apologies for any formatting confusion/differences (I’m on iPhone), and for any mistakes/issues I’m not completely finished yet!

      Here’s the code:

      import ui
      
      
      """ComboBox is a ui View class that allows a
      string to be chosen from a list of choices by
      tapping on the dropbox button."""
      class ComboBox (ui.View):
      	"""Initializing of ComboBox:
      		Accepts all kwargs of ui.View, as well as:
      			font -> Chosen string font
      			choices -> List of choice strings
      			selected_index -> Initial choice index
      			padding -> Internal padding around the label and dropdown button
                              button_tint -> Color of the dropbox button"""
      	def __init__(self, *args, **kwargs):
      		self.font = kwargs.pop(
      			'font', ('<System>', 20))
      		self.text_color = kwargs.pop(
      			'text_color', "black")
      		self.choices = kwargs.pop(
      			'choices', [""])
      		self.selected_index = kwargs.pop(
      			'selected_index', 0)
      		self.padding = kwargs.pop(
      			'padding', 3)
      		self.button_tint = kwargs.pop(
      			'button_tint', "grey")
      		kwargs.setdefault('border_width', 1.0)
      		kwargs.setdefault(
      			'border_color', '#e5e5e5')
      		kwargs.setdefault('corner_radius', 3.5)
      		ui.View.__init__(self, *args, **kwargs)
      		
      		# button for the dropbox
      		_x = self.width - self._padding - 30
      		_h = self.height - self._padding * 2
      		self.drop_button = ui.Button(
      			bg_color=self.bg_color,
      			frame=(_x, self._padding, 
      						 self.height, _h),
      			image=ui.Image('iow:arrow_down_b_24'),
      			tint_color=self.button_tint,
      			action=self.dropbox_should_open
      		)
      		
      		# label for selected item
      		# default to item 0
      		_w = self.width - self.drop_button.width - self._padding * 2
      		self.selected_label = ui.Label(
      			bg_color=self.bg_color,
      			alignment=ui.ALIGN_CENTER,
      			font=self.font,
      			text=self.choices[self.selected_index],
      			frame=(self._padding, self._padding, 
      						 _w, _h),
      			text_color=self.text_color
      		)
      		
      		# dropbox
      		_row_h = ui.measure_string(
      			self.choices[0], font=self.font)[1]
      		_row_h += self._padding
      		_h *= 5 if len(self.choices) > 5 else len(self.choices)
      		self.dropbox = ui.TableView(
      			bg_color=self.bg_color,
      			row_height=_row_h,
      			seperator_color=self.border_color,
      			data_source=self._data_source,
      			selected_row=-1,
      			allows_selection=True,
      			frame=(self._padding, self.height - 1,
      						 self.selected_label.width,
      						 _h),
      			border_color=self.border_color,
      			border_width=self.border_width,
      			corner_radius=self.corner_radius,
      			hidden=True,
      			touch_enabled=True
      		)
      		
      		# draw tableview although out of bounds
      		obj = self.objc_instance
      		obj.setClipsToBounds_(False)
      		
      		# add subviews
      		self.add_subview(self.selected_label)
      		self.add_subview(self.drop_button)
      		self.add_subview(self.dropbox)
      	
      	@property
      	def selected_index(self):
      		return self._selected_index
      	
      	@selected_index.setter
      	def selected_index(self, value):
      		if value < len(self.choices):
      			self._selected_index = value
      			if hasattr(self, 'selected_label'):
      				self.selected_label.text = self.choices[value]
      				self.set_needs_display()
      
      	@property
      	def selected_text(self):
      		return self.choices[self._selected_index]
      	
      	@property
      	def padding(self):
      		return self._padding
      	
      	@padding.setter
      	def padding(self, value):
      		if value < self.height / 2:
      			self._padding = value
      			self.set_needs_display()
      	
      	@property
      	def choices(self):
      		return self._data_source.items
      	
      	@choices.setter
      	def choices(self, value):
      		if type(value) is list and len(value) > 0:
      			ds = ui.ListDataSource(value)
      			ds.delete_enabled = False
      			ds.move_enabled = False
      			ds.font=self.font
      			ds.action=self.index_changed
      			ds.text_color=self.text_color
      			self._data_source = ds
      	
      	def layout(self):
      		# selected label layout
      		self.selected_label.width = self.width - self.height - self._padding * 2
      		self.selected_label.height = self.height - self._padding * 2
      		# drop button layout
      		self.drop_button.x = self.width - self.height
      		self.drop_button.width = self.height - self._padding
      		self.drop_button.height = self.height - self._padding * 2
      		# dropbox layout
      		self.dropbox.width = self.selected_label.width
      		self.dropbox.y = self.height
      		_h = ui.measure_string(
      			self.choices[0], font=self.font)[1]
      		_h += self._padding
      		_h *= 5 if len(self.choices) > 5 else len(self.choices)
      		self.dropbox.height = _h	
      	
      	def touch_began(self, touch):
      		print(touch)
      		if self._touch_in_frame(touch, self.selected_label.frame) and touch.phase == "began":
      			if self.dropbox.hidden:
      				self.dropbox_should_open(None)
      			else:
      				self.dropbox_should_close(None)
      
      	@staticmethod
      	def _touch_in_frame(touch, frame):
      		x, y, w, h = frame
      		xmin, xmax = x, x + w
      		ymin, ymax = y, y + h
      		x, y = touch.location
      		if xmin < x < xmax:
      			if ymin < y < ymax:
      				return True
      		return False
      	
      	def draw(self):
      		# draw the splitter border
      		p = ui.Path()
      		p.move_to(
      			self.selected_label.width + self._padding * 1.5, 0)
      		p.line_to(
      			self.selected_label.width + self._padding * 1.5,
      			self.height)
      		p.line_width = self.border_width
      		ui.set_color(self.border_color)
      		p.stroke()
      	
      	def dropbox_should_open(self, sender):
      		# animate drop box
      		if sender:
      			sender.action = self.dropbox_should_close
      		ui.animate(self.do_dropbox)
      	
      	def do_dropbox(self):
      		self.dropbox.hidden = not self.dropbox.hidden
      
      	def dropbox_should_close(self, sender):
      		if sender:
      			sender.action = self.dropbox_should_open
      		ui.animate(self.do_dropbox)
      
      	def index_changed(self, sender):
      		new_index = sender.selected_row
      		if new_index != self.selected_index and new_index != -1:
      			self.selected_index = new_index
      
      
      if __name__ == "__main__":
      	root = ui.View(bg_color="white")
      	combo = ComboBox(bg_color="white",
      									 choices=['test', 'test2'],
      									 corner_radius=3.5,
      									 )
      	combo.frame = (50, 50, 275, 40)
      	root.add_subview(combo)
      	root.present('sheet', hide_title_bar=True)
      
      
      posted in Pythonista
      mcriley821
      mcriley821
    • Trouble with Unicode

      Hey all,

      I’m modifying the keyboard example “Special Characters.py” to include all Unicode characters. I did this by scraping the Unicode code point range and category name from Wikipedia. It has a navigation view with all the categories in a scroll view, and then presents all the Unicode characters of that category.

      Anyhow, the problem is that I get spotty printability, but since the character is a valid Unicode character I can’t prevent it from displaying as 🠂. I don’t understand the problem since sys.maxunicode (1114111) suggests this shouldn’t be a problem...

      Is it due to the possibility that the iOS system font doesn’t have a rendering of these glyphs? How can I install Google Noto and access these glyphs (if that’s the issue).

      Code:

      #! python3
      import keyboard
      import ui
      
      with open('uni_blocks.txt', 'r') as block_file:
      	blocks = block_file.readlines()
      
      
      class BlocksView (ui.View):
      	def __init__(self, *args, **kwargs):
      		ui.View.__init__(self, *args, **kwargs)
      		self.glyph_sv = None
      		self.cat_sv = ui.ScrollView(
      			flex='WH',
      			frame=self.bounds
      		)
      		self.buttons = []
      		for block in blocks:
      			cells = block.split(' ')
      			start = cells[0]
      			end = cells[1]
      			name = ' '.join(cells[2:])
      			btn = self.create_button(name)
      			btn.action = self.cat_selected
      			btn.start = start
      			btn.end = end
      			self.cat_sv.add_subview(btn)
      			self.buttons.append(btn)
      		self.add_subview(self.cat_sv)
      	
      	def layout(self):
      		if self.cat_sv.on_screen:
      			bw = ui.get_screen_size()[0]
      			x, y = 2, 2
      			for button in self.buttons:
      				button.frame = (x, y, bw, 20)
      				y += 24
      			self.cat_sv.content_size = (0, (len(self.buttons) + 1) * 24 + 40)
      	
      	def cat_selected(self, sender):
      		# present another scroll view of unicode titled buttons
      		self.glyph_sv = ui.ScrollView(
      			name=sender.title,
      			frame=self.bounds,
      			flex='WH'
      		)
      		w = ui.get_screen_size()[0]
      		x = y = 2
      		rows = 1
      		for i in range(int(sender.start, 16), int(sender.end, 16)):
      			char = chr(i)
      			if char.isprintable() and not char.isspace():
      				btn = self.create_button(chr(i))
      				btn.action = self.insert_char
      				btn.number = i
      				btn.frame = (x, y, 35, 35)
      				x += 39
      				if x > w - 39:
      					x = 2
      					y += 39
      					rows += 1
      				self.glyph_sv.add_subview(btn)
      		self.glyph_sv.content_size = (w, (rows + 1) * 39 + 40)
      		self.navigation_view.push_view(self.glyph_sv, False)
      	
      	def create_button(self, name):
      		btn = ui.Button(title=name)
      		btn.font = ('<System>', 18)
      		btn.background_color = (1, 1, 1, 0.1)
      		btn.tint_color = 'white'
      		btn.corner_radius = 4
      		btn.size_to_fit()
      		return btn
      
      	def insert_char(self, sender):
      		if keyboard.is_keyboard():
      			keyboard.insert_text(sender.title)
      		else:
      			print(sender.title, sender.number)
      
      
      def main():
      	w = ui.get_screen_size()[0]
      	v = BlocksView(
      		frame=(0, 0, w, 133),
      		name='Categories',
      		flex='WH'
      	)
      	nav_view = ui.NavigationView(v)
      	nav_view.title_color = 'white'
      	if keyboard.is_keyboard():
      		keyboard.set_view(nav_view, 'expanded')
      	else:
      		# For debugging in the main app:
      		nav_view.bg_color = 'black'
      		nav_view.bar_tint_color='black'
      		nav_view.present('fullscreen', hide_title_bar=True)
      
      
      if __name__ == '__main__':
      	main()
      
      

      Source .txt:
      https://pastebin.com/raw/Y9Fsuykq

      Thanks!

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Odd behavior with gesture recognizers

      @mikael @JonB

      I think I figured out a solution that will work. Since the doubletap gesture was recognizing double-taps and gain access to self by inlining the objc method, I realized that’s all I really needed. I can initialize the TextView with editable=False, enable editing inside the objc method, and start editing. Then in the textview’s delegate, when editing is done, disable editing!

      Thank you guys for the help!

      Here’s the code if anyone is interested:

      from objc_util import *
      import ui
      
      UITap = ObjCClass('UITapGestureRecognizer')
      
      class Node (ui.View):
      	class TextViewDelegate (object):
      		def textview_did_change(self, tv):
      			try:
      				if '\n' == tv.text[-1]:
      					tv.text = tv.text[:-1]
      					tv.end_editing()
      			except IndexError:
      				pass
      		
      		def textview_did_end_editing(self, tv):
      			# do whatever with the text
      			tv.editable = False
      	
      	def __init__(self, *args, **kwargs):
      		ui.View.__init__(self, *args, **kwargs)
      		self.frame = (0,0,*(ui.get_screen_size()))
      		self.tv = ui.TextView(
      			name='node_label',
      			frame=(100, 100, 50, 50),
      			delegate=self.TextViewDelegate(),
      			bg_color='#b9b9ff',
      			editable=False
      		)
      		
      		tvObj = self.tv.objc_instance
      		
      		def handleTap_(_slf, _cmd, _gesture):
      			self.tv.editable = True
      			self.tv.begin_editing()
      			
      		self.target = create_objc_class(
      			'fake_target',
      			methods=[handleTap_]
      			).new()
      	
      		self.doubletap = UITap.alloc().initWithTarget_action_(
      			self.target,
      			'handleTap:'
      		)
      		self.doubletap.setNumberOfTapsRequired_(2)
      		tvObj.addGestureRecognizer_(
      			self.doubletap
      		)
      		self.add_subview(self.tv)
      
      	def will_close(self):
      		self.doubletap.release()
      		self.target.release()
      
      if __name__ == '__main__':
      	w, h = ui.get_screen_size()
      	view = Node(bg_color='white')
      	view.present()
      
      
      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Odd behavior with gesture recognizers

      @cvp TextField is even odder, having no gestureRecognizers. It probably has a view hierarchy with a TextView. Maybe I need to remove gestures from all underlying views of my TextView?

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Odd behavior with gesture recognizers

      @JonB I’ve seen @mikael’s repo, but based on personal reasons I’d rather not use it. I want to understand how things are working instead of importing.

      Anyhow, inlining the method did not fix the issue. Making tv a self attribute, and changing the method to:

      def handleTap_(_slf, _cmd, _gesture):
          self.tv.begin_editing()
      

      After the first double tap, a single tap suffices to start editing again. I also retained target (self.target).

      posted in Pythonista
      mcriley821
      mcriley821
    • Odd behavior with gesture recognizers

      I'm doing a project with ui and objc_util (typical). I'm getting this strange behavior when overriding a ui.TextView's gestures; the gesture's view is somehow re-overriding the gestures.
      The simplest code example I can muster is as follows:

      from objc_util import *
      import ui
      
      
      UITap = ObjCClass("UITapGestureRecognizer")
      
      
      class Node (ui.View):
          class TextViewDelegate (object):
              def textview_did_change(self, tv):
                  if '\n' == tv.text[-1]:
                      tv.text = tv.text[:-1]
                      tv.end_editing()
      
          def __init__(self, *args, **kwargs):
              ui.View.__init__(self, *args, **kwargs)
              self.frame = (0, 0, *(ui.get_screen_size()))
              tv = ui.TextView(
                  name="node_label",
                  frame=(100, 100, 50, 50),
                  bg_color="blue",
                  delegate=self.TextViewDelegate()
              )
              # this is where the interesting bit starts
              tvObj = tv.objc_instance
              # remove all the gestures of tv
              for gesture in tvObj.gestureRecognizers():
                  tvObj.removeGestureRecognizer_(gesture)
      
              # for a new gesture, we need a target and action
              # how to make self a target? not really sure
              # maybe making a "blank" target with the method 
              # would be enough? since self carries?
              # I tried making a target of self, but crashes
              target = create_objc_class(
                  "self",
                  methods=[self.handleTap_]
              ).alloc().init()
              # now we have a target and action
              # let's make the actual gesture
              doubletap = UITap.alloc().initWithTarget_action_(
                  target,
                  "handleTap:"
              )
              # make into an actual doubletap, and add to view
              doubletap.setNumberOfTapsRequired_(2)
              tvObj.addGestureRecognizer_(doubletap)
      
              # add the tv subview with a single gesture: doubletap
              # can confirm only one gesture by uncommenting below
              #print(self.objc_instance.gestureRecognizers())  # None
              #print(tvObj.gestureRecognizers())  # doubletap
              self.add_subview(tv)
      
      # Now, without @static_method, everything is fine up until
      # the below function is called -> results in TypeError of passing
      # 4 args to a 3 arg function, since the first arg is self. However,
      # with @static_method, we have to do some round-about trickery
      # to do what we want. 
          @static_method
          def handleTap_(_slf, _cmd, _gesture):
              gesture = ObjCInstance(_gesture)
              view = gesture.view()
      # More interesting stuff happens now. On the first call of handleTap_,
      # the next line prints only doubletap. On next calls, all the gestures 
      # have been reset
              print(view.gestureRecognizers())
      # we can only start editing now by becoming the first responder,
      # since we can't access self
              view.becomeFirstResponder()
      
      # I assume here that the call to becomeFirstResponder instantiates
      # a new TextView object somehow, yet this new object still contains
      # a doubletap gesture. Re-tapping the TextView in the UI will start
      # editing - no double tapping needed. 
      
      
      if __name__ == "__main__":
          w, h = ui.get_screen_size()
          view = Node(bg_color="white")
          view.present()
      
      

      What can I do to make self my target? Or how can I pass self to my method? Can I create a wrapper for the @static_method wrapper and pass self still? I'm stuck on what to do, since any direction I go seems to be a dead-end:

      • make self into a target = crash
      • @static_method = no reference to the true self instance
      • no @static_method = TypeError
      • can't use global variables, since I hope to have ~10 of these Nodes at a time

      Also, I'd prefer to not use a TextField since they have that awful bounding box. I also think this issue would carry to a TextField anyhow.

      Any ideas are greatly appreciated! I'm stumped!

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Can Pythonista set wifi off?

      No. You can’t turn off WiFi via Pythonista, unless you use Shortcuts.

      What problems are you having with Shortcuts?

      posted in Pythonista
      mcriley821
      mcriley821
    • RE: Pythonista with jailbroken device

      @ccc
      /bin contains:
      bash bunzip2 bzcat bzip2 bzip2recover cat chgrp chmod chown cp date dd df dir echo egrep false fgrep grep gunzip gzexe gzip kill launchctl ln ls mkdir mknod mktemp mv ps pwd readlink rm rmdir sed sh sleep stty su sync tar touch true uname uncompress vdir zcat zcmp zdiff zegrep zfgrep zforce zgrep zless zmore znew

      /sbin contains:
      dmesg dynamic_pager fsck fsck.sbin fsck_apfs fsck_apfs.sbin fsck_exfat fsck_exfat.sbin fsck_hfs fsck_hfs.sbin fsck_msdos fsck_msdos.sbin fstyp fstyp_msdos fstyp_ntfs fstyp_udf halt launchctl launchd launchd.sbin mount mount.sbin mount_apfs mount_apfs.sbin mount_devfs mount_fdesc mount_hfs mount_hfs.sbin mount_nfs newfs_apfs newfs_apfs.sbin newfs_hfs newfs_hfs.sbin pfctl pfctl.sbin quotacheck umount umount.distrib

      /usr/bin contains:
      7z 7za DumpBasebandCrash IOMFB_FDR_Loader PerfPowerServicesExtended [ abmlite appsearch apt apt-cache apt-cdrom apt-config apt-extracttemplates apt-ftparchive apt-get apt-key apt-mark apt-sortpkgs arch asn1Coding asn1Decoding asn1Parser autopoint awk b2sum base32 base64 basename basenc bashbug brctl c_rehash cap_mkdb captoinfo certtool cfversion chcon chflags chfn chown chsh cksum clear cmp comm compress csplit cut cycc cynject db_archive db_checkpoint db_convert db_deadlock db_dump db_hotbackup db_load db_log_verify db_printlog db_recover db_replicate db_stat db_tuner db_upgrade db_verify deviceinfo diff diff3 dircolors dirmngr dirmngr-client dirname doNotify dpkg dpkg-deb dpkg-divert dpkg-maintscript-helper dpkg-query dpkg-split dpkg-statoverride dpkg-trigger dselect du dumpsexp ecidecid env envsubst event_rpcgen.py expand expr factor faker file fileproviderctl find finger fmt fold footprint funzip gawk getconf getopt gettext gettext.sh gettextize getty gnupg2 gnutls-cli gnutls-cli-debug gnutls-serv gpg gpg-agent gpg-connect-agent gpg-error gpg-error-config gpg-wks-server gpgconf gpgparsemail gpgrt-config gpgscm gpgsm gpgtar gpgv groups gssc head hidutil hmac256 hostid hostinfo hpmdiagnose id idn2 infocmp infotocap install iomfsetgamma ip-print ipcrm ipcs join kbdebug kbxutil killall ksba-config last ldid ldrestart libassuan-config libgcrypt-config link locale locate login logname lsdiagnose lsvfs lz4 lz4c lz4cat lzcat lzcmp lzdiff lzegrep lzfgrep lzgrep lzless lzma lzmadec lzmainfo lzmore md5sum mkfifo mktemp mpicalc msgattrib msgcat msgcmp msgcomm msgconv msgen msgexec msgfilter msgfmt msggrep msginit msgmerge msgunfmt msguniq ncurses6-config ncursesw6-config nettle-hash nettle-lfib-stream nettle-pbkdf2 nfsstat ngettext nice nl nohup notificationWatcher nproc npth-config numfmt ocsptool od openURL openssl p11-kit p11tool pager pagesize passwd paste pathchk pax pbcopy pbpaste pinky pkcs1-conv play plistutil plutil powerlogHelperd pr printenv printf psktool ptx quota realpath recode-sr-latin renice reset restart runcon say sbdidlaunch sbreload scp script sdiff seq sexp-conv sftp sha1sum sha224sum sha256sum sha384sum sha512sum shred shuf snappy sort split srptool ssh ssh-add ssh-agent ssh-keygen ssh-keyscan stat stdbuf sum sw_vers sysdiagnose tabs tac tail tailspin tar taskinfo tee test tic time timeout toe toggleTether tput tr truncate trust tset tsort tty uicache uiduid uiopen unexpand uniq unlink unlz4 unlzma unrar unxz unzip unzipsfx update-alternatives updatedb uptime urlclip users vm_stat watchgnupg wc wget which who whoami xargs xgettext xz xzcat xzcmp xzdec xzdiff xzegrep xzfgrep xzgrep xzless xzmore yat2m yes zip zipcloak zipnote zipsplit zprint

      /usr/sbin contains:
      BTAvrcp BTAvrcp.sbin BTLEServer BTLEServer.sbin BTMap BTMap.sbin BTPbap BTPbap.sbin BlueTool BlueTool.sbin WiFiNetworkStoreModel.momd WirelessRadioManagerd WirelessRadioManagerd.sbin absd absd.sbin ac accton addNetworkInterface addNetworkInterface.sbin addgnupghome applecamerad applygnupgdefaults aslmanager aslmanager.sbin bluetoothd bluetoothd.sbin cfprefsd cfprefsd.sbin chown chroot ckksctl dev_mkdb distnoted distnoted.sbin edquota fairplayd.H2 fdisk filecoordinationd filecoordinationd.sbin hdik ioreg ioreg.sbin iostat ipconfig ipconfig.sbin mDNSResponder mDNSResponder.sbin mDNSResponderHelper mDNSResponderHelper.sbin mediaserverd mediaserverd.sbin mkfile nologin notifyd notifyd.sbin nvram nvram.sbin otctl pppd
      pppd.sbin pwd_mkdb quotaon racoon racoon.sbin reboot repquota rtadvd rtadvd.sbin scutil scutil.sbin spindump spindump.sbin sshd startupfiletool sysctl syslogd syslogd.sbin vifs vipw vsdbutil wifid wifid.sbin zdump zic

      Would that be the best way to do background cli commands to StaSh and report the stdout? Is there another way without launching a Web server?

      posted in Pythonista
      mcriley821
      mcriley821