Skip to content

Establish Rules for Dependencies Between Your Packages

If you're working on a bigger and more complex application, you probably follow some structure and organize your code into packages. In that case, it might make sense to establish some rules how these packages communicate with each other.

Here are some ideas that might make sense depending on your project's structure:

  • The api package can depend on any other package. But no other package in your project should depend on api.
  • Only the api package should use the api_utils package.
  • Only the core package should use the db package.

Establish Rules for Dependencies Between Your Packages with Sourcery Custom Rules

Currently, you need to define 2 Sourcery custom rules to flag various ways of dependency. 1 flags import statements and 1 flags from ... import statements.

Here is an example to flag all the cases when another package in your project depends on api:

rules:
  - id: no-dependency-api-import
    description: Do not import the `api` library in other packages
    pattern: import ..., ${module}, ...
    condition: module.matches_regex(r"^api\b")
    paths:
      exclude:
        - api/
        - test/
    tests:
      - match: import api
      - match: import api.auth
      - match: import api as my_api
      - match: import api.auth as api_auth
      - match: import json, api, datetime
      - no-match: import apiness

  - id: no-dependency-api-from
    description: Do not import the `api` library in other packages
    pattern: from ${module} import ...
    condition: module.matches_regex(r"^api\b")
    paths:
      exclude:
        - api/
        - test/
    tests:
      - match: from api import util
      - match: from api import util, auth
      - match: from api.whatever import SomeApiStuff
      - match: from api.level.other import util, other
      - match: from api import util as u, auth as a
      - match: from api import *
      - match: from api.books import *
      - no-match: from apiness import util
      - no-match: from api2 import util

Out of Scope

Please note that these rules find only direct references to a library in import and from ... import statements. The following is out of scope:

  • reimporting imported names
  • __import__ built-in function
  • importlib
  • import statements importing multiple packages

General Import Conventions

We recommend to follow some conventions for imports. That makes your code easier to read for humans and easier to work with for tools.

  • Do not use relative imports.
  • Use isort