oca.recipe.odoo Package¶
oca.recipe.odoo
Package¶
base
Module¶
- class oca.recipe.odoo.base.BaseRecipe(buildout, name, options)[source]¶
Bases:
object
Base class for other recipes.
It implements notably fetching of the main software part plus addons.
The
sources
attribute is adict
storing how to fetch the main software part and the specified addons, with the following structure:local path -> (type, location_spec, options)
, in which:- local path:
is either the
main_software
singleton (seeMainSoftware
) or a local path to an addons directory.- type:
can be either
'local'
'downloadable'
one of the supported vcs
- location_spec:
is, depending on the type, a tuple specifying how fetch is to be done:
url
, or(vcs_url, vcs_revision)
orNone
- addons options:
are typically used to specify that the addons directory is actually a subdir of the specified one.
VCS support classes (see
oca.recipe.odoo.vcs
) can implemented their dedicated options
The
merges
attribute is adict
storing how to fetch additional changes to merge into VCS type sources:local path -> [(type, location_spec, options), ... ]
See
sources
for the meaning of the various components. Note that inmerges
, values are a list of triples instead of only a single triple as values insources
because there can be multiple merges on the same local path.- addons_paths = ()¶
- apply_odoo_requirements_file()[source]¶
Try and read Odoo’s ‘requirements.txt’ and apply it.
This file appeared in the course of Odoo 8 lifetime. If not available, a warning is issued, that’s all.
Entries from the requirements file are applied if there is not already an entry in the versions section for the same project.
A more interesting behaviour would be to apply then if they don’t contradict an existing entry in the versions section, but that’s far more complicated.
- apply_version_dependent_decisions()[source]¶
Store some booleans depending on detected version.
To be refined by subclasses.
- bool_opt_get(name, is_global=False)[source]¶
Retrieve an option and interpret it as boolean.
Factorized to improve code readability.
- Parameters:
is_global – if
True
, the option is taken from the global buildout options instead of the part taken care of by this recipe instance.
- cleanup_odoo_dir()[source]¶
Revert local modifications that have been made during installation.
These can be, e.g., forbidden by the freeze process.
- develop(src_directory)[source]¶
Develop the specified source distribution.
Any call to
zc.recipe.eggs
will use that developped version.develop()
launches a subprocess, to which we need to forward the paths to requirements via PYTHONPATH.- Parameters:
setup_has_pil – if
True
, an altered version of setup that does not require PIL is produced to perform the develop, so that installation can be done withPillow
instead. Recent enough versions of OpenERP/Odoo are directly based on Pillow.- Returns:
project name of the distribution that’s been “developed” This is useful for OpenERP/Odoo itself, whose project name changed within the 8.0 stable branch.
- dump_nightly_latest_version()[source]¶
After download/analysis of ‘nightly latest’, give equivalent spec.
- extract_downloads_to(target_dir, outconf_name='release.cfg')[source]¶
Extract anything that has been downloaded to target_dir.
This doesn’t copy intermediary buildout configurations nor local parts. In the purpose of making a self-contained and offline playable archive, these are assumed to be already taken care of.
- finalize_addons_paths(check_existence=True)[source]¶
Add implicit paths and serialize in the addons_path option.
- Parameters:
check_existence – if
True
, all the paths will be checked for existence (useful for unit tests)
- freeze_to(out_config_path)[source]¶
Create an extension buildout freezing current revisions & versions.
- insert_odoo_git_addons(base_addons)[source]¶
Insert the standard, non-base addons bundled within Odoo git repo.
See lp:1327756
These addons are also part of the Github branch for prior versions, therefore we cannot rely on version knowledge; we check for existence instead. If not found (e.g, we are on a nightly for OpenERP <= 7), this method does nothing.
The ordering of the different paths of addons is important. When several addons at different paths have the same name, the first of them being found is used. This can be used, for instance, to replace an official addon by another one by placing a different addons’ path before the official one.
If the official addons’ path is already set in the config file (e.g. at the end), it will leave it at the end of the paths list, if it is not set, it will be placed at the beginning just after
base
addons’ path.Care is taken not to break configurations that corrected this manually with a
local
source in theaddons
option.- Parameters:
base_addons – the path to previously detected
base
addons, to properly insert right after them
- install_requirements()[source]¶
Install egg requirements and scripts.
If some distributions are known as soft requirements, will retry without them
- is_git_layout = False¶
True if this is the git layout, as seen from the move to GitHub.
In this layout, the standard addons other than
base
are in aaddons
directory right next to theodoo
package.
- is_stale_http_head()[source]¶
Tell if the download is stale by doing a HEAD request.
Assumes the correct date had been written upon download. This is the same system as in GNU Wget 1.12. It works even if the server does not implement conditional responses such as 304
- list_develops()[source]¶
At any point in time, list the projects that have been developed.
This can work as soon as the recipe is instantiated (because the ‘buildout’ part) has already been executed. In particular, it does not rely on the workingset init done by
zc.buildout.easy_install.Installer
and can be used in precedence rules that need to be executed before calling the Installer indirectly viazc.recipe.eggs
- Returns:
list of project names
Implementation simply lists the develop eggs directory There’s probably better to be done.
- main_http_caching = 'filename'¶
- property major_version¶
- make_absolute(path)[source]¶
Make a path absolute if needed.
If not already absolute, it is interpreted as relative to the buildout directory.
- nightly_dl_url = {'10.0rc1c': 'http://nightly.odoo.com/10.0/nightly/src/'}¶
Base URLs to look for nightly versions.
The URL for 8.0 may have to be adapted once it’s released for good. This one is guessed from 7.0 and is needed by unit tests.
- parse_addons(options)[source]¶
Parse the addons options into
sources
.See
BaseRecipe
for the structure ofsources
.
- parse_merges(options)[source]¶
Parse the merge options into
merges
.See
BaseRecipe
for the structure ofmerges
.
- parse_revisions(options)[source]¶
Parse revisions options and update
sources
.It is assumed that
sources
has already been populated, and notably has amain_software
entry. This allows for easy fixing of revisions in an extension buildoutSee
BaseRecipe
for the structure ofsources
.
- preinstall_version_check()[source]¶
Perform version checks before any attempt to install.
To be subclassed.
- read_odoo_setup()[source]¶
Ugly method to extract requirements & version from ugly setup.py.
Primarily designed for 6.0, but works with 6.1 as well.
- read_release()[source]¶
Try and read the release.py file directly.
Used as a fallback in case reading setup.py failed, which happened in an old OpenERP version. Could become the norm, but setup is also used to list dependencies.
- recipe_requirements = ()¶
- recipe_requirements_paths = ()¶
- release_dl_url = {}¶
Base URLs to look for official, released versions.
There are currently no official releases for Odoo, but the recipe has been designed at the time of OpenERP 6.0 and some parts of its code at least expect this dict to exist. Besides, official releases may reappear at some point.
- requirements = ()¶
- retrieve_addons()[source]¶
Peform all lookup and downloads specified in
sources
.See
BaseRecipe
for the structure ofsources
.
- retrieve_main_software()[source]¶
Lookup or fetch the main software.
See
MainSoftware
andBaseRecipe
for explanations.
- sandboxed_tar_extract(sandbox, tarfile, first=None)[source]¶
Extract those members that are below the tarfile path ‘sandbox’.
The tarfile module official doc warns against attacks with .. in tar.
The option to start with a first member is useful for this case, since the recipe consumes a first member in the tar file to get the odoo main directory in parts. It is taken for granted that this first member has already been checked.
- soft_requirements = ()¶
- update()¶
- with_odoo_requirements_file = False¶
Whether attempt to use the ‘requirements.txt’ shipping with Odoo
- class oca.recipe.odoo.base.MainSoftware[source]¶
Bases:
object
Placeholder to represent the main software instead of an addon location.
Should just have a singleton instance:
main_software
, whose meaning depends on the concrete recipe class using it.For example, in
oca.recipe.odoo.server.ServerRecipe
,main_software
represents the OpenObject server or the Odoo standard distribution.
devtools
Module¶
Provide devtools to openerp.
server
Module¶
- class oca.recipe.odoo.server.ServerRecipe(*a, **kw)[source]¶
Bases:
BaseRecipe
Recipe for server install and config
- apply_version_dependent_decisions()[source]¶
Store some booleans depending on detected version.
Also does some options normalization accordingly. Currently, there is only one Odoo version, this method will be really useful again in a while.
- merge_requirements(reqs=None)[source]¶
Prepare for installation by zc.recipe.egg
develop the odoo distribution and require it
gunicorn’s related dependencies if needed
Once ‘odoo’ is required, zc.recipe.egg will take it into account and put it in needed scripts, interpreters etc.
Historically, in
anybox.recipe.openerp
this used to take care of adding Pillow, which is now in Odoo’ssetup.py
.
- nightly_filenames = {'10.0': 'odoo_10.0.%s.tar.gz', 'trunk': 'odoo_10.0alpha1.%s.tar.gz'}¶
Name of expected nightly tarballs in base URL, by major version.
- recipe_requirements = ('babel',)¶
- release_filenames = {}¶
- requirements = ('oca.recipe.odoo',)¶
- server_wide_modules = ()¶
- soft_requirements = ('odoo-command',)¶
- template_upgrade_script = '/opt/hostedtoolcache/Python/3.8.13/x64/lib/python3.8/site-packages/oca/recipe/odoo/upgrade.py.tmpl'¶
- with_gunicorn = False¶
- with_upgrade = True¶
- ws = None¶
testing
Module¶
Utilities for unit tests.
- class oca.recipe.odoo.testing.FakeRepo(target_dir='.fake', url='.fake', **options)[source]¶
Bases:
BaseRepo
- get_update(revision)[source]¶
Make it so that the target directory is at the prescribed revision.
The target directory need not to be initialized: this method will “clone” it from the remote source (whatever that means in the considered VCS).
This method can fail under various circumstances, for instance if the wanted revision does not exist locally and offline mode has been selected.
- Raises:
CloneError – if initial cloning fails
UpdateError – if update of existing repository fails
Must be implemented in concrete subclasses
- is_local_fixed_revision(revspec)[source]¶
True if revspec is a locally available fixed revision.
The concept of a fixed revision depends on the concrete VCS in use. It means that retrieving revspec at any point in the future
is guaranteed to work
always yields the same result
In practice, for most VCSes, these cannot be totally guaranteed, but each VCS defines those cases whose breaking is considered to be a very bad practice.
In Mercurial, removing a commit from a public repository is possible, but very bad. In Git, removing a commit from a public repository is normal workflow, but removing a tag is very bad.
The name stresses that only locally available ones will be recognized due to the promise that this method does not query any remote repo.
- log = []¶
- log_std_options = True¶
- name = 'fakevcs'¶
- parents(pip_compatible=False)[source]¶
Return universal identifier for parent nodes, aka current revisions.
There might be more than one with some VCSes (ex: pending merge in hg).
- Parameters:
pip_compatible – if
True
, only pip compatible revision specifications are returned, depending on the VCS type.
- revision = 'fakerev'¶
- schemes = ['fakevcs+http']¶
- vcs_control_dir = '.fake'¶
- class oca.recipe.odoo.testing.PersistentRevFakeRepo(target_dir='.fake', url='.fake', **options)[source]¶
Bases:
FakeRepo
A variant of FakeRepo that still needs the directory structure around.
Makes for a more realistic test of some conditions. In particular, reproduced launchpad #TODO
- current_revisions = {}¶
- property revision¶
str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.
- class oca.recipe.odoo.testing.RecipeTestCase(methodName='runTest')[source]¶
Bases:
TestCase
A base setup for tests of recipe classes
- build_babel_egg()[source]¶
build an egg for fake babel in buildout’s eggs directory.
Require the test case to already have a
test_dir
attribute (typically set on class with the dirname of the test)
- build_fictive_egg()[source]¶
build an egg of a fictive distribution for testing purposes.
Require the test case to already have a
test_dir
attribute (typically set on class with the dirname of the test)
- develop_fictive(require_install=False)[source]¶
Develop fictive distribution in buildout’s directory.
Require the test case to already have a
test_dir
attribute (typically set on class with the dirname of the test)- Parameters:
require_install (bool) – if
True
, will be required fromeggs
option, and installed.
- fictive_dist_name = 'FictiveDist'¶
- fictive_name = 'fictivedist'¶
- fictive_version = None¶
- class oca.recipe.odoo.testing.TestingRecipe(buildout, name, options)[source]¶
Bases:
BaseRecipe
A subclass with just enough few defaults for unit testing.
- nightly_filenames = {'10.0rc1c': '10-0-nightly-%s.tbz'}¶
- release_dl_url = {'10.0': 'http://release.odoo.test/src/'}¶
Base URLs to look for official, released versions.
There are currently no official releases for Odoo, but the recipe has been designed at the time of OpenERP 6.0 and some parts of its code at least expect this dict to exist. Besides, official releases may reappear at some point.
- release_filenames = {'10.0': 'blob-%s.tgz'}¶
utils
Module¶
- class oca.recipe.odoo.utils.WorkingDirectoryKeeper[source]¶
Bases:
object
A context manager to get back the working directory as it was before.
If you want to stack working directory keepers, you need a new instance for each stage.
- active = False¶
- oca.recipe.odoo.utils.check_output(*popenargs, **kwargs)[source]¶
Backport of subprocess.check_output from python 2.7.
Example (this doctest would be more readable with ELLIPSIS, but that’s good enough for today):
>>> out = check_output(["ls", "-l", "/dev/null"]) >>> out.startswith('crw-rw-rw') True
The stdout argument is not allowed as it is used internally. To capture standard error in the result, use stderr=STDOUT.
>>> os.environ['LC_ALL'] = 'C' # for uniformity of error msg >>> err = check_output(["/bin/sh", "-c", ... "ls -l non_existent_file ; exit 0"], ... stderr=subprocess.STDOUT) >>> err.strip().endswith("No such file or directory") True
- oca.recipe.odoo.utils.clean_object_files(directory)[source]¶
Recursively remove object files in given directory.
Also remove resulting empty directories.
- oca.recipe.odoo.utils.is_object_file(filename)[source]¶
True if given filename is a python object file.
- oca.recipe.odoo.utils.major_version(version_string)[source]¶
The least common denominator of Odoo versions : two numbers.
Odoo version numbers are a bit hard to compare if we consider nightly releases, bzr versions etc. It’s almost impossible to compare them without an a priori knowledge of release dates and revisions.
Here are some examples:
>>> major_version('1.2.3-foo.bar') (1, 2) >>> major_version('6.1-20121003-233130') (6, 1) >>> major_version('7.0alpha') (7, 0)
Beware, the packaging script does funny things, such as labeling current nightlies as 6.2-date-time whereas version_info is (7, 0, 0, ALPHA) We can in recipe code check for >= (6, 2), that’s not a big issue.
Regarding Odoo saas releases (e.g. 7.saas~1) that are short-lived stable versions between two “X.0” LTS releases, the ‘saas~’ argument before the minor version number is stripped. For instance:
>>> major_version('7.saas~3') (7, 3)
- oca.recipe.odoo.utils.option_splitlines(opt_val)[source]¶
Split a multiline option value.
This function performs stripping of whitespaces and allows comments as ConfigParser would do. Namely:
a line starting with a hash is a comment. This is already taken care of by
zc.buildout
parsing of the configuration file.ConfigParser
does not apply this rule to the case where the hash is after some leading whitespace (e.g, line-continuation indentation) as in this example:[foo] bar = line1 line2 # this is a comment # this is not a comment, and will appear in 'bar' value
Therefore this function does not have to perform anything with respect to hash-comments.
everything after a semicolon following a whitespace is a comment:
[foo] bar = line1 line2 ;this is a comment
- Parameters:
opt_val (basestring) – the raw option value
- Returns:
tuple of strings
doctests (less readable than examples above, but more authoritative):
>>> option_splitlines('line1\n line2 ;this is a comment\n line3') ('line1', 'line2', 'line3') >>> option_splitlines('l1\n; inline comment from beginning\n line3') ('l1', 'line3') >>> option_splitlines('l1\n; inline comment from beginning\n line3') ('l1', 'line3') >>> option_splitlines('l1\n ; disappears after stripping \n line3') ('l1', 'line3') >>> option_splitlines('line1\n\n') ('line1',) >>> option_splitlines('') ()
The return value is guaranteed not to be a single string:
>>> option_splitlines('single') ('single',)
For convenience,
None
is accepted:>>> option_splitlines(None) ()
- oca.recipe.odoo.utils.option_strip(opt_val)[source]¶
Same as
option_splitlines()
for a single line.>>> option_strip(" hey, we have ; a comment") 'hey, we have' >>> option_strip(None) is None True
- oca.recipe.odoo.utils.total_seconds(td)[source]¶
Uniformity backport of
datetime.timedelta.total_seconds`()
- Parameters:
td – a
datetime.timedelta
instance- Returns:
the number of seconds in
tdelta
The implementation for Python < 2.7 is taken from the standard library documentation