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. (See also :doc:`wuttjamaican:narr/cli/scripts` for more simple examples.) 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.auth import administrator_role app = config.get_app() model = app.model # open db connection session = app.make_session() # not doing anything useful here, just an example admin = administrator_role(session) print(admin) # do something else...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/python3 app/foo.py --help Shell Scripts ------------- TODO