Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup Python guidelines #81

Open
ltekieli opened this issue Dec 13, 2024 · 5 comments
Open

Setup Python guidelines #81

ltekieli opened this issue Dec 13, 2024 · 5 comments
Labels
help wanted Extra attention is needed infrastructure General Score infrastructure topics lang:python

Comments

@ltekieli
Copy link
Member

  • Best guess coding rules
  • Best guess tooling (static code analysis, formatting)
@ltekieli ltekieli added help wanted Extra attention is needed infrastructure General Score infrastructure topics labels Dec 13, 2024
@AlexanderLanin
Copy link
Member

let's scope it to existing tools/scripts written by infrastructure/tooling team which are in in the score repository

@sameer6989
Copy link

This document serves as a draft guideline to be agreed upon by the Python developers to write clean, maintainable, and efficient code. This is not exhaustive but serves as a starting point to getting a comprehensive coding guideline document.

-> Code style guidelines

Follow PEP 8 (Python’s style guide)

  • Indentation: Use 4 spaces per indentation level.
  • Line length: Limit lines to 79 characters.
  • Separate top-level function and class definitions with two blank lines.
  • In method definitions inside a class, use a single blank line between methods.
    Ref. - PEP 8

Naming conventions

  • Use snake_case for variables and functions.
  • Use CamelCase for classes.
  • Use ALL_CAPS for constants.
    my_variable = 10
    class MyClass:
        pass

Ref. - PEP 8 Naming Conventions

Imports

  • Import modules at the top of files.
  • Use absolute imports whenever possible.
    Ref. - PEP 8 Imports

-> Writing clean and readable code

Avoid deep nesting

  • Use return early to avoid nested blocks.
    def is_even(number):
        if number % 2 == 0:
            return True
        return False

Add comments and docstrings

  • Use comments to explain the why, not the what.
  • Avoid overly complex one-liners; prioritize clarity over brevity.
  • Use docstrings for functions, classes, and modules.
    def add(a, b):
        """Adds two numbers."""
        return a + b

Ref. - PEP 257, Google Python Style Guide

Use type annotations

  • Make code self-documenting by using type hints.
    def greet(name: str) -> str:
        return f"Hello, {name}!"

Ref. - PEP 484

Adopt modular design

  • Break down large functions and classes into smaller, reusable components.
  • Group related functions and classes into modules and packages.
project/
    __init__.py
    module_one.py
    module_two.py
    utils.py
  • Use __init__.py to define package-level exports.

Ref. - PEP 420 - Implicit Namespace Packages


-> Avoid common pitfalls

Mutable default arguments

  • Use None instead of mutable objects as default arguments.
    def append_to_list(value, lst=None):
        if lst is None:
            lst = []
        lst.append(value)
        return lst

Handle Exceptions Gracefully

  • Use try-except blocks for error handling and logging meaningful messages.
  • Avoid catching generic Exception unless absolutely necessary:
try:
    result = 10 / divisor
except ZeroDivisionError:
    print("Error: Division by zero is not allowed.")
  • Use finally for cleanup tasks and else for code that executes if no exceptions occur.

Ref. - PEP 409 - Suppressing Exception Context

Avoid hardcoding

  • Use configuration files, environment variables, or constants for settings.

-> Performance optimization

Use list comprehensions

  • Example
    squares = [x**2 for x in range(10)]

Prefer built-in functions

  • Built-in functions are faster than manually written loops.
    result = sum([1, 2, 3, 4])

->Testing and debugging

Write unit tests

  • Use unittest, pytest, or other frameworks.
    def test_add():
        assert add(2, 3) == 5

Use logging instead of print statements

  • Logging helps with differentiating the logs based on severity.
    import logging
    logging.basicConfig(level=logging.INFO)
    logging.info("This is an informational message.")

->Version Control and Collaboration

Commit messages

  • Use meaningful commit messages that explain the “why.”

Document your code and API**

  • Use tools like Sphinx or MkDocs to generate professional documentation from docstrings.
  • Keep the documentation up to date with code changes.
    Ref. - Sphinx Documentation

-> Tools and linters


-> References and further reading


@AlexanderLanin
Copy link
Member

Nice! My 2 cents:

  • But a little too much? I would skip whatever the linter warns about anyway (naming conventions, imports on top of flle, etc)
  • commit messages are explained elsewhere in score
  • We currently don't intend do generate any documentation from docstrings
  • "Use tools like black, ruff, etc." is too generic, there is also no need to mention that at all
  • https://google.github.io/styleguide/pyguide.html is a footnote, but that's potentially the most important point here. In case it's any good. I haven't read it (yet).

@hoe-jo
Copy link
Contributor

hoe-jo commented Jan 29, 2025

Good first guideline!
Can we create a pr with .rst from it so we can discuss it in the files?

my notes would be:

  • For verification we are currently working on the definition of test cases and metatags for it etc, so there will be another guideline which we only could refer from here?
  • Shall we include some how tos like debugging python in bazel? Or shall we create here different structrure for it?
  • For the linters we could provide a VScode config including extensions and mention which formatters are used in the CI?

@AlexanderLanin
Copy link
Member

Looking at some code in our current repository let's elaborate on comments and type hints a little:

  • Always provide comments to explain something when it's not obvious. NEVER EVER provide comments because you have to. Most comments we see are best case redundant to the code itself and don't offer additional information. Worst case they are just wrong. Noone reads or fixes them, since they are so many.
  • type hints: I'm sure there is some reasonable guideline when to add type hints? It's somewhere between never and always. Both extremes are extremely annoying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed infrastructure General Score infrastructure topics lang:python
Projects
Development

No branches or pull requests

4 participants