PYTHON CODING STRUCTURE

PEP8 Options

Find syntax and semantic warnings or errors using linter flake8. The source code must adhere to PEP8 and PyFlakes standards with some of the exceptions-
  • In __init__.py only
    • F401: module imported but unused

Imports

Ordering status:
  • Standard library imports
  • ODOO imports
  • Known third party imports
  • Local imports in the relative form
  • Imports from ODOO modules
  • Unknown third party imports
The imported lines are alphabetically sorted in these 6 groups.
NOTE:
  • isort command- automatically sort imports
  • Install with pip install isort and use with isortmyfile.py

Idioms

  • Each python file must have first line as-
    • # coding: utf-8 or
    • # -*- coding: utf-8 -*-
  • For better translation and clarity, use-
    • % over .format()
    • %(varname) instead of positional
  • Favor readability over conciseness or use language features or idioms
  • Use list comprehension, dict comprehension and basic manipulation to make code more pythonic, easier to read and efficient. Commands like map, filter, sum and others can be used
  • For recordset methods, use filtered, mapped, sorted and other such commands
  • Some exceptions:
    • from openerp.exceptions import Warning as UserError (v8)
    • from openerp.exceptions import UserError (v9)
    • find more appropriate exception in openerp.exceptions.py
  • To document your code-
    • Docstring on methods that explains purpose of a function instead of summary of code
    • Simple comments for the parts of code that are not immediately obvious
    • Comments are a sign that the code is unreadable and needs to be refactored
  • Variable/class/method names must be meaningful
  • Refactor long functions into smaller ones used in loops
  • Use named parameter if the argument to a function call is not immediately obvious
  • Prefer using English variable names and write comments in English.
  • Strings that needs to be displayed in other languages must be translated using translation system
  • Avoid using api.v7 decorator in new code unless there is already an API fragmentation in parent methods

Symbols

Odoo Python Classes
  • Use UpperCamelCase for coding in api v8
            class AccountInvoice(models.Model):
            ...
  • Use underscore lowercase notation for old api
            class account_invoice(orm.Model):
            ...

Variable Names
  • For common variables, use underscore lowercase notation
  • For global variables or constants, use underscore uppercase notation
  • As new API works with records or recordsets instead of id lists, do not suffix variable names with _id or _ids if there aren't any

SQL

No SQL Injection
  • When using manual SQL queries, do not introduce SQL injection vulnerabilities
  • If user input is incorrectly filtered or badly quoted or allow an attacker to introduce undesirable clauses to SQL queries, the vulnerabilities are present.
  • The best way to deal with this and stay safe is- never use Python string concatenation (+) or string parameters interpolation (%) to pass variables to SQL query string
  • The database abstraction layer (psycopg2) decides how to format query parameters


Never Commit the Transaction
  • The OpenERP/OpenObject framework provides the transactional context for all RPC calls.
  • The principle is- a new database cursor is opened at the beginning of each RPC call and is committed on the returning of call.
  • If error occurs during the execution of RPC call, the transaction is being rolled back atomically while preserving the state of the system
  • The system provides dedicated transaction during execution of test suites so that it can be rolled back or not depending on the server startup option
  • Some consequences of manually call cr.commit()-
    • Inconsistent business data and data loss
    • Workflow desynchronization, documents stuck permanently
    • Test will not have clean roll back and it will start polluting database as well as triggering error

Models

Model Names :
  • Use dot lowercase name of models. Example- sale.order
  • Use name in singular form. Example- sale.order instead of sale.orders


Method Conventions :
  • Compute Field: The compute method pattern is __compute__<field_name>
  • Search Method: The search method pattern is __search__<field_name>
  • Inverse Method: The inverse method pattern is __inverse__<field_name>
  • Default Method: The default method pattern is __default__<field_name>
  • Constraint Method: The constraint method pattern is __check__<constraint_name>
  • Onchange Method: The onchange method pattern is __onchange__<field_name>
  • Action Method: An object action method is prefix with action__. The decorator of action method is @api.multi, but if it is going to be used with one record, add self.ensure_one() at the beginning of the method.
  • @api.one method:For v8, you can use @api.multi, for compatibilitty with v9 use @api.one


Model Attribute Order :
  • Private attributes
  • Default method and __default_get
  • Field declarations
  • Compute and search methods
  • Constraint methods and onchange methods
  • CRUD methods
  • Action methods
  • Other business methods

Do Not bypass ORM 

Never use database cursor directly when ORM serves the same purpose. If done, you will bypass all ORM features, even the transactions, access rights and others.