Skip to content
This repository has been archived by the owner on Apr 8, 2024. It is now read-only.

coding standards

daira edited this page Sep 9, 2014 · 3 revisions

Coding Standards

Consensed

This (currently empty) section includes standards we've consensed on.

Proposed

These are proposals that the team has not yet consensed on:

Avoiding Dialect

Follow the tahoe-lafs Coding Standards whenever possible.

Exception: Sometimes those standards assume the allmydata codebase which is not always feasible for LeastAuthority repositories.

In that case, we approximate in an ad-hoc manner until we do that too often. Then we either write a redundant library or split out functionality from allmydata. An example is allmydata.util.assertutil.

File Paths

Use Twisted Filepath

Use twisted.python.filepath instead of os.path if possible:

  • If Twisted is not a dependency, strongly consider making it a dependency even just to use twisted.python.filepath.
  • Create FilePath objects as close to the string input as possible.

When Twisted is Unavailable

If Twisted cannot be a dependency:

  • Always translate paths to absolute paths as close to the string input as possible with os.path.abspath.

    • Rationale: This makes logs and error messages unambiguous.
  • Always derive child paths from parent paths when possible using os.path.join.

    • Rationale: os.path.join(a, b) works regardless of if a ends with a path separator or not.
    • Rationale: Traversing up to parents is often surprising to users (ie: If I run foo ./my/path and this reads or changes foo ./blah I am often surprised except for well known exceptions like home directory dot paths).
  • Eschew string manipulation of paths:

    • Never use python string manipulation to compute or change details of directory hierarchy or extension, always rely on os.path.join and os.path.splitext to maintain hierarchy and extensions.

    • When synthesizing or parsing path components with string operations, always operate on a single "component" rather than a path which spans hierarchy.

      • eg:

        • instead of: logpath = '%s/%s-%s.log' % (logdir, componentname, timestamp)
        • use: logpath = os.path.join(logdir, '%s-%s.log' % (componentname, timestamp))
        • In both of these examples, how do you know neither componentname nor timestamp contain a path separator? (-It requires more context than these snippets and is a burden for code readers.)
    • Rationale: String manipulation for hierarchy manipulation is redundant with os.path and very likely to have bugs which os.path does not.

    • Rationale: The intent is clearer when reading code. eg: os.path.join(a, b) vs '/'.join([a, b]) etc...

Subprocesses

Eschew shell=True in calls to subprocess APIs. This is a security hazard and rarely provides any benefit. In the case that shell behavior is relied upon, consider rewriting those features explicitly in python.

Warning

Note that shell=True is implied if the args parameter is a single string.

Warning

Even when args is a sequences of strings, shell=True is still possible. (I like to always pass shell=False explicitly, even though that is the default if args is a sequence of strings. This is the kind of "flexible" python API style I abhor.)

Shell Escaping

If there are any other cases where shell escaping is used, this is almost certainly a cause for concern for security and correctness. Looking for the pipes module which has shell_quote.

Git Variable Names

If we have a variable which refers to part of a git repository it shall have the following form:

$(REPO_NAME)_repo_gitdir

OR

$(REPO_NAME)_repo_workdir

depending on which component it refers to.

We'll always derive the $(REPO_NAME)_repo_gitdir from the $(REPO_NAME)_repo_workdir, perhaps like this:

from twisted.python.filepath import FilePath
$(REPO_NAME)_repo_workdir = FilePath( $(DIRECTORY_NAME_STRING) )
$(REPO_NAME)_repo_gitdir = $(REPO_NAME)_repo_workdir.child('.git')