Coding Best Practices
Long-term ongoing refactoring means that some practices you see in FreeIPA's existing code are considered obsolete. They should not be used in new code, and old code should be updated when they are encountered.
Here is a list of these, with examples of the old and new way of doing things.
Decorator-based plugin registration
To allow registering plugins to non-default API objects, plugin registration changed from:
from ipalib import api ... class myobj_mod(LDAPUpdate): ... api.register(myobj_mod)
from ipalib.plugable import Registry register = Registry() ... @register() class myobj_mod(LDAPUpdate): ...
Note that it's necessary to name the decorator register.
Split long translatable strings
Long translatable strings, such as plugin modules' __doc__, should be split up by paragraph, so that if something is changed/added, only the affected part needs to be re-translated. Example:
__doc__ = _(""" Foo Plugin """) + _(""" This plugin allows management of enterprise foos and bars. """) + _(""" Here is a second paragraph. """")
Note that the strings should only be split when they are changed, because after a split all parts have to be re-translated.
Do not use star imports
Star imports make it more difficult to see where names come from, and names newly added to the imported module can unintentionally shadow variables elsewhere.
from baseldap import * class tank_create(LDAPCreate):
from ipalib.plugins import baseldap class tank_create(baseldap.LDAPCreate):
from ipalib.plugins.baseldap import LDAPCreate class tank_create(LDAPCreate):
See https://fedorahosted.org/freeipa/ticket/2653, and PEP8
Use the admintool framework for installation/management scripts
There is a framework that standardizes common tasks such as argument parsing, logging, error handling, interactive prompting. Use it.
For a simple example, see the implementation of ipa-server-certinstall.
Related design concerning the CLI changes: V3/Logging and output
For these items, all code in IPA was updated and, if applicable, the old way of doing things was disabled.
LDAPEntry dict-like API
A LDAPEntry no longer unpacks to a tuple:
# Old code dn, attrs = entry values = attrs[attrname]
Instead, the entry is a dict-like object:
# New code dn = entry.dn values = entry[attrname]
To highlight errors, a LDAPEntry currently cannot be iterated.