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

[FEATURE] Cleanup import statements #870

Open
mgovers opened this issue Jan 14, 2025 · 0 comments
Open

[FEATURE] Cleanup import statements #870

mgovers opened this issue Jan 14, 2025 · 0 comments
Labels
feature New feature or request good first issue Indicates a good issue for first-time contributors

Comments

@mgovers
Copy link
Member

mgovers commented Jan 14, 2025

The module graph for the Python wrapper is fairly convoluted (see https://power-grid-model.readthedocs.io/en/stable/advanced_documentation/python-wrapper-design.html). This is a direct consequence of the fact that many

Background

Definitions

We make the following distinctions:

  • modules v.s. symbols:
    • modules: .py files (or, more correctly, anything that can be imported from)
    • symbols: anything that exists within a module: classes, functions, variables, imported modules, etc. within a file (that means, anything that can marked import from a module)
  • 'public' v.s. 'protected' v.s. 'private':
    • public: any module or symbol that is publicly available (appears in API)
    • protected: anything that is meant for internal usage, and that users should not directly use (prefixed _)
    • private: anything that is restricted to a module or class that outside users should not even have knowledge of (prefixed __; double underscore)

In the PGM, 'protected' and 'private' are used interchangably, as we don't really have actual symbols marked strictly private with double underscore.

Conventions on definitions

In addition, we have the following conventions:

  • 'public' functionality is considered stable and changes in name or behavior are considered breaking.
    • we intend to not do any breaking changes without a major version bump
      • therefore any such change within the same major version is either a bug or a bug fix
      • we will always communicate such changes
  • 'protected' or 'private' functionality is considered unstable and the behavior and names may change over time.
    • Using any such functionality is considered danger mode and the user is responsible for migrating and handling bugs that arise from it
  • any public symbol that lives in a private module (including public submodules of a private module) are considered private from the level of the private module

Note: in Python, nothing is truly private and anything can technically be publicly available if you really want it. However, there is an intentionality argument that says that we can treat protected and private symbols as such. Breaking with the intentionality of the functionality is danger mode.

Conventions on changes

  • Keep existing public symbols public, always; it's a one-way path
  • Keep private symbols private
  • Make new imports private as much as possible (rename if needed)
  • If you create a new module, either place it in the private _core module and/or make it private at least until it's stable
  • If you create a new symbol within a module, make it private at least until it's stable
  • If you have to make new public functionality, make sure to double-check; it's a one-way path
    • Make sure that the docstring is up-to-date
    • Make sure that the symbol is present in the API reference in the docs

Conventions in code

To make sure we maintain the intentionality across the code, we do the following tricks in the code base:

# safe importing modules
import module_a   # exposes publicly; only do this you know what you're doing
import _module_b  # reuse internally

# safe importing modules under a different name
import _module_b as _mod_b    # reuse internally
import module_a as _mod_a     # reuse internally under a new name

# unsafe importing modules; DON'T DO THIS, EVER!!!
import module_a as mod_a      # exposes as a new public symbol; weird
import _module_b as module_b  # exposes as a new public symbol; very dangerous

# unsafe reusing. BEWARE!!! this is a one-way path
from module_a import func_c    # exposes a public symbol from another module; usually bad practice
                               # because users may import from multiple files
from _module_b import func_d   # exposes a function from a private module publicly;
                               # useful when you want to prevent breaking changes now and in the future;
                               # only do this if if you know what you're doing

# unsafe reusing with renaming. BEWARE!!! this is a one-way path
from module_a import func_c as func_e   # expose a public symbol from another module under a different name;
                                        # why ever do this???
from _module_b import func_d as func_f  # expose a public symbol from a private module;
                                        # useful if the name in the private module does not suit this module

# unsafe exposing private functionality; DON'T DO THIS, EVER!!!
from module_a import _func_g as func_g   # expose a private symbol from another module
from _module_b import _func_h as func_h  # expose a public symbol from anot

# safe reusing and good practice; rename new private symbols as you see fit
from module_a import func_c as _func_g   # reuse a public symbol from another module;
from _module_b import func_d as _func_h  # reuse a public symbol from another private module;

# safe reusing but usually bad practice (unless in tests), but not harmful; change as you see fit
from module_a import _func_e              # reuse a private symbol from another module;
from _module_b import _func_f             # reuse a private symbol from another private module;
from module_a import _func_e as _func_g   # reuse a private symbol from another module;
from _module_b import _func_f as _func_h  # reuse a private symbol from another private module;

TODO

Try to find a way to make the module graph less convoluted by changing expositions. Make sure to follow the above conventions.

Feel free to create new private modules and private functions where necessary.

Relates to #869 .

@mgovers mgovers added the feature New feature or request label Jan 14, 2025
@mgovers mgovers added the good first issue Indicates a good issue for first-time contributors label Jan 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request good first issue Indicates a good issue for first-time contributors
Projects
Status: No status
Development

No branches or pull requests

1 participant