0838cdb93c
per changes regarding typer, wuttjamaican etc.
104 lines
3.1 KiB
ReStructuredText
104 lines
3.1 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.
|
|
|
|
(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
|