• Ti Leyon

    @ittraining what exactly is a modern Python developer and what does he/she want and expect? Using “print” as a statement is not a bad habit but a valid proven concept dictated by an equally sound programming paradigm. I also happen to harbor the awful tradition of conceiving strings as arrays of ASCII values, a practice I do not intend to give up until a future new year resolution. These are among a slew of old fashion, deprecated (are they?) abstractions around which I built a substantial library that I do not want to “correct” according to the fancy of a few designers. In fact Python 3.xx is not an evolution of Python 2.xx but a drastic divergence. Usually, when such a paradigm shift is warranted, designers create a brand new language. Ritchie did not go with “B v2” but started “C”. So did Wirth by setting aside “Pascal” and starting “Modula”. I do want modern Python developers (whatever that means) to ride into the sunshine with their shiny Python 3.x. I just want them to live Python 2.x alone by not advocating to remove it from future releases of Pythonista. By the way, I do write codes that are compatible from Python 2.7 up to latest releases of Python 3.x when my targeted audience is varied. They are also GUI compatible across different platforms without changing any code. A few of my postings in this forum can attest to that. However, for my private routines, that work flawlessly, I want to keep them backward compatible with Python 1.x. Because sometimes I take them to my virtual computers running Windows 3.11 or Mac system 7 or OS 8 to prove to myself that I could have solved certain problems decades ago if I was not much dumber then. In my book real programmers don't eat quiche.

    posted in Pythonista read more
  • Ti Leyon

    @ccc With all due respect to you and @mikael, there is no way that Python 2 can be an issue if it is not activated. Even a file containing a virus is harmless if it is not executed. Fifteen years ago, I used to be fascinated by “Nimda” when it just came out and made all that damage. I used to open it (not execute it) and examine its object code without any problem. If Python 2 pauses some risk if it just sits within some Python 3 directory then Python 3 is more dangerous than its older sibling. I am just advocating to uphold the traditional Python 3 distribution model (with Python 2 included) and let a user decide if they want to be “safe” or not.

    posted in Pythonista read more
  • Ti Leyon

    @mikael I am not sure that I understand your point. Are you asserting that Python 2 is so “unsafe” that even if you are not using it through a shebang or otherwise, a remote rogue process can bypass IOS, guess that Python 2 is installed within Python 3, access the Pythonista sandbox and execute a script that will make your device explode or some other nefarious aim? If that is the case we should all uninstall any version of Pythonista at once. Otherwise, let the system stand as it is in all future releases without any extra complexity for the user and @OMZ.

    posted in Pythonista read more
  • Ti Leyon

    @ccc I too am absolutely oppose to the removal of Python 2 support from future releases of Pythonista. I couldn’t care less about the innumerable functions and syntaxes being constantly added to python or any other language for that matter. I implement models and solve problems using whatever language that is available in a specific system using the most basic construct possible. Any complex program can be reduced to statement, decision and iteration. If complexity arises, unless it is really extensive or not directly related to my code (such as a GUI), I tend to handle it myself and my way. It is nice to have sympy preinstalled but I would do fine without it. That said, I still mainly use “print” as a statement instead of a function and so many other concepts that might be evolving endlessly within the Python framework that I do not care about. It is therefore easier to place the shebang “#!python2” on top my scripts instead of unnecessarily correcting codes that already work.

    posted in Pythonista read more
  • Ti Leyon

    @themusicman Maybe you should try using UniPAGE then you may write and test your codes on all major platforms without modification (MS Windows, OS X, Linux, IOS [Pythonista], Android [Pydroid recommended]). For all the desktop environment you will need to install Kivy (already preinstalled in Pydroid). All the basic UI elements (Button, Text input, label etc…) are included. You do not have to install the module you can just add your code to it. I wanted to include TKinter to make it truly universal on most versions of Python with absolutely no installation necessary but I never got the chance to do it. I probably will try to spare some time in the coming weeks to do that. You may even use an extension to UniPAGE called Graphics Agnostic Python (GAP) which provides a visual interface designer that automatically generates a “.py” file with the complete interface.

    posted in Pythonista read more
  • Ti Leyon

    Hey @JonB did not you write a graphical file manager by the name of “PhoneManager”? I adapted and use it occasionally without the need to ever download “stash”. Do not get me wrong, “stash” is probably one of the best and most useful script published in this forum (as attest by its popularity). However, if you are not entirely dedicated to a specific OS it becomes costly (in time, memorizing and touch typing) to get involve in any CLI dedicated to that OS. @adrius42 you may probably get most of what you want by using “PhoneManager” and/or @cvp’s script and modify them to your need once you become familiar with the nitty-gritty of Pythonista under IOS.

    posted in Pythonista read more
  • Ti Leyon

    @uncompleted if you want to use pandas while on the move you should get yourself an Android device if you do not already own one. It does not seem that pandas is coming to Pythonista anytime soon. Meanwhile, the recent release of Pydroid 3 on the Android platform is a free, full featured python 3.6 implementation that includes PIP, Kivy and Pyqt5. You can use PIP to download most of the modules available on desktops including Pandas, Numpy, Scipy, Matplotlib, Scikit-learn, Jupyter etc... The only interesting modules that are not yet compatible seem to be Tensorflow and OpenCV. Of course Tkinter is not included but personally I do not think it is a big loss. By the way you may buy the Huawei MediaPad M3 8.0 for about US $200.00 on Amazon. This is a 2.3 Gz Octa Core device that easily outperforms the iPad mini 4. For scripts that includes modules available in Pythonista you may even bridge the UIs so you do not have to rewrite your codes. Here is an example showing one way to go about it: https://forum.omz-software.com/topic/4307/graphics-agnostic-python-gap.

    posted in Pythonista read more
  • Ti Leyon

    @scatter it is fairly easy to write cross UI platforms applications that run unmodified at the source code level on all major GUIs using python. That is if you plan to use specific UI elements and not trying to create warpers around a platform from the standpoint of another. I have published scripts in this forum (refer to this thread) that demonstrate the matter with fully functional modules. They cover the basic UI elements that (arguably) form the basis of most applications. They cover the Pythonista UI matched with the Kivy GUI. Integrating Tkinter maybe a little more complicated since it does not closely follow the same syntax structure as the others. However, it can be done with not much pain if you really want to go that route. Here is a simple demo that covers basic geometric forms and integrates all three GUIs automatically. I also developed a graphic designer that speeds up the coding of the interface that you may find here. Hope this helps.

    posted in Pythonista read more
  • Ti Leyon

    Since I intend to include “Tkinter” in future implementation of universal codes (refer to GAP in this forum) I went to investigate the 3.xx implementation of that module. They did take out the capitalization from “Tkinter”. Change the “Tkinter” block from “getgui()” to add one more exception (as shown below) and the script should run everywhere without modification.

                try:
                    from Tkinter import Tk
                    platform = 'Tk'
                    gui = object
                except:
                    import tkinter
                    import sys
                    sys.modules['Tkinter'] = tkinter
                    platform = 'Tk'
                    gui = object
    

    posted in Pythonista read more
  • Ti Leyon

    Once I saw this thread I thought about a straight Python implementation. Since it was already done I extended @enceladus snippet into a universal Python gradient demo. I also included @Phuket2 radial takes (well sort of) and added a square gradient. A “Next” button at the bottom right of the window cycles the view between linear, radial and square gradient fills. I tried to stay as close as possible to the spirit of @enceladus code. It detects and uses the Pythonista UI, Kivy or Tkinter automatically. Therefore, it should work on any Python distribution unmodified. Come to think of it I think that they change the capitalization for Tkinter in version 3.xx. Change the name accordingly if you are using any python version higher than 2.xx This is nothing serious though just some “silly” (as @Phuket2 put it) coding for fun. Below is the script.

    def getgui():
        try:
            import ui
            platform = 'Pythonista'
            gui = ui.View
        except:
            try:
                from kivy.uix.floatlayout import FloatLayout
                platform = 'Kivy'
                gui = object
            except:
                from Tkinter import Tk
                platform = 'Tk'
                gui = object
        return platform, gui
            
    platform, gui = getgui()
    
    if platform == 'Pythonista':
        import ui
    
    class MyView(gui):                    
        def __init__(self, platform, gradient, *args, **kwargs):
            self.gradient = gradient
            self.step_size = 3
            self.gradient_type = ['linear', 'radial', 'square']
            self.current_fill = 0
            self.grads = []
            self.platform = platform
            if self.platform == 'Pythonista':
                ui.View.__init__(self, *args, **kwargs)
                self.next_button = ui.Button(frame= \
                    (330, 360, 30, 60), title = 'Next')
                self.next_button.background_color = (0.4,0.4,0.4)
                self.next_button.action = self.next_fill
                self.next_button.height = 30
                self.next_button.width = 60
                self.next_button.tint_color = 'white'
                self.next_button.font = ('<system>', 12)
                self.add_subview(self.next_button)
            
            elif self.platform == 'Kivy':
                from kivy.uix.floatlayout import FloatLayout
                from kivy.uix.button import Button
                self.root = FloatLayout()
                self.frame = kwargs['frame']
                self.next_button = Button( text = 'NEXT',
                size_hint_y = None, size_hint_x = None,
                height = 30, width = 60, font_size = 12, pos = (330, 10),
                on_press = self.next_fill )
                self.root.add_widget(self.next_button)
    
            elif self.platform == 'Tk':
                from Tkinter import Tk
                from Tkinter import Canvas
                from Tkinter import Frame
                from Tkinter import Label
                from Tkinter import NW
                self.master = Tk()
                self.root = Canvas(self.master, width=kwargs['frame'][2], \
                                   height=kwargs['frame'][3])
                self.root.pack()
                self.frame = kwargs['frame']
                contour = Frame(self.master, height=30, width=60)
                contour.pack_propagate(0) # don't shrink
                label = Label(contour, text='NEXT', fg='white', bg='#585858', \
                              height=30, width=60)
                label.bind("<Button-1>", self.tk_button_down)
                label.bind("<ButtonRelease-1>", self.tk_button_up)
                
                label.pack()
                label.config(font=('TkDefaultFont',12), padx=0,pady=0)
                contour.place(x=330, y =360, anchor=NW)
            
        def next_fill(self, sender):
            self.current_fill += 1
            if self.current_fill == 3:
                self.current_fill = 0
            if self.platform == 'Pythonista':
                self.set_needs_display()
            else:
                self.draw()
            
        def tk_button_down(self, event):
            event.widget.config(bg='#00A5D4')
          
        def tk_button_up(self, event):
            event.widget.config(bg='#585858')
            self.next_fill(self.tk_button_up)
        
        def present_all(self, mode):
            if self.platform == 'Pythonista':
                self.present(mode)
            if self.platform == 'Tk':
                self.draw()
                self.root.mainloop()
            elif self.platform == 'Kivy':
                from kivy.base import runTouchApp            
                from kivy.core.window import Window
                Window.size = self.frame[2:4]
                self.draw()
                runTouchApp(self.root)
    
        def draw(self):
            x,y,w,h = self.frame
            ((fr,fg,fb), (tr, tg, tb)) = gradient       
            num_steps = int(w/self.step_size)
            for step in range(num_steps):
                x = step*self.step_size
                t = step/(num_steps * 1.0)
                if self.platform == 'Pythonista':
                    if self.gradient_type [self.current_fill] == 'linear':
                        path = ui.Path.rect(x,0,self.step_size,h)
                    elif self.gradient_type [self.current_fill] == 'radial':
                        if w - ((2 * step) * self.step_size) >= 0:
                            path = ui.Path.oval(x, x, w - 2*x, h-2*x)
                    elif self.gradient_type [self.current_fill] == 'square':
                        if w - ((2 * step) * self.step_size) >= 0:
                            path = ui.Path.rect(x,x,w - ((2*step) * \
                                (self.step_size)),h - (2*step)*self.step_size)
                        ui.set_color((fr*(1-t)+tr*t, fg*(1-t)+tg*t, fb*(1-t)+tb*t))
                        path.fill()
                    ui.set_color((fr*(1-t)+tr*t, fg*(1-t)+tg*t, fb*(1-t)+tb*t))
                    path.fill()
    
                elif self.platform == 'Tk':
                    if step == 0:
                        self.root.create_rectangle( 0, 0, w, h, \
                                                fill='black', outline='black')                    
                    cl = '#' + '%02x' % int((fr*(1-t)+tr*t) * 255) + \
                        '%02x' % int((fg*(1-t)+tg*t) * 255) + \
                        '%02x' % int((fb*(1-t)+tb*t) * 255)
                    if self.gradient_type [self.current_fill] == 'linear':
                        self.root.create_rectangle( x, 0, self.step_size + x, h, \
                                                fill=cl, outline=cl)
                    elif self.gradient_type [self.current_fill] == 'radial':
                        if w - ((2 * step) * self.step_size) >= 0:
                            self.root.create_oval( x + self.step_size, x + \
                                self.step_size, w - ((2*step) * (self.step_size)) \
                                + x, h - (2*step)*self.step_size + x, \
                                fill=cl, outline=cl)
                    elif self.gradient_type [self.current_fill] == 'square':
                        if w - ((2 * step) * self.step_size) >= 0:
                            self.root.create_rectangle( x, x, w - ((2*step) * \
                                (self.step_size)) + x, h - (2*step)*self.step_size \
                                + x, fill=cl, outline=cl)
                        
                elif self.platform == 'Kivy':
                    if step == 0:
                        from kivy.graphics import Color
                        from kivy.graphics import Rectangle
                    self.grads.append ((fr*(1-t)+tr*t, fg*(1-t)+tg*t, \
                                                 fb*(1-t)+tb*t))
                    self.root.canvas.add(Color (fr*(1-t)+tr*t, fg*(1-t)+tg*t, \
                                                 fb*(1-t)+tb*t))
                    if self.gradient_type [self.current_fill] == 'linear':
                        self.root.canvas.add(Rectangle(pos = (x, 0), \
                                                size = (self.step_size,h)))
                    elif self.gradient_type [self.current_fill] == 'radial':
                        if w - ((2 * step) * self.step_size) >= 0:
                            if step == 0:
                                from kivy.graphics import Line
                            self.root.canvas.add(Line(circle = (w/2, h/2, w - \
                                (2*step)*self.step_size), width = self.step_size))
                    elif self.gradient_type [self.current_fill] == 'square':
                        if w - ((2 * step) * self.step_size) >= 0:
                            self.root.canvas.add(Rectangle(pos = (x, x), size = \
                                                (w - (2*step)*self.step_size, \
                                                 h - (2*step)*self.step_size)))
                    self.root.remove_widget(self.next_button)
                    self.root.add_widget(self.next_button)
    
    w,h = 400,400 
    gradient = ((1,0,0) , (0,1,0))
    v = MyView(platform,gradient, frame=(0,0,w,h))
    v.present_all('sheet')
    
    

    posted in Pythonista read more

Internal error.

Oops! Looks like something went wrong!