Klassen Software Solutions

Python Coding Standards

def from_url(url: str): """Read a JSON from a URL. Returns: Either returns a List or a Dict depending on the returned contents. Raises: ValueError: if the url is empty requests.exceptions.ConnectionError: if the url connection cannot be made kss.util.jsonreader.NotOkResponseError: if the url returns a non-OK response kss.util.jsonreader.ContentTypeResponseError: if the url does not claim to return 'application/json' json.decoder.JSONDecodeError: if the returned contents cannot be interpreted as JSON """ contract.parameters(lambda: bool(url)) logging.debug("GET '%s' as JSON", url) resp = requests.get(url, headers={'Accept': 'application/json'}) if not (resp.status_code >= 200 and resp.status_code < 300): raise NotOkResponseError(resp.status_code) ctype = resp.headers.get('content-type', '') if not ctype.startswith('application/json'): raise ContentTypeResponseError(ctype) return resp.json()

General Coding Principles

  1. Favour reliability and readability over strict formatting guidelines, but if you choose to break one of our guidelines you must be prepared to justify your decision.
  2. When appropriate1 , follow Programming by Contract patterns. Use the tools in the kss.util.contract module of the pyutil library for this purpose.
  3. Write unit tests that cover your code. Your code must pass the unit tests before your pull requests will be accepted. Use the standard Python unittest module for this purpose.
  4. Follow the Python 3 standard.
  5. Document the public portion of your API using the standard Python docstrings.
  6. Do not use newlines liberally. In particular, do not use them to make your code "double spaced." Newlines should be used to draw the eye to logically grouped sections of the code.
  7. Eliminate all compiler warnings as reported by pylint. If you cannot eliminate a warning use a # pylint: disable=... comment, but be prepared to justify your decision. An example could look like the following:

    # pylint: disable=no-self-use
    #    Justification: self is required as part of the API.
    def pre_project_callback(self, _project: Dict) -> List:
        """Subclasses may override this to perform ...

Specific Coding Guidelines

For the most part we follow the PEP 8 coding standards, so you should become familiar with them. We also use pylint to check for conformance. In addition to PEP 8, you should keep the following in mind:

  1. Keep lines to no more than 95 characters in length.2
  2. Keep methods and blocks to no more than 50 lines in length.3
  3. Ensure that everything in a single module is closely related.
  4. Don’t document the obvious. It should be possible to understand your code simply by reading your code. Instead comments (other than the documentation comments mentioned above) should describe why you chose a specific implementation, or why you are breaking from one of our standards, or just to make the code more navigable (e.g. # TODO: <something>).
  5. Place the public portions of your API near the start of your file, and the private implementation portions near the end.

1. Since we often use Python for the creation of simple tools, we do not always follow the Programming by Contract pattern. However, when writing things that may be used as part of a production system, you should follow the pattern.

2. Our code reviewers should be able to view two files side by side in a 12pt font on a reasonably sized desk monitor.

3. Developers should be able to see an entire block at once in a 12pt font on a laptop screen.