omz:forum

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

    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 1
    • Topics 5
    • Posts 110
    • Best 20
    • Controversial 0
    • Groups 0

    bennr01

    @bennr01

    27
    Reputation
    2743
    Profile views
    110
    Posts
    1
    Followers
    0
    Following
    Joined Last Online

    bennr01 Unfollow Follow

    Best posts made by bennr01

    • StaSh version 0.7.0 released

      Hi everyone,
      some of you may have already noticed that StaSh version 0.7.0 0.7.1 was released a couple of months ago.
      It features a vast amount of changes since version 0.6.0 (including initial py3 compatibility).
      Please note that a forced update is required. Update by using selfupdate -f. Pythonista must be restarted after an update in order to allow the changes to become effective.

      A changelog is included at the end of this post.
      If you do not know what StaSh is, keep reading.

      Thanks to @ywangd for creating StaSh and allowing me to post the announcement on the forum.

      StaSh - Shell Like an Expert in Pythonista

      Inspired by shellista and its variants, StaSh is a serious attempt to implement a Bash-like shell for Pythonista.

      Since its initial release, valuable contributions and advices have been received
      constantly from the Pythonista community.
      The two most popular utilities are
      pip (authored by @briarfox)
      and git (authored by @jsbain).
      Remarkable contributions are also made by
      @dgelessus,
      @pudquick,
      @oefe,
      @cclauss,
      @georg.viehoever,
      @BBOOXX,
      @bennr01,
      @glider-gun,
      @steljas,
      @zrzka,
      @seanld,
      @zed,
      @sdushantha and
      @ywang-bom.

      StaSh stands for Pythonista Shell. While Sta may not be the best
      abbreviation for Pythonista, it forms a concise and meaningful word with the
      following Sh part. So the name StaSh was chosen to indicate it is a confined
      environment and great treasures may be found within.

      Installation

      StaSh can be easily installed via one line of python command
      (courtesy of @whitone).

      import requests as r; exec(r.get('http://bit.ly/get-stash').text)
      

      Simply copy the above line, paste into Pythonista interactive prompt and
      execute. It installs StaSh as a Python module under the site-packages
      folder (~/Documents/site-packages/stash) and copies a launching script,
      ~/Documents/launch_stash.py
      for easy access.

      StaSh works with both Pythonista 2 and 3, though not all commands support python3.

      If you have previous versions of StaSh installed (e.g. v0.4.x),
      You may need to restart Pythonista BEFORE the installation.

      If you have a GitHub tool available in Pythonista, such as
      gitview or
      gitrepo,
      you can choose to directly clone or download the
      repository.

      StaSh requires Pythonista v2.0 or Pythonista3 as the new ObjC feature is heavily used. For
      older Pythonista 1.5 compatible version, please refer to the
      v0.4 branch.

      Upgrade

      Once StaSh is installed, it can be easily updated by running the selfupdate
      command from within the shell.

      • selfupdate defaults to the master branch. To update from a different
        branch, e.g. dev, use selfupdate dev.
      • By default, selfupdate compares local and remote versions and only performs
        update if newer version is found. You can however force the update without
        version checking via selfupdate -f.
      • To check for newer version without actually install it, use selfupdate -n.
      • selfupdate manages StaSh installation folder and may delete files in the
        process. It is therefore recommended to not place your own scripts under
        $STASH_ROOT/bin. Instead, save your own scripts in~/Documents/bin or
        customise the locations with the BIN_PATH environment variable.
      • You may need to restart Pythonista after the update for changes to take full
        effects.

      selfupdate cannot be used for version 0.4.x and under. A fresh
      installation is needed.

      Version 0.7.0 requires a forced update. Please run selfupdate -f.

      Notable Features

      StaSh has a pile of features that are expected from a real shell. These
      features are what really set the difference from shellista.

      • Panel UI program that is completely event driven

        • No blocking thread, builtin interactive prompt is accessible at all time
        • Consistent look and feel as a proper PC terminal
        • Almost all scripts can be called from within StaSh, including programs
          using UI and Scene packages.
        • Attributed text (color and style) support
        • Multiple sessions are possible by opening additional Panel tabs
        • Being a pure UI program, it is possible to launch and forget. The program
          stays active indefinitely. Non-UI scripts can only run for 10 minutes
          in background. But StaSh can stay up forever (till memory runs out due to
          other Apps). You can just launch StaSh to run a few commands and leave it.
          It will still be there for you when you return later.
      • Comprehensive command line parsing and handling using
        pyparsing

        • Environmental variables, e.g echo $HOME, NAME=value
        • Aliases, e.g. alias l1='ls -1'
        • Single and double quotes behave like Bash, e.g. "*" means literal *,
          "$HOME" expands while '$HOME' does not.
        • Backslash escaping, e.g. ls My\ Script.py
        • Glob, e.g. ls ~/*.py
        • Backtick quotes for subprocess, e.g. touch `ls *.py`
        • Pipes to chain commands, e.g. find . -name "*.txt" | grep interesting
        • IO redirect (actually just Output redirect), e.g. ls *.py > py_files.txt.
          Input redirect can be achieved by using pipes.
          • It is possible to redirect to the Pythonista builtin console,
            e.g. ls > &3
        • Bang(!) to search command history, e.g. ls -1, !l. Bang commands like
          !! and !-1 also works.
      • Smart auto-completion just as expected

        • One UI button, Tab, is provided to enable command line auto-completion.
        • It is smart to complete either commands or files based on the
          cursor position
        • It also completes environment variables and aliases.
        • It also features a sub-command auto-completion system. For an example,
          type git sta and press Tab. It will auto-completes to git status .
          You can easily add your own sub-commands completion via JSON files.
      • Thread management allows multiple commands running in parallel

        • One foreground jobs and unlimited number of background jobs can run
          simultaneously.
        • A foreground job can be stopped by pressing the CC button or Ctrl-C
          on an external keyboard.
        • A background job is issued by appending an ampersand character (&)
          at the end of a normal command, e.g. httpserver &. It can be terminated
          by the kill command using its job ID.
        • A few utilities are provided for thread management.
          • jobs to list current running background jobs.
          • kill to kill a running job.
          • fg to bring background jobs to foreground
          • CZ button (Ctrl-Z) to send a foreground job to background
      • Command line history management. Three UI buttons are provided to navigate
        through the history.

      • On-screen virtual keys - an extra row of keys on top of the on-screen
        keyboard to provide control functions and easier access to symbols

        • Virtual keys for control functions including:
          • Tab - command line auto-completion
          • CC (Ctrl-C) - terminate the running job
          • CD (Ctrl-D) - end of Input
          • CU (Ctrl-U) - kill line
          • CZ (Ctrl-Z) - Send current running foreground job to background
          • KB - show/hide keyboard
          • H - display a popup window to show command history
          • Up - recall the previous command in history
          • Dn - recall the next command in history
        • Customisable virtual keys for commonly used symbols, e.g. ~/.-*|>.
          • The Symbols can be customized via the VK_SYMBOLS option in stash
            config file (default is .stash_config).
      • Swipe on the virtual key row to position cursor (similar to what Pythonista
        builtin editor offers)

      • External keyboard support

        • Tab key for auto-completion
        • Up (↑) / Down (↓) for navigating through command history
        • Ctrl-A and Ctrl-E to jump to the beginning and end of the input line,
          respectively
        • Ctrl-U to erase the input line
        • Ctrl-W to erase one word before cursor
        • Ctrl-L to clear the screen
      • You can run (almost) any regular python scripts from within StaSh

        • There is no need to customize them for the shell. If it can be executed by
          a python interpreter via python your_script.py, you can just call it from
          within StaSh by just typing your_script
        • The shell object is made available to scripts being called. This enables a
          range of complex interactions between the shell and called scripts.
          For an example, the running script can use the shell object to execute
          more commands, e.g. _stash('pwd').
      • You can give it a resource file, similar to .bashrc, to customize its
        behaviour. Like the Bash resource file, aliases, environment
        variables can be set here. The default resource file is .stashrc under
        StaSh installation root (i.e. ~/Documents/site-packages/stash).

        • The prompt is customizable with the PROMPT environment variable.
          • \w - current working directory with HOME folder abbreviated as ~
          • \W - last path component of current working directory
          • All other strings are displayed literally
          • The default setting is PROMPT='[\W]$ '
      • Easy self update to keep update with the development by running a single
        selfupdate command from within the shell.

      • The UI can be configured via configuration file to customize its font
        size and color. The default config file is .stash_config or stash.cfg
        under StaSh installation root.

      Usage

      The usage of StaSh is in principle similar to Bash. A few things to note are:

      • The search paths for executable scripts is set via an environment variable
        called BIN_PATH as PATH is used by the system. The default BIN_PATH is
        ~/Documents/bin:~/Documents/stash_extensions/bin:$STASH_ROOT/bin.

      • The executable files are either Python scripts or StaSh scripts. The type of
        script is determined by looking at the file extensions ".py" and ".sh".
        A file without extension is considered as a shell script.

        • When invoking a script, you can omit the extension, StaSh will try find the file
          with one of the extensions. For an example, StaSh interprets the command
          selfupdate and find the file selfupdate.py to execute.
        • Files without extension won't show up as an auto-completion possibility.
      • Commands can only be written in a single line. No line continuation is
        possible. However, multiple commands can be written in a single line by
        separating them with semicolons, e.g. ls -1 > file_list; cat file_list.

      • There are many Python scripts provided along with StaSh.
        These scripts range from performing
        regular shell tasks to advanced utilities like ssh and git. Note the
        scripts are by no means complete when compared to a real Linux shell. The
        collection will be gradually expanded should the need arise. It is
        also expected and appreciated that the community would come up with more
        scripts. The pip command may also install new commands.

        • alias.py - Define or print aliases
        • cat.py - Print contents of file
        • cd.py - Change current directory
        • clear.py - Clear console
        • cowsay.py - configurable speaking cow
        • cp.py - Copy file
        • crypt.py - File encryption using AES in CBC mode
        • curl.py - Transfer from an URL
        • cut.py - Cut out selection portions of each line of a file
        • dropbox_setup.py - Configure dropbox accounts for other commands
        • du.py - Summarize disk usage of the set of FILEs, recursively for directories
        • easy_config.py - UI for configuring stash
        • echo.py - Output text to console
        • edit.py - Open any text type files in Pythonista editor
        • find.py - Powerful file searching tool
        • fg.py - Bring a background job to foreground
        • ftpserver.py - A simple FTP server
        • gci.py - Interface to Python's built-in garbage collector
        • gh.py - GitHub interface
        • git.py - Git client ported from shellista
        • grep.py - search contents of file(s)
        • head.py - Display first lines of a file
        • httpserver.py - A simple HTTP server with upload function (ripped from
          https://gist.github.com/UniIsland/3346170)
        • jobs.py - List all jobs that are currently running
        • kill.py - Terminate a running job
        • latte.py - package manager
        • ls.py - List files
        • mail.py - Send emails with optional file attachment
        • man.py - Show help message (docstring) of a given command
        • mc.py - Easily work with multiple filesystems (e.g. local and FTP)
          synchronously.
        • md5sum.py - Print or check MD5 checksums
        • mkdir.py - Create directory
        • monkeylord.py - Manage monkey patches with the goal to make Pythonista more viable
        • more.py - Display output one screen page at a time
        • mount.py - Mount filesystems
        • mv.py - Move file
        • openin.py - Show the open in dialog to open a file in external apps.
        • pbcopy.py - Copy to iOS clipboard
        • pbpaste.py - Paste from iOS clipboard
        • ping.py - Ping remote hosts
        • pip.py - Search, download, install, update and uninstall pure Python
          packages from PyPI.
        • printenv.py - List environment variables
        • printhex.py - Print hexadecimal dump of the given file
        • pwd.py - Print current directory
        • python.py - Run python scripts or modules
        • python3.py - Run python3 scripts or modules
        • quicklook.py - iOS quick look for files of known types
        • rm.py - delete (remove) file
        • rmdir.py - delete (remove) directories
        • scp.py - Copy files from/to remote servers.
        • selfupdate.py - Update StaSh from its GitHub repo
        • sha1sum.py - Print of check SHA1 checksums
        • sha256sum.py - Print of check SHA256 checksums
        • sort.py - Sort a list, also see unique
        • source.py - Evaluate a script in the current environment
        • ssh.py - SSH client to either execute a command or spawn an interactive
          session on remote servers. pyte is
          used for terminal emulation and gives the command the feel of a
          full-fledged SSH client.
        • ssh-keygen.py - Generate RSA/DSA SSH Keys.
        • stashconf.py - Change StaSh configuration on the fly
        • tail.py - Print last lines of a FILE.
        • tar.py - Manipulate archive files
        • touch.py - Update timestamp of the given file or create it if not exist
        • totd.py - Print a random tip
        • umount.py - Unmount filesystems
        • uniq.py - Remove duplicates from list, also see sort
        • unzip.py - Unzip file, also see zip
        • version.py - Show StaSh installation and version information
        • wc.py - Line, word, character counting
        • webviewer.py - Open a url in the webbrowser
        • wget.py - get data from the net
        • whatis.py - Show a description for some of the commands
        • which.py - Find the exact path to a command script
        • wol.py- Wake on LAN using MAC address for launching a sleeping system
        • xargs.py - Command constructing and executing utility
        • zip.py - Zip file, also see unzip

      Acknowledgements

      • Pythonista is a wonderful piece of
        software.
      • StaSh is inspired by
        shellista
        and its variants, including
        ShellistaExt and
        ShellistaUI.
      • The UI part of StaSh has its root from ShellistaUI.
      • Many of the command scripts, e.g. ls.py, cp.py, mv.py, are taken from
        ShellistaExt with some modifications.

      Known Issues

      • Pickled objects are not restored correctly and generate AttributeError as
        if the class definition cannot be found.
      • Some commands may still not fully support python3.

      Contributing

      • Check any open issues or open a new issue to start discussions about your
        ideas of features and/or bugs
      • Fork the repository, make changes, and send pull requests
        • Please send pull requests to the dev branch instead of master

      Change Log

      Version 0.7.0 - 2018-05-04

      • New Features
        • Python 3 compatibility
          • StaSh now supports python 3, though some commands still need to be ported.
        • StaSh now shows a short tip on startup
        • pip now supports wheels and commandline scripts and has been improved greatly.
        • the python command now has an interactive console
        • man can now also show help for other topics, e.g. man monkeypatching
        • the monkeylord command helps improving desktop compatibility by providing monkeypatches for various modules and functions (e.g. subprocess)
        • easy_config.py allows you to easily configure your StaSh using a UI.
        • access other filesystems using the mount, umount and mc commands.
        • StaSh can now run commands specified in sys.argv, allowing command execution using the pythonista URL schema.
        • And many more improvements and bugfixes everywhere.
      • Command Scripts
        • cowsay.py
        • dropbox_setup.py
        • easy_config.py
        • ftpserver.py
        • gci.py
        • gh.py
        • head.py
        • latte.py
        • mc.py
        • monkeylord.py
        • more.py
        • mount.py
        • ping.py
        • python3.py
        • rmdir.py
        • tail.py
        • totd.py
        • umount.py
        • webviewer.py
        • whatis.py

      Version 0.6.0 - 2016-02-08

      • New Features

        • New thread management system enables multiple jobs running at once.
          • One foreground jobs and unlimited number of background jobs.
        • sys.stdin, sys.stdout and sys.stderr are now replaced system
          wide to allow IO dispatch based on running threads.
      • Improvements

        • Runtime state is now managed by threads for simplicity and readability.
        • Environment persistent level is now explicitly required by caller.
          No more magic top level thread.
      • Command Scripts

        • New scripts
          • jobs.py
          • kill.py
          • fg.py
          • curl.py

      Version 0.5.x - 2016-01-11

      • New Features

        • Attributed text (color and style) support
          • Default font size is now 14 on iPad (increased from 12)
        • True external keyboard support
        • Killable threads
        • StaSh is now installed as a Python module under ~/Documents/site-packages/stash
          • Also adds a launch script as ~/Documents/launch_stash.py for easy access
      • Improvements

        • Largely redesigned the logic of user/script IO handling (modelled after pyte)
        • Better scrolling
      • Command Scripts

        • New scripts
          • du.py - Summarize disk usage recursively
          • Replace selfupdate.sh with selfupdate.py to enable more sophisticated
            installation functions.

      Version 0.4.x

      • Improvements

        • Added launch_stash.py to run StaSh in a way that can survive through
          "global variable clearing" in Pythonista.
      • Command Scripts

        • New scripts
          • wol.py - Wake computer on LAN
        • Changed scripts
          • pbcopy.py - renamed from copy.py to avoid name conflict and to be consistent with the OSX tool.
          • pbpaste.py - renamed from paste.py.
      • Bug Fixes

        • sys.path is now correctly restored at command scripts exit.
        • Change directory no longer crashes when accessing folders inaccessible.

      Version 0.4.1 - 2015-03-06

      • New Features

        • StaSh now provides localized input history for running scripts.
        • New py_pdb config option to enable dropping into pdb when a runing
          script errors out. This makes it convenient to debug Python scripts
          inside StaSh.
        • Added ipython style (up-key) history search
      • Improvements

        • Started overhaul of the git command.
          • It now takes a more modular approach to separate complex sub-command
            into its own module.
          • branch, merge, reset, fetch sub-commands significantly
            improved.
          • Updated dependancies on latest dulwich release.
        • Press CC (Control-C) while script is waiting for user input no longer
          breaks sub-sequent user input.
        • Better docstring for scripts
        • Various bug fixes
      • Command Scripts

        • New scripts
          • stashconf.py - Change StaSh configuration on the fly
          • telnet.py - Simple telnet client
        • Changed scripts
          • pcsm.py - Removed. The scope of the design has been broadened to
            target all pythonista scripts. The script will be back when it is
            ready for the design change (under a different name). In the mean
            time, psiclient is a
            proof-of-concept client for Pythonista Script Index.

      Version 0.4.0 - 2015-01-29

      • New Features

        • New UI design with unified Input/Output areas
          • No more screen flashing when scrolling. Smooth scroll at all time
          • Support device rotation at any direction
          • Manipulate cursor position with ease
          • Consistent look and feel as a proper PC terminal
        • External keyboard support
          • Tab completion works flawlessly
          • Navigate through command history with ⌘ (cmd) + up (↑) / down (↓)
        • Swipe gesture on virtual key buttons
          • Similar to what Pythonista builtin editor offers, you can now swipe
            left/right on the extra virtual key row to position cursor with
            better control and precision
        • More virtual keys
          • Show/hide on-screen keyboard with the KB button.
          • Kill line easily with the CU (Ctrl-U) button
      • Improvements

        • Auto-completion now takes account of cursor position and completes the
          corresponding word fragment
        • You can now navigate back to the unfinished line when browsing through
          command history
        • Single Gist file installation just got better. Now it requires no
          additional steps
          . Simply run the script and the full stack of files
          will be installed.
      • Command Scripts

        • New scripts
          • crypt.py - File encryption using AES in CBC mode
        • Changed scripts
          • pcsm.py - scsm is renamed to pcsm (Pythonista Command
            Script Manager) to clearly state that the scripts are NOT StaSh
            specific. The Index
            repo
            is
            also renamed to Pythonista Command Script Index.
      • Various bug fixes

      Version 0.3.0 - 2015-01-25

      • New Features

        • The main _stash object is now callable. It is now more convenient for a
          Python script to issue Shell commands via the callable, e.g.
          _stash('ls'), _stash('pwd')
        • Sub-command auto-completion system configurable via a JSON file (currently
          supports pip and git)
        • Comments (both full line and trailing) are now allowed in shell scripts
        • All arguments are now by default converted from unicode type to str
          type with utf-8 encoding before passing them to external scripts. The
          change is to recognise that Python 2.x and its libraries are not fully
          unicode compliant. This behavior can be turned off in config file.
        • Added a config option, py_traceback, to display full Python exception
          trace stack for command scripts.
        • A lib folder is added for storing shared modules so command scripts do
          not have to include them separately.
          • These modules are stored as attributes of the main _stash object.
      • Improvements

        • Runtime now emulates sub-shell environment even more correctly.
        • Unit tests added with Travis CI support.
        • Documentation updates
      • Bug Fixes

        • Multi-statements separated by semicolon in a single line should now work
          correctly in all cases
        • White-spaces are now correctly recognized within double quotes
        • Shell scripts now correctly works with pipes
        • Various other bug fixes
      • Command Scripts

        • New scripts
          • pip.py - A pare-down client for PyPI that does search,
            install, remove, update, list, versions.
            • Only works for pure Python packages that do not require
              compilation
            • No dependency handling at this stage but will report failure if
              installed package failed to import (that may be caused by
              dependency)
          • git.py - Basic git client ported from shellista
            • Requires customized
              dulwich
              and gittle
              modules.
            • If the above modules are not installed, they will be automatically
              installed the first time git runs. However, if they exist
              already, please make sure the above customized versions are in
              use.
          • scsm.py - StaSh Command Script Manager (initial attempt to build
            an index and a client for command scripts that perform list,
            install, remove and info)
            • It is really in a test phase and open to all suggestions.
            • Check out the Index
              repo
              for
              how to register new command scripts
          • tar.py - Manipulate archive files (tar, gzip, bzip2 format)
          • find.py - Search file/directory recursively in a file hierarchy
          • xargs.py - Construct argument lists and execute
            • This command enables some quite powerful operations. A few
              examples are as follows:
              • Delete all tmp files: find . -n "tmp*" | xargs rm
              • Find all Python files and archive them: find ~/Documents -n "*.py" | xargs tar -zcvf scripts.tar.gz
              • Rename all log files to log.old: find . -n "*.log" | xargs -n 1 -I {} mv {} {}.log
          • mail.py - Send emails with optional file attachment
          • cut.py - Cut out selection portions of each line of a file
          • wc.py - Line, word and character count
          • md5sum.py - Print or check MD5 checksums
          • sha1sum.py - Print of check SHA1 checksums
          • sha256sum.py - Print of check SHA256 checksums
          • zip.py - Package and compress files and directories
        • Changed scripts
          • clear.py now replaces cls.py to be consisent with the Linux counterpart
          • cat.py - now usable on binary files
          • selfupdate.sh - now removes test related files.
          • unzip.py - now takes a -t option to show file contents
          • printenv.py - now ignores special environment variables, e.g. $1

      Version 0.2.0 - 2014-12-31

      • New Features

        • Added virtual keys for commonly used symbols, e.g. ~/.-*|>
          • The keys can be customized with VK_SYMBOLS option in .stash_config
        • Shell scripts can now access arguments via special environment variables
          ($0, $1, ..., $#, $@)
        • Exit status is now available as $?
        • Background jobs are now allowed by appending an ampersand at the end of a
          command, e.g. httpserver &.
          • Background jobs are executed in Pythonista main thread and can be
            terminated by tap the close button on the interactive prompt panel.
            This enables a script to perform housekeeping tasks recieving the
            KeyboardInterrupt exception. An example is the httpserver command.
            It releases the binding port when terminated and allows subsequent
            calls to the same command without restarting Pythonista.
      • Improvements

        • Parser is redesigned and optimized. It should be more efficient and
          faithful to Bash in some edge cases.
        • Runtime is optimized to make clear sub-shell emulation, especially on
          variable and environment passing between shells of different levels.
          • Multi-line shell scripts are now executed in a single thread for
            improved efficiency
        • Auto-completion enhanced
        • Command line history management enhanced
      • Command Scripts

        • New scripts
          • ssh.py - SSH client to either execute a command or spawn an
            interactive session on remote servers.
            pyte is used for terminal
            emulation and gives the command the feel of a full-fledged SSH client.
          • scp.py - Copy files from/to remote servers.
          • ssh-keygen.py - Generate RSA/DSA SSH Keys.
          • man.py - Show help message (docstring) of a given command
          • httpserver.py - A simple HTTP server with upload function
            (ripped from https://gist.github.com/UniIsland/3346170)
          • edit.py - Open any text type files in Pythonista editor
          • openin.py - Show the open in dialog to open a file in external apps.
          • quicklook.py - iOS quick look for files of known types
          • touch.py - Update timestamp of the given file or create it if not exist
          • source.py - Evaluate a script in the current environment
          • python.py - run python scripts or modules
          • which.py - Find the exact path to a command script
          • printhex.py - Print hexadecimal dump of the given file
          • version.py - Show StaSh installation and version information
        • Changed scripts
          • env.py - Replaced by printenv.py (env is now an alias to printenv)
          • bh.py - Removed. /dev/null is accessible in StaSh
          • selfupdate.sh - The GitHub branch to retrieve can now be customized
            via environment variable SELFUPDATE_BRANCH (default is master)
      • Various bug fixes

      Version 0.1.0 - 2014-12-10

      • initial release

      Links

      • Main StaSh forum thread
      • Pythonista 3 update thread
      • GitHub repo
      posted in Pythonista
      bennr01
      bennr01
    • RE: Problem with arrays

      I think you may be confusing a few different datatypes here, so I'll try to explain some approaches for your problem.

      First of, Python does not really have something like arrays. Usually, when one wants to use something akin to an array in Python, one uses a list instead. The main difference between a list and an array is that usually arrays are fixed size and often fixed type also while Python lists can have any required size and mixed types of elements. However, you wrote "same variables", so lists may not be what you are looking for. Still, heres a short tutorial for lists:

      # create a list
      l = []  # alternatively, use "l = list()"
      # add an element to a list
      l.append(1)
      # get the size of the list
      print(len(l))
      # get the first element (index is 0 as indexes start with 0)
      print(l[0])  # prints "1"
      # remove the first element
      del l[0]  # alternatively, use "l.pop(0)", which also returns the element
      

      Now let's take a look at how lists could be used for your problem:

      # number of players
      num_players = 4
      # number of variables each player has
      num_vars = 10
      
      # initiate a two-dimensional list with all players or variables
      # a two-dimensional list is a list of lists. In this case, all "variables" will be initialized as None.
      players = [[None] * num_vars] * num_players
      
      # set 2nd variable for player 3 to 12. Remember that indexes start at 0
      players[2][1] = 12
      # get 2nd variable for player 3
      print(players[2][1])  # prints "12"
      
      # ============= alternative =============
      # using math, we can do this a bit more efficient using 1-dimensional lists
      
      # number of players
      num_players = 4
      # number of variables each player has
      num_vars = 10
      
      # initiate a one-dimensional list with all players or variables
      players = [None] * num_vars * num_players
      # now we can access a variable by using index = (player_index * num_vars + var_index)
      
      # set 2nd variable for player 3 to 12. Remember that indexes start at 0
      players[2 * num_vars + 1] = 12
      # get 2nd variable for player 3
      print(2 * num_vars + 1)  # prints "12"
      
      

      However, as I said before, lists aren't a good solution for this. Let's take a look at another datastructure, the dict. A dict is a mapping of key-value pairs. Think of it like a dictionary, where each word you look up (in this case the key) has some associated words (the value). Here is an example of a dict usage:

      d = {}  # alternatively, use "d = dict()"
      # set a key to a value
      d["name"] = "bennr01"
      # get the number of defined keys in a dict
      print(len(d))  # prints "1"
      # get a value for a key
      print(d["name]")  # prints "bennr01"
      # remove a key-value pair
      del d["name"]
      

      Using dicts, you can refer to the variables using names. Here's how to use it for your problem:

      players = []
      # create a player here
      player_1 = dict(name="Player 1", score=0)
      players.apend(player_1)
      
      # set the score for the first player (again, index 0)
      players[0]["score"] = 100
      # get the score for the first player
      print(players[0]["score"])  # prints "100"
      
      # ============= alternative ==============
      # instead of using a list for all players, you could also use a dict
      
      players = {}  # <-- see the difference
      # create a player here
      player_1 = dict(name="Player 1", score=0)
      players[1] = player_1
      
      # set the score for the first player. As we are using a dict, we do not need to start with 0. We can even use strings
      players["pl_1"]["score"] = 100
      # get the score for the first player
      print(players["pl_1"]["score"])  # prints "100"
      

      Still, what you should be looking into are classes. Classes can have attributes and methods. As a tutorial would take too long, here is how you would use them:

      
      class Player(object):
          """This class represents a player"""
          def __init__(self, name):
              self.name = name
              self.score = 0
      
          def increment_score(self):
              """Increment the score by 1. This is an example for a method."""
              self.score += 1
      
      players = []
      # create a player
      player = Player("bennr01")
      players.append(player)
      # get the name
      print(players[0].name)  # prints "bennr01"
      # increase score
      players[0].increment_score()
      # print score
      print(players[0].score)  # prints "1"
      

      You can of course combine this with lists and dicts as needed.

      posted in Pythonista
      bennr01
      bennr01
    • RE: Download and unzip files

      @macfox2 If you want to use StaSh, download the file using 'wget url_here' and unzip it using 'unzip file_here'.

      posted in Pythonista
      bennr01
      bennr01
    • RE: Numbers behave like strings in iPhone

      @JonB said:

      For doing 1:1 character replacements, maketrans plus translate makes for clean code. You list all the characters you are replacing in one string, all the replacements in the second, and all the characters to delete in the third argument to maketrans.

      Damn, I never knew about this. Now I can finally replace my for c in (...): s = s.replace(c, "") loops. My code may finally look acceptable.

      posted in Pythonista
      bennr01
      bennr01
    • RE: Numbers behave like strings in iPhone

      @ccc said:

      Does anyone use Python 2 anymore?

      Please don't judge those of us who prefer the version of python closer to perfection.

      posted in Pythonista
      bennr01
      bennr01
    • RE: pip install gestures, WKWebView, UI animations and more

      After looking into this issue for a bit, it seems like the same bug as in Issue #364. This should have been fixed 12 months ago, just a month after the latest version bump for master. So it is possible that you have a version installed before that version bump.

      So, since it seems like the master branch became a bit outdated,I just merged 152 commits from dev into master. This should include the fix as well as a version bump, so could you please try another selfupdate?

      posted in Pythonista
      bennr01
      bennr01
    • RE: pip install gestures, WKWebView, UI animations and more

      would appreciate any hints on how to debug this?

      In general, stashconf py_traceback 1, stashconf py_pdb 1 and pip --verbose install pythonista-gestures.

      I just tried and could not replicate the error (it installs successfully).

      Error matches a stash issue.

      I think that one is a different issue. StaSh pip has two installers: one for source install (via setup.py) and one for wheels (.whl). The linked issue was regarding the source install, while this issue is with wheel installations. Also, I think we already fixed the linked issue, but I am not sure...

      posted in Pythonista
      bennr01
      bennr01
    • RE: Install with stash in site-packages instead of site-packages-3

      pip -6 install <package> should work.

      posted in Pythonista
      bennr01
      bennr01
    • RE: Function for recognize quantity of unique combinations

      @lyubomyr83 Something like this?

      # -*- coding: utf-8 -*-
      """
      Test solution for https://forum.omz-software.com/topic/6159/function-for-recognize-quantity-of-unique-combinations
      """
      import operator
      
      
      OPERATORS = {
          "+": operator.add,
          "-": operator.sub,
          "*": operator.mul,
          "×": operator.mul,
      }
      
      
      def eval_eq(a, op, b):
          return OPERATORS[op](a, b)
      
      
      def uniques_col(operators, max):
          if len(operators) == 0:
              # we could also just return (max - 1)
              raise ValueError("No operators given!")
          elif len(operators) > 1:
              # the code in the question makes it look like we should add
              # the number of individual operator combinations if multiple
              # operators are given.
              n = 0
              for op in operators:
                  n += uniques_col(op, max)
              return n
          else:
              combinations = []
              for a in range(max, 0, -1):
              # for a in range(1, max + 1):
                  for b in range(max, 0, -1):
                  # for b in range(1, max + 1):
                      res = eval_eq(a, operators, b)
                      if res > max:
                          # should this be result >= max?
                          continue
                      if res < 0:
                          # result cant be under 0
                          continue
                      comb = (a, operators, b)
                      print(comb)
                      if comb not in combinations:
                          combinations.append(comb)
              return len(combinations)
      
      
      if __name__ == "__main__":
          testdata = [
              # format: operators, max, expected
              ("-", 2, 3),
              ("+", 2, 1),
              ("+-", 2, 4),
              ("+-", 3, 9),
              ("+-*", 3, None),
          ]
          for ops, m, exp in testdata:
              n = uniques_col(ops, m)
              print("uniques_col({m}, '{o}') -> {r}; expected {e}".format(m=m, o=ops, r=n, e=exp))
      

      This produced this output:

      (2, '-', 2)
      (2, '-', 1)
      (1, '-', 1)
      uniques_col(2, '-') -> 3; expected 3
      (1, '+', 1)
      uniques_col(2, '+') -> 1; expected 1
      (1, '+', 1)
      (2, '-', 2)
      (2, '-', 1)
      (1, '-', 1)
      uniques_col(2, '+-') -> 4; expected 4
      (2, '+', 1)
      (1, '+', 2)
      (1, '+', 1)
      (3, '-', 3)
      (3, '-', 2)
      (3, '-', 1)
      (2, '-', 2)
      (2, '-', 1)
      (1, '-', 1)
      uniques_col(3, '+-') -> 9; expected 9
      (2, '+', 1)
      (1, '+', 2)
      (1, '+', 1)
      (3, '-', 3)
      (3, '-', 2)
      (3, '-', 1)
      (2, '-', 2)
      (2, '-', 1)
      (1, '-', 1)
      (3, '*', 1)
      (2, '*', 1)
      (1, '*', 3)
      (1, '*', 2)
      (1, '*', 1)
      uniques_col(3, '+-*') -> 14; expected None
      
      

      Your question is kind of hard to understand, so I am not sure this solution is correct...

      posted in Pythonista
      bennr01
      bennr01
    • RE: No update?

      @Guest said:

      1. And even if omz push Pythonista to App Store this time, how about the next version? We still have to wait for 2 years? After 2 years, I think Python 4.0 will be released, while we are still using Python 3.6.1. Guys, I really don't understand why are you so optimistic about all these things. Yeah, of course we can use it now and of course you can still use Windows XP and Python 2, just don't try to force all of the users to keep waiting Pythonista 3.3.

      (long text, tldr below)

      The reason I am optimistic about this is simple: I was never disappointed by Pythonista. When I first bought the original pythonista, I did not expect any updates at all. It was (and still is) working nicely and at that point already had way more features than the app I used previously. So when after a few month pythonista received an update, I was positively surprised.I do not remember what exactly the first update I experienced was, but since then we have gotten the ui, bluetooth and objc modules, none of which I expected to receive.

      I believe that the displeasedness some users experience regarding these updates is a general change in mentallity that occured over the years. Products used to be finished, as in *if this app is working and has all promised features, there wont be an update. This is something that I observe increasingly frequently, especially with games. A few years ago, someone asked in the steam discussions "Is this game dead?". The response was quite fitting: No, it is finished. That used to be a thing.. While I am now steering off-topic, in the time before steam, updates were extremely rare. You had your cd/dvd and could install the game. Sometimes the developer published patches, but even these were few (most of the time 2 at most) in numbers. IMO, it is likely that the easy online update distribution let developers publish less polished and sometime incomplete products. Since fixes were needed, more updates were published. I believe this increased frequency in updates let to changed user expectations. Compared to this, updates simply used to be less needed.

      Since I do not expect updates, every update is a posive developement (I get free content). No update is no negative developement (It still works and I still have the complete product I bought).

      TL;DR: It is likely due to a changed mindset over time. I bought Pythonista as what I expected to be a complete product (which it was) and all updates are a positive developement.

      1. We already waited for 2 years, and you just keep waiting and begging omz to update? Did he show up? He just said, oh, I'm coming.And you just wait like a dog waiting for food. But what did he do? From early 2019 to the end of 2019.

      As I wrote in some other threads before, pythonista's update cycles always used to be long. While this one is extraordinary long compared to the previous ones, it matters little. While some of the frequently requested features would be really nice, I can work perfectly fine with the current version of pythonista.

      Also, while I understand some users may be upset about the appearant lack of developement, it simply does not matter for me. So what if there is no update? I bought a complete product and all updates are just a bonus. There is no requirement for omz to create any non-bugfix updates, and complaining about him taking too long to give us free stuff is just chosing-beggar style (please note that this is not aimed at you, I just want to explain my mindset here).

      1. Maybe you think it is normal for an application like this, but not for me and my friends.

      This is it. It used to be normal. I personally believe that this is still what should be normal, but the (as written above) increasingly distribution of incomplete/unpolished products lead to a change in what is considered normal.

      1. And don't tell me about Pyto. Imaging that you installed Python 3.6.1 2 years ago and python.org didn't release any updates about python any more, and after waiting for 2 years, you are told that python.org will close in 2 days. What would you think? Just smile and then try other tools?

      I am also super annoyed about the pyto spam, especially since I believe it to be inappropiate to mention it often in this forum. It costs money to host these forums and posting about pyto here is literally advertising competition.

      That being said, I think most users mentioning pyto are just trying to be helpful. Some features have very little chance of being added to pythonista (like pandas), so mentioning pyto in this context is just trying to be constructive.

      (Off-topic: python.org closing down would not cause any problems. Everything on there is likely available on hundreds of other websites. Its so important that we have enough redundancy for all content on there. Also, I personally see the newer versions of python not very attractive. Many of the new features seem unpythonic and straight up ugly, like PEP572 and some other stuff).

      1. I don't know why are you so optimistic. Maybe you are using WIndows XP, iOS 5.0 and Python2?

      Yes, I am using python 2, though I am migrating to 3 slowly. That being said, I believe this to be a both an unfair and a wrong comparsion. Upgrading from Windows XP costs money, pythonistas updates are free. Just imagine the outcry if every pythonista update costs as much as the normal app (This actually did happen once, when upgrading to pythonista3, but this had so many new features that it was basically a new app. There were also lots of rabats for existing users. All other updates, however, were free).

      After writing this, I now feel old...

      posted in Pythonista
      bennr01
      bennr01

    Latest posts made by bennr01

    • RE: Numbers behave like strings in iPhone

      @JonB said:

      For doing 1:1 character replacements, maketrans plus translate makes for clean code. You list all the characters you are replacing in one string, all the replacements in the second, and all the characters to delete in the third argument to maketrans.

      Damn, I never knew about this. Now I can finally replace my for c in (...): s = s.replace(c, "") loops. My code may finally look acceptable.

      posted in Pythonista
      bennr01
      bennr01
    • RE: Numbers behave like strings in iPhone

      @ccc said:

      Does anyone use Python 2 anymore?

      Please don't judge those of us who prefer the version of python closer to perfection.

      posted in Pythonista
      bennr01
      bennr01
    • RE: Numbers behave like strings in iPhone

      @talns100 If I understand your problem correctly, you call input("Number: ") and get a string value as a return value although you had expected a string.

      This is a python2 vs python3 issue. In python2, raw_input() returned a string while ’input()evaluated the input as a python object. In py3,input()is equivalent to python2'sraw_input()`.

      To fix this, you could:

      • run the script as py2 instead (not recommended)
      • wrap the input() in a int() (int(input("Number: ")))
      • import ast and use ast.literal_eval(input("Number: ")).

      The last variant will allow inputing any value while preventing python code execution.

      posted in Pythonista
      bennr01
      bennr01
    • RE: Anyone able to direct me to pickle in Pythonista resources?

      Pickling refers to using the pickle module for persisting data. You don't need to implement it yourself, it's included in a module by default.

      First, you can access the documentation by swiping from right to left to open the console. There you'll find a button labeld ?. Press it to open the documentation. The documentation contains a lot of explanations, how-tos and references of modules. You'll need to search for pickle, then you'll get a guide on how to use it.

      If you don't want to look it up:

      import pickle  # load the pickle module
      
      my_data = ...  # whatever you want to save
      s = pickle.dumps()  # s is now a string from which you can rebuild my_data
      with open("data.bin", "wb") as fout:  # open file 'data.bin' for binary writing
          fout.write(s)  # write string s
      # let's load it
      with open("data.bin", "rb") as fin:  # open file 'data.bin' for binary reading
          loaded_s = fin.read()  # read string from file
      loaded = pickle.loads(loaded_s)  # unpickle the string, returning a copy of my_data
      

      The above code stores some data and reloads it. You could also change the code to use pickle.dump() instead of pickle.dumps(), which is better when working with large data sets, but I think this explains it better.

      However, I don't think pickle is the go-to solution. I don't know what exactly you are attempting to save, but generally pickle should be avoided. Pickle is python specific and very flexible, but also insecure. If an attacker can modify a file containing a pickle dump, arbitrary code execution becomes possible. You should instead think about using the json module, which can't store custom classes but is still one of the most common data formats, using files directly (requires a bit more work) or using a database like anydbm or sqlite3.

      posted in Pythonista
      bennr01
      bennr01
    • RE: yaml.dump() appending to file rather than overwriting

      @Sparky01

      I haven't tested it, but I think the problem is that you aren't using file offsets correctly. Basically, right now you are reading the file, then continue writing from the last position you have read.

      The best solution would be to seperate reading and writing the files.

      import yaml
      
      class MyClass():
        def __init__(self):
          with open('config.yml', 'r') as fin:
              self.config = yaml.load(fin)
          self.config['hi'] = 1
          self.config['hello'] = 1
          with open('config.yml', 'w') as fout:
              yaml.dump(
                self.config,
                fout,
                default_flow_style=False
              ) 
          print(self.config)
          # returns {'hi': 1, 'hello': 1} 
          
      MyClass()
      

      Alternatively, call self.configFile.seek(0) after reading. This sets the read/write offset to the beginning of the file. Be warned that this only works if the new file content has at least the same length as the original file content, otherwise trailing bytes will remain!

      posted in Pythonista
      bennr01
      bennr01
    • RE: Problem with arrays

      I think you may be confusing a few different datatypes here, so I'll try to explain some approaches for your problem.

      First of, Python does not really have something like arrays. Usually, when one wants to use something akin to an array in Python, one uses a list instead. The main difference between a list and an array is that usually arrays are fixed size and often fixed type also while Python lists can have any required size and mixed types of elements. However, you wrote "same variables", so lists may not be what you are looking for. Still, heres a short tutorial for lists:

      # create a list
      l = []  # alternatively, use "l = list()"
      # add an element to a list
      l.append(1)
      # get the size of the list
      print(len(l))
      # get the first element (index is 0 as indexes start with 0)
      print(l[0])  # prints "1"
      # remove the first element
      del l[0]  # alternatively, use "l.pop(0)", which also returns the element
      

      Now let's take a look at how lists could be used for your problem:

      # number of players
      num_players = 4
      # number of variables each player has
      num_vars = 10
      
      # initiate a two-dimensional list with all players or variables
      # a two-dimensional list is a list of lists. In this case, all "variables" will be initialized as None.
      players = [[None] * num_vars] * num_players
      
      # set 2nd variable for player 3 to 12. Remember that indexes start at 0
      players[2][1] = 12
      # get 2nd variable for player 3
      print(players[2][1])  # prints "12"
      
      # ============= alternative =============
      # using math, we can do this a bit more efficient using 1-dimensional lists
      
      # number of players
      num_players = 4
      # number of variables each player has
      num_vars = 10
      
      # initiate a one-dimensional list with all players or variables
      players = [None] * num_vars * num_players
      # now we can access a variable by using index = (player_index * num_vars + var_index)
      
      # set 2nd variable for player 3 to 12. Remember that indexes start at 0
      players[2 * num_vars + 1] = 12
      # get 2nd variable for player 3
      print(2 * num_vars + 1)  # prints "12"
      
      

      However, as I said before, lists aren't a good solution for this. Let's take a look at another datastructure, the dict. A dict is a mapping of key-value pairs. Think of it like a dictionary, where each word you look up (in this case the key) has some associated words (the value). Here is an example of a dict usage:

      d = {}  # alternatively, use "d = dict()"
      # set a key to a value
      d["name"] = "bennr01"
      # get the number of defined keys in a dict
      print(len(d))  # prints "1"
      # get a value for a key
      print(d["name]")  # prints "bennr01"
      # remove a key-value pair
      del d["name"]
      

      Using dicts, you can refer to the variables using names. Here's how to use it for your problem:

      players = []
      # create a player here
      player_1 = dict(name="Player 1", score=0)
      players.apend(player_1)
      
      # set the score for the first player (again, index 0)
      players[0]["score"] = 100
      # get the score for the first player
      print(players[0]["score"])  # prints "100"
      
      # ============= alternative ==============
      # instead of using a list for all players, you could also use a dict
      
      players = {}  # <-- see the difference
      # create a player here
      player_1 = dict(name="Player 1", score=0)
      players[1] = player_1
      
      # set the score for the first player. As we are using a dict, we do not need to start with 0. We can even use strings
      players["pl_1"]["score"] = 100
      # get the score for the first player
      print(players["pl_1"]["score"])  # prints "100"
      

      Still, what you should be looking into are classes. Classes can have attributes and methods. As a tutorial would take too long, here is how you would use them:

      
      class Player(object):
          """This class represents a player"""
          def __init__(self, name):
              self.name = name
              self.score = 0
      
          def increment_score(self):
              """Increment the score by 1. This is an example for a method."""
              self.score += 1
      
      players = []
      # create a player
      player = Player("bennr01")
      players.append(player)
      # get the name
      print(players[0].name)  # prints "bennr01"
      # increase score
      players[0].increment_score()
      # print score
      print(players[0].score)  # prints "1"
      

      You can of course combine this with lists and dicts as needed.

      posted in Pythonista
      bennr01
      bennr01
    • RE: Instance attribute as the value of another class instant attribute

      First of, you can move your *_patient_list into the Patient class to reduce global variables.

      class Patient(object):
          master_patient_list = []  # this should be shared among all Patients
          def __init__(self, ...):
              ...
              self.master_patient_class.append(self)
      

      Second, I think you want something like this for example:

      class Physician(Employee):
          illness2doctor = {}  # shared dict mapping illness -> doctor for illness
      
          def __init__(self, name):
               # just as example
               self.name = name
      
          @classmethod
          def register_doctor(cls, doctor, illness):
              assert not illness in cls.illness2doctor  # prevent overwrite
              cls.illness2doctor[illness] = doctor
      
          @classmethod
          def get_doctor_for(cls, patient):
              illness = patient.illness
              if illness not in cls.illness2doctor:
                  raise KeyError("No doctor for illness")
              return cls.illness2doctor[illness]
      
      
      # --- usage ---
      # create a new physician
      alice = Physician(name="Alice")
      # alice can treat "Broken Leg"
      Physician.register_doctor(alice, "Broken Leg")
      
      # now we can get the doctor for patient1
      print(Physician.get_doctor_for(patient1).name)
      # -> should print "Alice"
      
      posted in Pythonista
      bennr01
      bennr01
    • RE: How do you split/slice list of strings

      [s[i:i+2] for s in a for i in range(0, len(s), 2)]

      Replace 2 with chunk length.

      posted in Pythonista
      bennr01
      bennr01
    • RE: Stash, PIP and versions

      @trey

      You can also use six by running pip -6 install…, but I’ve found modules installed into Python 3 that way from Python 2 StaSh to be unreliable. You can import them, but sometimes they don’t work, and pip list doesn’t show them in either StaSh 2 or 3. So I just wouldn’t do it.

      -6 does not use six, it just tells pip to use the shared site-packages directory so that you can install a package for both interpreters. Some packages may distribute different files depending on the installing python version which may cause the problems. Also, since pip stores information about the installed packages within site-packages, you must specify -6 for pip show too (pip -6 show).

      posted in Pythonista
      bennr01
      bennr01
    • RE: Stash, PIP and versions

      StaSh runs on both py2 and py3, though not all commands support py3. pip uses the python interpreter StaSh was launched with and installs the package into the version specific site-packages directory. You can use the -6 option to tell pio that it should install a package into the shared site-packages directory.

      You can force StaSh to use a specific python version by long-pressing the Run-Button and choosing the "run with python X" option.

      posted in Pythonista
      bennr01
      bennr01