docs/subsystems/management-commands.md
Zulip has a number of Django management commands that
live under {zerver,zilencer,analytics}/management/commands/.
If you need some Python code to run with a Zulip context (access to
the database, etc.) in a script, it should probably go in a management
command. The key thing distinguishing these from production scripts
(scripts/) and development scripts (tools/) is that management
commands can access the database.
While Zulip takes advantage of built-in Django management commands for things like managing Django migrations, we also have dozens that we've written for a range of purposes:
update_analytics_counts.py,
sync_ldap_user_data, etc.makemessages, compilemessages,
populate_db, fill_memcached_caches, etc.runtornado and process_queue.send_test_email.deactivate_realm, reactivate_realm,
change_user_email (for the case where the user doesn't control the
old email address).send_password_reset_email, export, purge_queue.It's generally pretty easy to template off an existing management
command to write a new one. Some good examples are
change_user_email and deactivate_realm. The Django documentation
is good, but we have a few pieces advice specific to the Zulip
project.
ZulipBaseCommand class in
zerver/lib/management.py; this will add some helpful general
flags, as well as tools for adding and parsing --realm and
--user flags, so you don't need to write the tedious code of
looking those objects up. This is especially important for users,
since the library handles the issues around looking up users by
email well (if there's a unique user with that email, just modify it
without requiring the user to specify the realm as well, but if
there's a collision, throw a nice error).zerver/lib/ that already does what you need. For most actions,
you can just call a do_change_foo type function from
zerver/actions/ to do all the work; this is usually far
better than manipulating the database directly, since the library
functions used by the UI are maintained to correctly live-update the
UI if needed.Management commands are essentially independent Python scripts with access to the Zulip server's database and libraries; so you don't need to do anything special like restart the server when iteratively testing one, even if testing in a Zulip production environment where the server doesn't normally restart whenever a file is edited.