Forum Archive

StaSh for Pythonista 2 and 3

ywangd

StaSh v0.5.0 is formally ready for Pythonista 2.0 and it is recommended to upgrade whether you are on v0.4.x or beta 0.5.0.

Please do NOT try to upgrade using selfupdate. Due to changes to installation structure , please run following one line command to get the latest version (it may also help to restart Pythonista before the installation).

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

StaSh is now installed as a Python module in site-packages. To start the shell, please run launch_stash.py found in the home directory. Future upgrades can still be retrieved normally via selfupdate.

Thanks!

e.warashina

Hi,

I'm new to Pythonista and got your StaSh just now.

It's amazing tool for me. Thank you.

By the way, I got stuck in the git.
I got a error like:

$ git status
stash: <type 'exceptions.Exception'> Current directory isn't a git repository

after I run:

$ git init
initialize a new Git repository

git commit aslo got the same error.

Are there any helps or hint?

I think that I'm running StaSh v0.5.0. The git automatically installed by StaSh would came from dulwich.

Thanks.

append:
I'll paste command log when I installed git.
I tried that remove site-package directory and reinstall StaSh, Pythonista on both of iPhone and iPad.

StaSh v0.5.0
[~/Documents]$ ls
Examples Welcome.md bs4test.py launch_stash.py site-packages sttest
[~/Documents]$ cd s
site-packages/  sttest/
[~/Documents]$ cd sttest/
[sttest]$ git init
dulwich was not found.  Will attempt to download.
Need to download dulwich.  OK to download [y/n]?y
Opening: https://github.com/jsbain/dulwich/archive/ForStaSH_0.12.2.zip
Save as: /private/var/mobile/Containers/Data/Application/BC3334F5-A7B9-4503-A5C0-A3E8D7A8A2DE/tmp/dulwich.zip  (400490 bytes)
      8192  [2.05%]
     16384  [4.09%]
     24576  [6.14%]
     32768  [8.18%]
     40960  [10.23%]
     49152  [12.27%]
     57344  [14.32%]
     65536  [16.36%]
     73728  [18.41%]
     81920  [20.45%]
     90112  [22.50%]
     98304  [24.55%]
    106496  [26.59%]
    114688  [28.64%]
    122880  [30.68%]
    131072  [32.73%]
    139264  [34.77%]
    147456  [36.82%]
    155648  [38.86%]
    163840  [40.91%]
    172032  [42.96%]
    180224  [45.00%]
    188416  [47.05%]
    196608  [49.09%]
    204800  [51.14%]
    212992  [53.18%]
    221184  [55.23%]
    229376  [57.27%]
    237568  [59.32%]
    245760  [61.36%]
    253952  [63.41%]
    262144  [65.46%]
    270336  [67.50%]
    278528  [69.55%]
    286720  [71.59%]
    294912  [73.64%]
    303104  [75.68%]
    311296  [77.73%]
    319488  [79.77%]
    327680  [81.82%]
    335872  [83.87%]
    344064  [85.91%]
    352256  [87.96%]
    360448  [90.00%]
    368640  [92.05%]
    376832  [94.09%]
    385024  [96.14%]
    393216  [98.18%]
    400490  [100.00%]
/private/var/mobile/Containers/Shared/AppGroup/C2262ABC-29FF-4015-8027-57D05D396DD5/Documents/site-packages/stash/lib/dulwich.old: does not exist
mv: /private/var/mobile/Containers/Shared/AppGroup/C2262ABC-29FF-4015-8027-57D05D396DD5/Documents/site-packages/stash/lib/dulwich: no such file or directory
/private/var/mobile/Containers/Shared/AppGroup/C2262ABC-29FF-4015-8027-57D05D396DD5/Documents/site-packages/stash/lib/dulwich.old: does not exist
Still could not import dulwich.
            Perhaps your network connection was unavailable.
            You might also try deleting any existing dulwich versions in site-packages or elsewhere, then restarting pythonista.
Opening: https://github.com/jsbain/gittle/archive/master.zip
Save as: /private/var/mobile/Containers/Data/Application/BC3334F5-A7B9-4503-A5C0-A3E8D7A8A2DE/tmp/gittle.zip  (28334 bytes)
      8192  [28.91%]
     16384  [57.82%]
     24576  [86.74%]
     28334  [100.00%]
Opening: https://github.com/FriendCode/funky/archive/master.zip
Save as: /private/var/mobile/Containers/Data/Application/BC3334F5-A7B9-4503-A5C0-A3E8D7A8A2DE/tmp/funky.zip  (8474 bytes)
      8192  [96.67%]
      8474  [100.00%]
initialize a new Git repository
[sttest]$
ccc

See https://forum.omz-software.com/topic/2515/using-git-inside-stash

ywangd

@e-warashina I am glad that you find StaSh useful.

@JonB is the author of the git tool. I am sure he will be able to share more information on this issue. But here is my take on it:

  • git init requires a path parameter. For an example, if you need initialise the current working directory, you need to run git init .

  • The directory is now initialised. If you type ls -a , you'll be able to see a new .git folder created.

  • Now if you type git status, an error will be generated reporting 'HEAD' is not found. This is expected as there is currently no commit in the repo. I do think the error message can be formatted in a more user-friendly way (a possible future improvement).

  • You can now add a file to the repo via git add SOME_FILE and them commit by git commit.

  • Now if you run git status again, it will correctly show the status.

Hope this helps.

e.warashina

@ccc,
@ywangd Thank you for your advice.

It works very well.
So, I missed any git init's path parameter as you noticed!

After run git init ., everything went like clockwork.

I love this tool so much. And, I'm very impressed your support.
I say thank you again.

ihf

Ran the one liner, restarted Pythonista, ran launch_stash.py. Pythonista crashes (returns to home screen) after 1 sec. Then I tried deleting stash and trying again. It gets as far as "Preparing the folder structure..."

ywangd

@ihf said:

Ran the one liner, restarted Pythonista, ran launch_stash.py. Pythonista crashes (returns to home screen) after 1 sec. Then I tried deleting stash and trying again. It gets as far as "Preparing the folder structure..."

What is your device and iOS version? Is it jailbroken? It worked for me on three different devices:
* iPhone 6+ with iOS 9.2
* iPad Air 2 with iOS 9.2
* iPad mini 1 with iOS 9.1 (32-bit)

I don't quite get why it stuck at the installation script as it performs only pure and simple Python calls.

ihf

@ywangd Ipad3, JB, IOS 8.1.2. I don't understand either, I'm just reporting what I see.

ihf

@ywangd ran the one liner again and it ended this time with Installation completed but when I run launch_stash it still crashes immediately.

ywangd

@ihf said:

@ywangd Ipad3, JB, IOS 8.1.2. I don't understand either, I'm just reporting what I see.

Thanks for the report. It is very likely that the crash is related to JB. Since I don't have a Jailbroken device, I cannot do any further tests. Anyway, I guess with a JB device, you can leverage the real BSD shell and a pretending shell like stash is of little use.

ywangd

@ihf Here are two possible alternatives:

  • Continue to use v0.4.x
  • I plan to make the usage of attributed texts optional (i.e. no font color and style). Maybe this would help JB devices.
JonB

I am using stash on ipad3 ios 8.4.1. I seem to remember a few issues with objc that were fixed with later ios versions, but i forget which.

I will say that we have found an issue related to cursor setting using the new attributed text functions on 32 bit devices. This could be related.

ihf

@ywangd Please let me know if/when there is a version (other than v0.4.x) that I might try. Once one uses Stash with Pythonista it is hard to go back :-)

JonB

the ios8crash branch seems to solve the specific problems i was having. modify getstash.py to list the ios8crash instead of master, then restart pythonista.

ywangd

@ihf said:

@ywangd Please let me know if/when there is a version (other than v0.4.x) that I might try. Once one uses Stash with Pythonista it is hard to go back :-)

@JonB and I worked out two solutions for an iOS8 related crash issue.

You can get them with following one-liner installers.

  1. ios8crash
import urllib2; exec urllib2.urlopen('http://bit.ly/get-stash').read() in {'_br': 'ios8crash'}
  1. iso8crash2
import urllib2; exec urllib2.urlopen('http://bit.ly/get-stash').read() in {'_br': 'ios8crash2'}

Please let me know how they work for you. Thanks!

ihf

@ywangd I only tried the first solution and it worked!. Thank you very much!

ihf

@ywangd Will I be able to use selfupdate in the future or will I then lose the ios8 fix?

dgelessus

@ihf If nothing has changed you should be able to do something like SELFUPDATE_BRANCH=ios8fix selfupdate (this is a single command in one line) to update from a branch that isn't master.

ywangd

@dgelessus I just noticed that the leading environmental variable NO longer works for the new selfupdate.py. It used to work with selfupdate.sh. I'll need to fix it later.

As an alternative, you can still update to a specific branch by just typing selfupdate.py BRANCH

@ihf Great the first fix worked for you. Could you please also give the 2nd fix a try? I currently prefer the 2nd fix as it is much simpler. The fix will stay in the main branch once it is finalised. This means you can simply selfupdate to get any future updates.

ihf

@ywangd Unfortunately, ios8crash2 does not fix the problem (it crashes as before). Ios8crash works fine.

ywangd

@ihf The fix is now merged into the master branch along with some other improvements. You can get the update by running selfupdate. Thanks!

disorientedp

@ywangd On the latest version of StaSh, I get an error message that makes it unusable:

Traceback (most recent call last):
  File "/private/var/mobile/Containers/Shared/AppGroup/9BC2C58D-632D-4A13-9539-7CC3C7AA159A/Documents/launch_stash.py", line 36, in <module>
    reload(stash)
  File "/private/var/mobile/Containers/Shared/AppGroup/9BC2C58D-632D-4A13-9539-7CC3C7AA159A/Documents/site-packages/stash/stash.py", line 34, in <module>
    from system.shcommon import IN_PYTHONISTA, ON_IPAD
ImportError: cannot import name IN_PYTHONISTA
disorientedp

@ywangd Never mind, I stopped getting the error without changing anything

ywangd

@disorientedp said:

@ywangd Never mind, I stopped getting the error without changing anything

It is likely that the old stash related modules were still cached after updating. Restart Pythonista will clear the cache and fix the problem (as indicated by the last message printed by selfupdate).

Olaf

@ywangd, I sent you a pull request for an improved version of edit. Please let me know if you don't receive or if I've erred otherwise in the process; I'm an amateur on GitHub ;-(

ywangd

@Olaf said:

@ywangd, I sent you a pull request for an improved version of edit. Please let me know if you don't receive or if I've erred otherwise in the process; I'm an amateur on GitHub ;-(

It is a good improvement on edit. Thanks for the pull request. It worked out very well.

ywangd

So the porting came along quicker than I expected. The py3 branch can at least start in Pythonista 3.

However many commands still not working, esepcially wget which then affects pip and git. The issue is that I could not figure out how to download a zip file from GitHub using urllib3. I tried following code, but the read method always returns an empty string !!??

import urllib3
http = urllib3.PoolManager()
r = http.request('GET', 'https://github.com/ywangd/stash/archive/master.zip')

# So far so good, but then nothing can be read from the response object
print(r.read())  # this gives an empty string
print(r.read(999)) # empty string as well ...

I tried requests as well with requests.get(ZIP_FILE_URL).raw.read(). It returns empty string as well. I guess this is not a surprise as requests is a wrapper of urllib3.

Any help is appreciated.

Webmaster4o

Try this : http://stackoverflow.com/questions/28118611/python-urllib2-returning-an-empty-string

ywangd

@Webmaster4o Thanks for the help. Unfortunately it didn't solve the issue. Still getting empty strings.

The problem that I am experiencing is with urllib3 not 2. It actually worked fine with urllib2. Since urllib2 is removed from Python 3, urllib3 seems to be the logical alternative. The urllib family just seem to have so many incompatibilities between versions.

Webmaster4o

@ywangd What was your code using requests? That's usually easier to handle ;)

ywangd

@Webmaster4o I used the requests module as follows and try to read a chunk of data at a time.

import requests
r2 = requests.get('https://github.com/ywangd/stash/archive/master.zip')
print(repr(r2.raw.read()))
print(repr(r2.raw.read(999))) 

The read calls return empty strings as well. I noticed the raw property is in fact a urllib3 response object. So above code should behave the same as using urllib3. I do get content if I call r2.text. But this downloads the entire file at once which is not what I am after.

omz

I usually use requests like this to download a file without having to load it in memory completely. Works in Python 2 and 3.

import requests
url = 'https://github.com/ywangd/stash/archive/master.zip'
r = requests.get(url, stream=True)
with open('dest.zip', 'wb') as f:
    for chunk in r.iter_content(1024):
        f.write(chunk)
Webmaster4o

I'm not sure what raw does, but it's empty on my macbook as well. Try text. Here's a comparison:

>>> import requests
>>> r=requests.get('https://github.com/ywangd/stash/archive/master.zip')
>>> r.text[:100]
'PK\x03\x04\n\x00\x00\x00\x00\x00ۀNH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r\x00\t\x00stash-master/UT\x05\x00\x01�\x16�VPK\x03\x04\n\x00\x00\x00\x08\x00ۀNHf��?�\x01\x00\x00\x1e\x03\x00\x00\x17\x00\t\x00stash-master/.gitign'
>>> r.raw.read()[:100]
b''
Webmaster4o

@omz Beat me to it 😄

ywangd

@omz It worked! Thanks for helping out on this noob issue. :)

Now I am reading the source code of iter_content and it calls self.raw.stream(....). But if I try this with urllib3 directly, it still won't work ... anyway, it is not important as only requests is designed for humans ...

omz

@Webmaster4o Aside: When you're dealing with binary data (zip files, images...), you should use r.content instead of r.text

dgelessus

@ywangd FYI, urllib3 is a third-party module from PyPI. urllib and urllib2 are Python standard libraries. In Python 3 everything from the old urllib and urllib2 was reorganized as submodules of urllib. urllib3 and requests are both available on Pythonista 2 and 3.

ccc

Why not just switch to requests for all of this? It works in both Python 2 and 3 and is far easier and more reliable to use than the alternatives. At the last Pycon, the consensus was to move requests into the Standard Library but the maintainer declined because he wants to keep the innovations and bug fixes coming at a faster pace than the Standard Library process would allow.

If you moved to requests, what functionality would still be missing?

ywangd

@dgelessus Thanks for the information. Didn't know that.

BTW, to test the Python 3 port, run following one-liner to get the py3 branch.

import requests as r; exec(r.get('http://j.mp/gsp35').text)
ywangd

@ccc I have now switched to requests following omz's example code. It's indeed much friendly than urllib.

ywangd

@JonB Dulwich supports at least to Python 3.4 But Gittle has no Python 3 support. Any idea how the git tools could be ported to Pythonista 3?

The python-future project has an experimental feature to automatically translate Python 2 modules to Python 3 upon loading. But I am not sure how reliable it is.

The main framework of StaSh is working now. I am in the process to make sure all the commands still work. I have ran git through some 2to3 tools so itself is now mostly Python 3 compatible. But the dependencies could be the tricky part.

Webmaster4o

@ywangd I think I remember there being a python3 fork in the pull requests for gittle, I don't know how complete it is.

JonB

I guess I can start removing gittle dependancies (right after I finish the gh command, which is almost ready)

Much of gittle is superceeded by dulwich porcelain, or workarounds in my own code. I have been itching to rewrite git from scratch for a while anyway. my newfound discovery of docopts will make much of the CLI interface easier, the trickier bit is whether it makes more sense to update dulwich, or git.

Phuket2

Guys, time for a new thread for StaSh Pythonista 3.x?

ywangd

@Phuket2 @JonB I think we should have a separate thread for the git tools. With the main post being some instruction, tips for best practice/workflow to help out many common issues. We can then discuss about porting and other improvements in the new thread.

cappy

@ywangd I've just installed Stash. How do I cd to the Home directory? I'm not familiar with the iPad file system.

"Please run launch_stash.py under the Home directory to start StaSh."

JonB

The best way to run stash, is to click the wrench icon, then edit, then the plus sign. then find the launch_stash file.

Then, you will have a shortcut in the wrench menu that you can run anytime.

ywangd

@cappy The launch_stash.py file is found in the directory when you start Pythonista, i.e. Documents.

From Pythonista's file browser (swipe to right to reveal it if not already visible), select launch_stash.py. This opens the file in the editor, then click the Run button (the right-facing triangle on the top right) to start StaSh.

Once you know where the launch file is, you can create an editor action to access it quickly as @JonB suggested.

Tizzy

I just typed 'git' into stash and got this, looks similar to something posted in here earlier...I'm so confused.

'''

StaSh v0.4.0
[~/Documents]$ git
Opening: https://github.com/transistor1/dulwich/archive/master.zip
Save as: /private/var/mobile/Containers/Data/Application/B381FF20-8B02-43E0-870D-BCC9678441DA/tmp/dulwich.zip
8192
16384
24576
32768
40960
49152
57344
65536
73728
81920
90112
98304
106496
114688
122880
131072
139264
147456
155648
163840
172032
180224
188416
196608
204800
212992
221184
229376
237568
245760
253952
262144
270336
278528
286720
294912
303104
311296
319488
327680
335872
344064
352256
355169
stash: ImportError('No module named dulwich',): (No module named dulwich)
[~/Documents]$

'''

ccc

@Tizzy your stash is v0.4.0 but the current version is v0.6.0.

ywangd

@Tizzy It is recommended to install the latest version of StaSh (0.6.3). Version 0.5 and up is not compatible with 0.4 and lower. So please delete your current 0.4 installation and run the following oneliner to get the latest release:

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

Once installed, restart Pythonista and run launch_stash.py under Documents to start.

Phuket2

@ywangd , sorry I am at a total loss.its really mixed up here. About Pythonista 2/3

I do in Pythonista 3
import requests as r; exec r.get('http://bit.ly/get-stash').text
In Python 3,
I get

import requests as r; exec r.get('http://bit.ly/get-stash').text
File "", line 1
import requests as r; exec r.get('http://bit.ly/get-stash').text
^
SyntaxError: invalid syntax

dgelessus

The line should really be

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

Note the parentheses around the argument to exec. In Python 2 exec was a special statement and did not require parentheses like a normal function. In Python 3 exec was changed to a normal function (just like print) so now you need parentheses to call it. In Python 2 exec can also be used like in Python 3 (see the language reference for the details) so the Python 3 style is what you should use in almost all cases.

Phuket2

@dgelessus , I still get an error

import requests as r; exec(r.get('http://bit.ly/get-stash').text)
Traceback (most recent call last):
File "", line 1, in
File "", line 18
print 'Downloading %s ...' % URL_ZIPFILE
^
SyntaxError: Missing parentheses in call to 'print'

But I can see there is a problem with the print. But it's part of an install, not sure I can do anything about that

dgelessus

Uh @ywangd is there a different download link for the py3 branch?

ccc

https://forum.omz-software.com/topic/2545/stash-for-pythonista-2-and-3/39

Tizzy

@dgelessus @ywangd So it's interesting that Stash runs in its own tab, presumably on its own thread, and closing the tab kills the thread?

How do you implement this in pythonsta for other scripts? (this would solve the only being able to run a single script limitation)

ALSO, I appreciate the confirmation before downloading stuff in this version... in that last one simply typing something would try to download it.

ALSO bug report, sometimes the keyboard goes black except the top row with "tab, ~, "etc...

ywangd

@Phuket2

For Pythonista 3, there is a separate branch and following oneliner installs it (note it uses a different url for the py3 branch):

import requests as r; exec(r.get('http://j.mp/gsp35').text)
ywangd

@Tizzy
StaSh uses threads to run commands users type in the terminal. The thread is killable and when StaSh UI is closing, it kills all the threads it spawned. With current version, you can already run multiple scripts with StaSh at the same time. Here is an example that a http server and client runs together. Details of the killable threads can be found in the shthreads.py file.

in that last one simply typing something would try to download it.

I don't quite understand it. Do you mean that pip and git download their dependancies?

ALSO bug report, sometimes the keyboard goes black except the top row with "tab, ~, "etc...

The extra key row is something I wanted to re-write since 2.0 came out. Just didn't have the time. I'll work on it when time permits.

Phuket2

@ywangd , thank you. Successfully downloaded it

Tizzy

@ywangd yes in regards to the dependencies. in the previous version it wouldn't even prompt you it just started downloading. This one it asks first. Good call.