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:
- Install the Nx Console VSCode Plugin if you haven't already
- Open the Nx Console in VSCode
- Click
Generate (UI)
in the "Common Nx Commands" section - Search for
@aws/nx-plugin - py#project
- Fill in the required parameters
- Click
Generate
pnpm nx g @aws/nx-plugin:py#project
yarn nx g @aws/nx-plugin:py#project
npx nx g @aws/nx-plugin:py#project
bunx nx g @aws/nx-plugin:py#project
You can also perform a dry-run to see what files would be changed
pnpm nx g @aws/nx-plugin:py#project --dry-run
yarn nx g @aws/nx-plugin:py#project --dry-run
npx nx g @aws/nx-plugin:py#project --dry-run
bunx nx g @aws/nx-plugin:py#project --dry-run
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:
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:
pnpm nx run my_scope.my_library:add some-pip-package
yarn nx run my_scope.my_library:add some-pip-package
npx nx run my_scope.my_library:add some-pip-package
bunx 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:
{ ... "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:
pnpm nx run <project-name>:build
yarn nx run <project-name>:build
npx nx run <project-name>:build
bunx 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:
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:
pnpm nx run <project-name>:test
yarn nx run <project-name>:test
npx nx run <project-name>:test
bunx 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:
pnpm nx run <project-name>:test -k 'test_say_hello'
yarn nx run <project-name>:test -k 'test_say_hello'
npx nx run <project-name>:test -k 'test_say_hello'
bunx 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.
pnpm nx run <project-name>:lint
yarn nx run <project-name>:lint
npx nx run <project-name>:lint
bunx 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.
pnpm nx run <project-name>:lint --configuration=fix
yarn nx run <project-name>:lint --configuration=fix
npx nx run <project-name>:lint --configuration=fix
bunx 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:
pnpm nx run-many --target lint --all --configuration=fix
yarn nx run-many --target lint --all --configuration=fix
npx nx run-many --target lint --all --configuration=fix
bunx nx run-many --target lint --all --configuration=fix