StaSh - Shell Like an Expert in Pythonista
This error is tricky. It is due to the
module_namevariable being unicode type instead of an plain ASCII str. So once you add
module_name = str(module_name)
into the code, everything works.
This error is probably due to the fact that Python 2.x and its libraries are not fully unicode compliant. In fact, if you type
runpy.run_module(u'SimpleHTTPServer', run_name='__main__')into a PC version python interpreter, it reports exactly the same error.
When the script runs by itself,
sys.argvis set to plain strings. But it is set to the same strings of unicode version when executed by StaSh. I am not entirely clear about the reason. Anyway, the fix is easy. I'll also see if it is worthwhile to always convert all arguments to
strbefore calling an external script.
unicodestrings exclusively. Since the command input field is just a regular text field, it also returns its contents as
unicode, and since there's no reason for Python to coerce down to
strit doesn't. Also instead of a plain
str()conversion it would be better to use the
unicodeobjects, that way the string is guaranteed to be properly encoded as UTF-8.
@dgelessus Thanks for the explaination. That makes sense.
I am still thinking about whether it is really necessary to always encode unicode arguments to str before executing a command.
@ywangd, it isn't really necessary, because you'll almost never need to pass non-ASCII characters to a command. But when you do try, you'll very likely run into problems. I'm not sure what exactly happens when you do
encodeis also guaranteed to work in future Python versions. Python 3 (if/when Pythonista supports it) is much more strict when it comes to byte data and unicode text.
I checked, and Python 2.7 on my Raspberry Pi encodes runtime args as UTF-8
strobjects. It is possible that the encoding is OS-dependent, but UTF-8 is usually a safe choice. Python 3 of course uses proper Unicode
unicodestrings as UTF-8 anyway.
encodestill is safer ;)
@ywand Thank you very much, can't believe I missed that. Spend hours looking for that problem.
It seems that '&' is not passed by the input. I was using that to flag its own thread. I added it to _word_chars and it now passes &. Is it held for a reason?
@dgelessus Thanks for the explanation
ihf last edited by
This is a very nice piece of work and quite useful. I use a BT keyboard on my iPad and I am wondering if there is any way that the special keys (e.g., Tab, Up, Ctrl-C) could be made to work from the keyboard?
I just submited a pull request.
- man.py - lists programs in /bin and displays the docstring.
- edit.py - opens a file in the pythonista editor
- python.py - allows execution of .py files and modules. Basicly allows the -m flag with python. You can run SimpleHTTPServer, pylint, unittests etc.
- added '&' to _word_chars in stash.py - I needed this to allow running a python script in it's own thread emulating bash &.
wradcliffe last edited by
@briarfox - what are the references to Shash and "drag and drop" talking about in your prior posts? Sounds like some other shell where you drag and drop scripts into a window or something. Did you mean StaSh and dnd means something other then what I think it does?
@wradcliffe Sorry I was being a bit dyslexic. By Dnd I was referring to adding scripts to StaSh/bin. As in it's easy to extend. Probably not the correct use of the term.
Thanks a lot for your pull request. I made some changes to
python.pyafter the merge. In short, the script now takes a flag -b to indicate running as background thread instead of &. I used
argparsemodule for argument processing. It even provides free help message if you type
I personally think the & character shall be handled by the shell instead of the script gets called. Because otherwise every script has to check for & to decide if it runs in background. This task should be handled by shell/OS instead of individual script.
My current preference is to not allow background jobs (commands end with a &). This is mainly because it does not seem possible to end a thread gracefully from another (main) thread.
Thread._Thread__stop()can be used and often works, but it does not perform any housekeeping tasks (e.g.
try: ... finally:block is not honoured). It just ends the thread abruptly and leaves a somewhat messy state, for example, the socket port will not be released if a http server thread is ended this way. Of course, an external can still spawn threads on its own and StaSh has no control of it since it is not really an OS.
The shell in fact should have reported parsing error when sees a &. It was actually a bug that causes the shell ignore the character instead of erring out (it is now fixed). This character is Not part of
_word_charwhich is consistent as a real shell. It is a punctuator, similar to
;, to separate commands. I am still debating whether background job shall be directly allowed by StaSh. But as for now, I prefer to leave it out.
I hope these changes are OK with you. Thanks!
Sorry but I never had a chance to use an external keyboard. So I won't be of much help on this. Hopefully someone else would come up with a solution. Otherwise it'll have to wait till I can get a keyboard ...
@ihf re. keyboard, that is possible in a very limited way. See KeyboardControl.py, it uses a delegate and a specifically filled text field to deduce the user's keystrokes. It has issues with some of the more unusual combinations and I doubt it would be possible to integrate it in StaSh. The only thing I could think of would be to detect when the cursor jumps to the beginning of the text field (that is what the up arrow does when there's no line above the current one) and then show the previous history item in the text field. Tab might also work, because there is no other way (except copy and paste) to insert a tab character or multiple spaces at once.
Just submitted a pull request with:
- ssh-keygen - Generates rsa/dsa keys for scp and ssh
- scp - Secure copy. Gets and Put files/dirs onto or from a remote.
I'm working on an ssh script and would like some feedback. It currently only works for linux. You should use ssh-keygen to create a key pair. Add the .pub to your known_hosts on your server. You can also use the user password if you do not want to use a rsa/dsa key.
I've used this modules with scp to make all my commits and pushes to the stash repo. It's nice to have full git access from Pythonista.
ssh client for stash. ssh looks for a valid key generated buy ssh-keygen in .ssh.
You can open an intereactive shell by not passing a command. If a command is passed,
the single command is ran with output then ssh exits.
(exit) command will exit shell.
usage: ssh [-h] [--password PASSWORD] [-p PORT] host [command]
host host ex. firstname.lastname@example.org
command Command to send as a quoted string
-h, --help show this help message and exit
--password PASSWORD Password for rsa/dsa key or password login
-p PORT, --port PORT port for ssh default: 22
mncfre last edited by
It would be nice to have the zip comand on Stash, I only see unzip or tar, but Pythonista don't recognize tar.gz
zipis now added. You can get it via
selfupdatefrom within StaSh. Or if you want to get the latest development version, try
SELFUPDATE_BRANCH=dev selfupdate. You'll need restart StaSh afterwards. Thanks!
mncfre last edited by
@ywangd thanks a lot, this is by far the best shell in Pythonista
whitone last edited by
I noticed that the pip command allows you to list all modules installed using this command and specially allows you to update individual modules! This is very useful! So I cleaned up my environment in Pythonista and now I'm handling everything with StaSh.
I was able to run many libraries in Pythonista without having to change them much, I tried only to override the functions. So now I'm creating StaSh scripts for running CLI program written in Python: in practice the first time they are run if the modules they needs are not installed they install these modules (as the command git) and apply monkey patches.
For those who have just installed Pythonista and want to install StaSh I created a simplified installation creating a shortened url for getstash.py.
To install StaSh just copy the following line in the Pythonista console:
import requests; exec requests.get('http://bit.ly/StaSh').text
Congratulations to all for this fantastic tool!
wradcliffe last edited by
@whitone - Thanks for posting this. I have never used pip and my setup under Pythonista is now littered with many modules that I manually "installed". It is not hard, but I figured that there must be a better way. I also have no idea what monkey patches are about so I need to do some reading.
If you have any cycles it would be very instructional to have one quick tutorial on a useful program you installed and converted and the patches you had to apply to get it working and how you now have this captured and automated using stash - pip, etc.
One last question - are you referring to CLI programs in general or using the PyCLI module: https://pythonhosted.org/pyCLI/ ? This seems like a great way to go for writing scripts and gets people going using logging and a good command line interface.
polymerchm last edited by