The new release of the pythonanywhere
helper scripts package introduces
new commands covering our files API.
Installation¶
Assuming you’re on the latest system image (and you haven’t changed your
default python
command to run Python below 3.6) you can use the basic pip install pythonanywhere --user
command, which will install our helper
scripts for your default Python version. If you installed the package
previously, add -U
flag to the command.
To use our helper scripts you need to have a valid API token, which you can obtain on your Account page in the API Token tab.
Introducing a new style of invoking commands¶
Our files API wrappers are the first which come only with the new style
command subcommand options
and not as standalone scripts to run as were used
before (e.g. pa_delete_scheduled_task
). All previously released scripts
will work for backwards compatibility, but it’s preferable to use the new
style ones from now on. The main command to use is, as you may expect, pa
.
$ pa --help
Usage: pa [OPTIONS] COMMAND [ARGS]...
This is a new experimental PythonAnywhere cli client.
It was build with typer & click under the hood.
Options:
--install-completion [bash|zsh|fish|powershell|pwsh]
Install completion for the specified shell.
--show-completion [bash|zsh|fish|powershell|pwsh]
Show completion for the specified shell, to
copy it or customize the installation.
--help Show this message and exit.
Commands:
django Makes Django Girls tutorial projects deployment easy
path Perform some operations on files
schedule Manage scheduled tasks
webapp Everything for web apps
To get an overview of the subcommands’ options, run:
$ pa path --help
Usage: pa path [OPTIONS] COMMAND [ARGS]...
Perform some operations on files
Options:
--help Show this message and exit.
Commands:
delete Delete file or directory at PATH.
get Get contents of PATH.
share Create a sharing link to a file at PATH or check its sharing...
tree Show preview of directory contents at PATH in tree-like format
(2...
unshare Disable sharing link for a file at PATH.
upload Upload CONTENTS to file at PATH.
If you’re familiar with the git
command’s interface, ours works in a
similar way.
path
commands overview¶
Let’s assume there’s a PythonAnywhere user called “username” and they have default files plus some newly created ones:
$ mkdir -p ~/foo/bar; touch ~/foo/{baz,quux}
Common options for all commands¶
Running any (sub)command with --help
will print its usage message. By
default all commands will show our API error messages when one is
received. That can be suppressed by adding -q
(--quiet
) flag.
$ pa path get ~/asdf
_______________________________________________________________________
/ \
| GET to fetch contents of https://www.pythonanywhere.com/api/v0/user/use |
| rname/files/path/home/username/asdf failed, got <Response [404]>: No such |
| file or directory: /home/username/asdf |
\ /
-----------------------------------------------------------------------
\
~<:>>>>>>>>>
$ if pa path get ~/asdf -q; then echo exists; else echo does not exist; fi
does not exist
get
– show file contents or list directory¶
Directories¶
Now, when username
runs pa path get ~
they will see contents of their HOME
directory, including default (hidden) files and recently created directory
foo
. The output consists of two columns – first indicates the type (F for
files, D for directories).
$ pa path get ~
/home/username:
F .bash_history
F .bashrc
D .cache
F .gitconfig
D .local
F .profile
F .pythonstartup.py
F .vimrc
D .virtualenvs
F README.txt
D foo
By default, the list is sorted alphabetically. Providing the -r
flag will
reverse the ordering, the -d
flag will filter only by directories and -f
will
show only files (non-directories, to be strict, as in Linux everything is
basically a file).
We can use also a -r
(--raw
) option which will dump the JSON API response to
the output, if parsing it with other CLI utilities (like jq
) is preferred.
This has effect only when you’re accessing directories (because the output
for a file is its contents – see later).
$ pa path get ~/foo --raw
{"bar": {"type": "file", "url": "https://www.pythonanywhere.com/api/v0/user/username/files/path/home/username/foo/bar"}, "baz": {"type": "file", "url": "https://www.pythonanywhere.com/api/v0/user/username/files/path/home/username/foo/baz"}, "quux": {"type": "directory", "url": "https://www.pythonanywhere.com/api/v0/user/username/files/path/home/username/foo/quux"}}
$ pa path get ~/foo -r | jq
{
"bar": {
"type": "file",
"url": "https://www.pythonanywhere.com/api/v0/user/username/files/path/home/username/foo/bar"
},
"baz": {
"type": "file",
"url": "https://www.pythonanywhere.com/api/v0/user/username/files/path/home/username/foo/baz"
},
"quux": {
"type": "directory",
"url": "https://www.pythonanywhere.com/api/v0/user/username/files/path/home/username/foo/quux"
}
}
Files¶
When the argument passed to pa path get
is a file (non-directory), its contents
will be displayed:
$ pa path get ~/README.txt
# vim: set ft=rst:
See https://help.pythonanywhere.com/ (or click the "Help" link at the top
right) for help on how to use PythonAnywhere, including tips on copying and
pasting from consoles, and writing your own web applications.
tree
¶
The get
command provides a list of the contents of a given path. To get an
overview of the directory contents in a tree-like structure, we can use the
tree
command.
$ pa path tree ~
/home/username:
.
├── README.txt
└── foo/
├── bar
├── baz
└── quux/
This command however is not a full implementation of its Linux counterpart – since path API calls are expensive, we limit the tree levels shown to 2, and no hidden files are listed.
delete
file or directory¶
It does what it means – mind that it’s a dangerous command, since it will
delete contents recursively and permanently! Let’s use our newly created
directory foo
:
$ pa path delete ~/foo
< /home/username/foo deleted! >
\
~<:>>>>>>>>>
$ ls ~/foo
ls: cannot access '/home/username/foo': No such file or directory
upload
contents of a file¶
We can upload the contents of a file to given path, or stream the contents directly to the standard input. If the path contains non-existent directories, they will be created. Mind that when the path points to an existing file, it will be overwritten!
$ echo "This is my new file" > file.txt
$ pa path upload --contents file.txt ~/somewhere/something
< Content successfully uploaded to /home/username/somewhere/something! >
\
~<:>>>>>>>>>
10:12 ~ $ cat ~/somewhere/something
This is my new file
If we want to stream the contents directly from the command line, the syntax is a bit tricky:
$ pa path upload ~/somewhere/something -c - <<< "New contents stream"
< /home/pafkpa/somewhere/something successfully updated! >
\
~<:>>>>>>>>>
10:18 ~ $ cat ~/somewhere/something
New contents stream
Using echo "Stream" | pa path upload ~/where -c -
is also valid.
That, obviously, would probably not have much sense on PythonAnywhere, but
we could imagine some useful scenarios while using pa
commands from local
machine (see: Running scripts on your local machine).
Sharing and unsharing files (share
and unshare
commands)¶
PythonAnywhere provides a feature to share your code with people online. That currently works only for files (and the path to the file must not be a symbolic link).
$ echo 'print("Hello, world!")' > hello.py
$ pa path share --check ~/hello.py
< /home/username/hello.py has not been shared >
\
~<:>>>>>>>>>
hello.py
is not shared yet – we can easily change that:
$ pa path share ~/hello.py
_______________________________________________________________________
/ \
| /home/username/hello.py successfully shared at https://www.pythonanywher |
| e.com/user/username/shares/e248a1adae4b4554b229815874f6ef8f/ |
\ /
-----------------------------------------------------------------------
\
~<:>>>>>>>>>
That SnakeSay dialog is quite effective, but we may prefer to get a raw link to the shared file instead:
$ pa path share --porcelain ~/hello.py
https://www.pythonanywhere.com/user/username/shares/07a987add2b24fcb982144006197c38b/
To unshare that file, simply run:
$ pa path unshare ~/hello.py
< /home/username/hello.py is no longer shared! >
\
~<:>>>>>>>>>
Running scripts on your local machine¶
While some of our helper scripts were meant to be run explicitly on
PythonAnywhere (see: pa django --help
), others can be run from outside of
your PythonAnywhere environment. With the file API wrappers it may make even
more sense to run some commands from your local machine than from
PythonAnywhere, where you can easily perform file operations without doing
extra calls to the API.
In order to run pa
commands locally, apart from installing the
pythonanywhere
package, you need to provide two extra bits of information
to the scripts:
- the API token
- your PythonAnywhere username (if it’s different than your machine’s user log name)
Using our example (of a user called “username”), that can be achieved by
using LOGNAME
and API_TOKEN
environment variables, like this (the example is
for a Linux environment):
$ export LOGNAME=username
$ export API_TOKEN='thisismytokenOneone1111!'
You can go even a step further and have a shim script for our API wrappers, which could look like this:
#!/bin/sh
export LOGNAME=username
export API_TOKEN='thisismytokenOneone1111!'
# Below is the path to `pa` command -- it can be located elsewhere,
# depending on how you installed our pythonanywhere package
/home/mylocaluser/.virtualenvs/helperscripts/bin/pa "$@"
Then you’d run the script like this (assuming that the script is called
“my_pa
” and is located in the current working directory):
$ ./my_pa path get "/home/username/README.txt"