rattail-manual/docs/base/scripts.rst

97 lines
3 KiB
ReStructuredText

Writing Scripts
===============
There are 2 types of scripts you may need to write: Python and shell.
The reason for writing a script is usually for sake of automating some task,
logic for which is either "not important enough" or perhaps is "too custom" to
warrant adding it to the app proper. For instance app upgrade scripts are
closely tied to the machine/environment on which the app is installed and so
are kept outside of the app proper.
Which isn't to say, by the way, that these scripts shouldn't be tracked via
source control. All scripts needed to manage the app *should* ideally be
committed to a Git repo somewhere; see :doc:`/deploy/index` for more on that.
As a rule, shell scripts are "simpler" but of course are limited to the
commands defined by the app (and underlying shell). Python scripts bring
maximum flexibility but can sometimes be overkill.
Python Scripts
--------------
A "complete" sample Python script is shown below. It may be more complex than
you typically need, but hopefully not too bad; modify as you like.
If you use :doc:`/data/versioning` then it is important to "postpone" most
module imports, until the config has been fully created. (Even if you don't
use versioning it's a good habit, in case you ever change your mind.) This is
why, in the example below, the import from ``rattail.db`` happens within the
main function, instead of at the top of the script.
.. code-block:: python
#!/srv/envs/poser/bin/python3
"""
This script is useful for such and such.
"""
import argparse
from rattail.config import make_config
def do_something(config):
# most imports should not happen until config is made
from rattail.db import Session
# open db connection
model = config.get_model()
session = Session()
# do something...for instance count the departments
print(session.query(model.Department).count())
# must commit session to save any changes
#session.commit()
session.close()
if __name__ == '__main__':
# here we define available command line args
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--config', metavar='PATH',
action='append', dest='config_paths')
# here we determine what args caller specified
args = parser.parse_args()
# okay let's make that config, per command line
config = make_config(args.config_paths)
# if you'd rather skip command line parsing altogether,
# you can instead do something like this:
#config = make_config('/srv/envs/poser/app/quiet.conf')
# and finally let's do something useful
do_something(config)
Let's say you name this script ``foo.py`` and put it in your app dir, so
running it would look like:
.. code-block:: sh
cd /srv/envs/poser
bin/python app/foo.py --help
TODO: It seems like Rattail should have a way of generating a skeleton script
like the above.
Shell Scripts
-------------
TODO