Package: anthem
Anthem is a tool to help scripting Odoo instances for automated setup,
upgrades, testing and more.It should be an alternative to the other tools likeoerpscenario.Make your own songsWriting your songs is as easy as creating a Python Package. The
songs functions called by anthem must have a positionalctxargument.ctxis essentially the execution context - you can accessctx.envfrom
it, which is an Odoo environment instance that you should be pretty much familiar with.## songs/install.py

def setup_company(ctx):
    """ Setup company """
    company = ctx.env.ref('base.main_company')
    company.name = 'My Company'


def main(ctx):
    setup_company(ctx)LogsA song can display some logs when executed with@anthem.log,Context.logandContext.log_line.importanthem@anthem.logdefsetup_company(ctx):""" Setting up company """company=ctx.env.ref('base.main_company')withctx.log('Changing name'):company.name='My Company'ctx.log_line('Name changed')withctx.log('Loading a logo'):company.logo=b64encode(LOGO_CONTENT)ctx.log_line('Logo changed')The decorator on the function will display the first line of the docstring.
Both the decorator and the context manager will show the timing of the
execution. The upper example gives:Execute your songsUse the command lineanthem. Provided your songs andopenerpare in thePYTHONPATH:Anthem will execute the functionmainof the modulesongs.installwith
actxinitialized with an Odooenv.Instead of using-cfor the command line, you can export the environment
variableOPENERP_SERVERwith the path of the configuration file.In order to haveopenerpin thePYTHONPATH, you might install it as a
package withpip install-eor directly modify thePYTHONPATH.In order to have yoursongsin thePYTHONPATH, the better is to make a
Python package out of them.TestingDependenciesTo run the tests, you must have Postgresql running, with accesses for your user
(or you will have to modifytests/config/odoo.cfgwith your database
username and password).Run the testsTo runanthem’s tests, it is a good idea to do aneditableinstall of it
in a virtualenv. You must also prepare the environment by installing odoo packages.Odoo 9.0 (Python 2):Odoo 10.0 (Python 2):Odoo 11.0 (Python 3):If need be, you can drop the test database with (adapt the version):These steps will download the nightly release of Odoo install it as a package
then install a database, so tests can be run against it (and that’s also why it
is important to use a virtualenv!)When callingpytest, you have to define theOPENERP_SERVERenvironment
variable with the configuration file for the Odoo database that will be used
for the tests.LyricsLyrics are predefined snippets written for the most commonly used cases, like:Loading data: read (load) a data file (CSV format is supported at the moment)Provide XMLIDs for recordsUpserting a record: essentially search for the record and update it with
given values, or create it in case it isn’t there yetUninstalling a module(s)Updating module configuration: pre-defining a set of settings for a particular
module (or set of modules)Loading dataThere’s an ability to supply data in a handy CSV format - Anthem is just able to
parse and load those.load_csvmethod is meant to be the main entrypoint for
doing so:ParamDescriptionctxAnthem context instancemodelOdoo model name or model klass fromctx.envpathabsolute or relative path to CSV file.
If a relative path is given you must provide a value forODOO_DATA_PATHin your environment
or set--odoo-data-pathoption.headerwhitelist of CSV columns to loadheader_excludeblacklist of CSV columns to ignorefmtparamskeyword params forcsv_unireaderCSV format is similar to that of an Odoo export format, namely:
* it should contain a set of field names in a header
* each consecutive row defines a set of values to use to create records on a given modelRecordsThis section is dedicated to methods that operate on records.Provide XMLIDs for recordsThis is as simple as callinganthem.records.add_xmlidwith a record as a
first parameter and a desired XMLID as a second.E.g., you have a very specialres.partnerrecordfoo:fromanthem.recordsimportadd_xmlid[...]@anthem.logdefadd_xmlid_to_foo(ctx):"""Make Jhony Foo great again."""foo=ctx.env['res.partner'].create({'name':'Jhony','lastname':'Foo',})add_xmlid(foo,'__setup__.res_partner_foo_jhony')From now on, Jhony could be referred to asctx.env.ref('__setup__.res_partner_foo_jhony').Upserting a record“Upsert”is a commonly used term that basically stands for UPDATE or INSERT.
Anthem features a facility that is capable of executing that kind of operations
on Odoo databases. There is a method calledanthem.records.create_or_updatethat relies on the model, a set of values and a record XMLID.If your goal is to create the record in the first place as well as provide an
XMLID, as was shown in a previous section,create_or_updatedoes just what
you need.Examplefromanthem.recordsimportcreate_or_update[...]@anthem.logdefcreate_partner_foo(ctx):"""Ensure that Jhony Foo is known to our Company."""create_or_update(ctx,model='res.partner',xmlid='__setup__.res_partner_foo_jhony',values={'name':'Jhony','lastname':'Foo',})Upon calling, it would:Try to fetch the record by a given XMLIDIf the record was found:Update it with the given values (callrecord.update(values)on it)Otherwise:Create a record with given values (callmodel.create(values))Provide an XMLID to it (usinganthem.records.add_xmlid)In any case: return that record backModulesThis section is dedicated to methods that operate on modules.Uninstalling a module(s)Sometimes you just need some particular module to be gone from your instance(s)
and you’d like it done programmatically, without having to reach for each
instance, search for it and hit the“Uninstall”button. Anthem can do the
job for you: you can simply call ananthem.lyrics.modules.uninstallwith a
list of module names that you won’t use anymore.Example (given that there are modulesfooandbarthat you want gone):fromanthem.lyrics.modulesimportuninstall[...]@anthem.logdefuninstall_foo(ctx):"""Get rid of legacy `foo` and `bar`."""uninstall(ctx,['foo','bar'])Updating translations on module(s)In a similar fashion, sometimes you need to update translations on a set of
modules -anthem.lyrics.modules.update_translationsis there for you :wink:Example is similar to the previous case - just call the different method instead.Updating module configurationBy using this feature, you’re able to preconfigure your module setup via Anthem
song: you’ll just need a straight idea what needs to be done, an instance of a
configuration settings model for your module (model name will do as well) and a
mapping (in a form of Python dictionary) of technical configuration names with
desired values.Here’s a brief example ofsalemodule configuration:fromanthem.lyricsimportsettings[...]@anthem.logdefdefine_sale_settings(ctx):"""Configure `sale` module."""model=ctx.env['sale.config.settings']# it's okay to use 'sale.config.settings' as a string thoughmodel='sale.config.settings'settings(ctx,model,{'default_invoice_policy':'delivery',...:...,'et':'cetera',})Be advised: settings onchange are not triggered by this function.Usage within MarabuntaAnthem andMarabuntaare powerful
when combined: you can call a set of songs inside Marabunta’s migration steps
using following syntax:...-version:10.0.1.0.0operations:pre:-anthem songs.upgrade.your_pre_song::mainpost:-anthem songs.upgrade.your_post_song::mainBy using this approach, you possess the power of full-pledged OdooEnvironmentinstance initialized on a live database while performing a
regular upgrade powered by Marabunta.Let’s say that you have to enable multicompany with inter-company transactions
on a migration to next version, lets say, 10.0.1.1.0. In this case, you’ll need
a song to back this up on a Python side first:# songs.upgrade.upgrade_10_0_1_1_0.pyfromanthem.lyricsimportsettings[...]@anthem.logdefenable_multicompany(ctx):"""Set up multicompany."""settings(ctx,'base.config.settings',{# enable multicompany as it is'group_light_multi_company':True,# enable inter-company transactions'module_inter_company_rules':True,})[...]@anthem.logdefmain(ctx):enable_multicompany(ctx)And then you’ll need to call it on a migration step:...-version:10.0.1.1.0operations:post:-anthem songs.upgrade.upgrade_10_0_1_1_0::mainBoom! Enjoy your new multicompany settings.That’s all, folks!Thanks for reading. Happy hacking and enjoy your songwriting skills!Release HistoryUnreleasedFeaturesBugfixesImprovementsDocumentationBuild0.14.0 (2023-05-16)BugfixesFix Update_translation function and update black version 22.3.0Pin version of Setuptools < 58Fix environment initialization for Odoo 15Fixadd_xmlidfor Odoo 15ImprovementsEnable Travis-CI tests for Odoo 14 and Odoo 15Add: nuke_translations to allow to remove already existing translations0.13.0 (2019-08-29)FeaturesBREAKING: Change defaultoverwritevalue forlyrics.modules.update_translationsto FalseSupport odoo saas versionsBugfixesMakelyrics.modules.update_translationsOdoo >= 11.0 compatible0.12.2 (2019-06-21)ImprovementsAdd ‘tracking_disable=True’ as default context to load CSVs
(avoid creating ‘mail.message’ records and speed up the import process)BuildPackaging: build universal wheels0.12.1 (2018-11-09)DocumentationImprove API docsBuildThe lib is now automaticaly published to Pypi by Travis when a tag is added0.12.0 (2018-03-19)FeaturesAdd a new option--odoo-data-pathor env. variableODOO_DATA_PATH.Thelyrics.loaders.load_csvmethod now accepts a relative path appended to the
new option “odoo data path”. Absolute paths are still allowed.Bugfixeslyrics.loaders.update_translationsis now deprecated as it was a duplicate fromlyrics.modules.update_translations0.11.0 (2017-12-22)FeaturesMake it Python 3 and Odoo 11 compatibleBuildSwitch to unicodecsv instead of custom code to handle thatFix the flapping tests setup. Removed tox which was provoking that for some reason.Add a lint check in build0.10.0 (2017-09-19)BugfixesDisable Odoo’s xmlrpc portBuildAdd ‘build-release.sh’ script with commands to build and upload the dist files0.9.0 (2017-08-21)FeaturesNew lyrics: modules.update_translations to update translations from po filesLyrics ‘uninstall’ has been moved from uninstaller.uninstall to modules.uninstall,
previous path is still working for backward compatibilityNew lyrics context manager ‘records.switch_company’0.8.0 (2017-07-24)FeaturesNew lyrics: Define settings like being in the interfaceAdd CSV Loading columns control (columns whitelist and blacklist)BugfixesFix error when loading CSV with no rows0.7.0 (2017-04-28)ImprovementsSplit CSV loaders in functions to be able to get rows from a CSV or to load
rows, enabling to modify the rows before loading them for instancecreate_or_update lyrics accepts now a model so we can change its env (user,
context, …)New lyrics to uninstall module0.6.0 (2017-01-18)FeaturesCSV loaders can be used with a model in order to pass a contextBugfixesFix tests by installing eggs from odoo/requirements.txt0.5.0 (2016-10-12)FeaturesSupport Odoo 10Allow to specify the encoding of an imported file, default is utf8Bugfixes‘records.add_xmlid’ lyrics do no longer fail when it already exists0.4.0 (2016-08-19)FeaturesNew lyrics: CSV loaders from path or streamNewctx.log_lineto print a line respecting the current indentationImprovementsAdd tests for the existing lyricsBuildFinally green builds!0.3.0 (2016-07-26)FeaturesAdd –quiet modeFixesEncode the logged strings to the default encoding or utf8Allow to use Ctrl-c to stop anthem.Set openerp’s loglevel to ERROR, its logs clutter anthem’s own outputs0.2.0 (2016-07-22)FeaturesAbility to log descriptions and timings in songs with the
context managerContext.logand the decoratoranthem.log.from anthem import log

@log
def setup_company(ctx):
    """ Setup company """
    # do stuff
    with ctx.log('other stuff'):
        # do other stuff

@log
def load_data(ctx):
    """ Load data """
    # load

@log
def main(ctx):
    setup_company(ctx)
    load_data(ctx)If we run anthem onmain, we will get:running... main
   running... Setup company
      running... other stuff
      other stuff: 0.850s
   Setup company: 1.100s
   running... Load data
   Load data: 2.900s
main: 4.000s0.1.3 (2016-07-07)FixesCorrect lyric to create or update a record0.1.2 (2016-07-07)Add a lyric to create a xmlidAdd a lyric to create or update a record0.1.1 (2016-06-23)Fixed crash on non-editable install.0.1.0 (2016-06-23)Initial release.