Skip to content

Python Projects

The Python project generator can be used to create a modern Python library or application configured with best practices, managed with UV, a single lockfile and virtual environment in an UV workspace, pytest for running tests, and Ruff for static analysis.

Usage

Generate a Python Project

You can generate a new Python project in two ways:

  1. Install the Nx Console VSCode Plugin if you haven't already
  2. Open the Nx Console in VSCode
  3. Click Generate (UI) in the "Common Nx Commands" section
  4. Search for @aws/nx-plugin - py#project
  5. Fill in the required parameters
    • Click Generate

    Options

    Parameter Type Default Description
    name required string - Project name.
    directory string packages Parent directory where the project is placed.
    projectType required string application Project type
    moduleName string - Python module name

    Generator Output

    The generator will create the following project structure in the <directory>/<name> directory:

    • Directory<module-name>
      • __init__.py Module initialisation
      • hello.py Example Python source file
    • Directorytests
      • __init__.py Module initialisation
      • conftest.py Test configuration
      • test_hello.py Example tests
    • project.json Project configuration and build targets
    • pyproject.toml Packaging configuration file used by UV
    • .python-version Contains the project’s Python version

    You may also notice the following files created/updated in the root of your workspace:

    • pyproject.toml Workspace level packaging configuration for UV
    • .python-version Contains the workspace Python version
    • uv.lock Lockfile for Python dependencies

    Writing Python Source Code

    Add your Python source code in the <module-name> directory.

    Importing your Library Code in Other Projects

    Since UV workspaces are set up for you, you can reference your Python project from any other Python project in your workspace:

    packages/my_other_project/my_other_project/main.py
    from "my_library.hello" import say_hello

    Above, my_library is the module name, hello corresponds to the Python source file hello.py, and say_hello is a method defined in hello.py

    Dependencies

    To add dependencies to your project, you can run the add target in your Python project, for example:

    Terminal window
    pnpm nx run my_scope.my_library:add some-pip-package

    This will add the dependency to your project’s pyproject.toml file, and update the root uv.lock.

    Runtime Code

    When you use your Python project as runtime code (for example as the handler for an AWS lambda function), you will need to create a bundle of the source code and all its dependencies. You can achieve this by adding a target such as the following to your project.json file:

    project.json
    {
    ...
    "targets": {
    ...
    "bundle": {
    "cache": true,
    "executor": "nx:run-commands",
    "outputs": ["{workspaceRoot}/dist/packages/my_library/bundle"],
    "options": {
    "commands": [
    "uv export --frozen --no-dev --no-editable --project my_library -o dist/packages/my_library/bundle/requirements.txt",
    "uv pip install -n --no-installer-metadata --no-compile-bytecode --python-platform x86_64-manylinux2014 --python `uv python pin` --target dist/packages/my_library/bundle -r dist/packages/my_library/bundle/requirements.txt"
    ],
    "parallel": false
    },
    "dependsOn": ["compile"]
    },
    },
    }

    Building

    Your Python project is configured with a build target (defined in project.json), which you can run via:

    Terminal window
    pnpm nx run <project-name>:build

    Where <project-name> is the fully qualified name of your project.

    The build target will compile, lint and test your project.

    Build output can be found in the root dist folder in your workspace, inside a directory for your package and target, for example dist/packages/<my-library>/build

    Testing

    pytest is configured for testing your project.

    Writing Tests

    Tests should be written in the test directory within your project, in python files prefixed with test_, for example:

    • Directorymy_library
      • hello.py
    • Directorytest
      • test_hello.py Tests for hello.py

    Tests are methods which begin with test_ and make assertions to verify expectations, for example:

    test/test_hello.py
    from my_library.hello import say_hello
    def test_say_hello():
    assert say_hello("Darth Vader") == "Hello, Darth Vader!"

    For more details about how to write tests, please refer to the pytest documentation.

    Running Tests

    Tests will run as part of the build target for your project, but you can also run them separately by running the test target:

    Terminal window
    pnpm nx run <project-name>:test

    You can run an individual test or suite of tests using the -k flag, specifying either the name of the test file or method:

    Terminal window
    pnpm nx run <project-name>:test -k 'test_say_hello'

    Linting

    Python projects use Ruff for linting.

    Running the Linter

    To invoke the linter to check your project, you can run the lint target.

    Terminal window
    pnpm nx run <project-name>:lint

    Fixing Lint Issues

    The majority of linting or formatting issues can be fixed automatically. You can tell Ruff to fix lint issues by running with the --configuration=fix argument.

    Terminal window
    pnpm nx run <project-name>:lint --configuration=fix

    Similarly if you would like to fix all lint issues in all packages in your workspace, you can run:

    Terminal window
    pnpm nx run-many --target lint --all --configuration=fix