rats.projects
¶
Interact with the various components in the repository during development.
A project is loosely tied to one repository, which is made up of one or more components. Each component is a separate entity that can be built, tested, and released independently. This module provides a handful of convenience APIs to query for project and component information, along with exposing a few methods to run commands within the context of a component's development environment. It's common for python environments to be misconfigured, and as we run commands in multiple components, it's easy to accidentally run commands in a component with the wrong virtual environment being activated, with unpredictable results. The libraries in this module try to alleviate some of these pain points while trying to remain agnostic of env management tools and other component specific choices.
Warning
Python environments are never trivial to manage, and are a common source of complexity because of the many ways to define your development environment. We've tested the functionality in this module heavily for the set of tools we use to develop rats, but some of the contained functionality might not work fully within components that use a different set of tool, like conda.
__all__ = ['ComponentId', 'ComponentNotFoundError', 'ComponentTools', 'PluginConfigs', 'PluginContainer', 'PluginServices', 'ProjectConfig', 'ProjectNotFoundError', 'ProjectTools', 'UnsetComponentTools', 'find_nearest_component', 'find_repo_root']
module-attribute
¶
ComponentId
¶
Bases: NamedTuple
A simple wrapper around the name of a component, for typing convenience.
name
instance-attribute
¶
ComponentTools(path)
¶
A small collection of operations commonly done on components.
This class might contain unrelated things like poetry and docker specific methods that we can hopefully move to better components in the future.
Source code in src/rats/projects/_component_tools.py
component_name()
¶
symlink(src, dst)
¶
Create a symlink in the component directory.
The destination path must be relative to the component directory.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
src
|
Path
|
the existing file or directory to link to |
required |
dst
|
Path
|
the symlink path to be created |
required |
Source code in src/rats/projects/_component_tools.py
copy(src, dst)
¶
Copy a file into the component.
The destination path must be relative to the component directory.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
src
|
Path
|
the existing file to copy |
required |
dst
|
Path
|
the destination of the copied file |
required |
Source code in src/rats/projects/_component_tools.py
copy_tree(src, dst)
¶
Copy a directory into the component.
The destination path must be relative to the component directory.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
src
|
Path
|
the existing directory to copy |
required |
dst
|
Path
|
the destination of the copied directory |
required |
Source code in src/rats/projects/_component_tools.py
create_or_empty(directory)
¶
Ensure a directory in the component exists and is empty.
find_path(name)
¶
Given a path, relative to the root of the component, return the full path.
All paths are expected to be within the directory of the component.
Source code in src/rats/projects/_component_tools.py
pytest()
¶
ruff(*args)
¶
pyright()
¶
poetry(*args)
¶
Source code in src/rats/projects/_component_tools.py
run(*args)
¶
Tries to run a command within the component's venv.
Source code in src/rats/projects/_component_tools.py
exe(*cmd)
¶
Run a command from the root of a component.
Source code in src/rats/projects/_component_tools.py
is_poetry_detected()
¶
Returns true if we think this component might be managed by poetry.
Since PEP 621 is gaining adoption, including by poetry, we should be able to remove most of the complexity in trying to parse details out of pyproject.toml. This method is here until we can fully delete any non PEP 621 code since we initially started as poetry-specific.
Source code in src/rats/projects/_component_tools.py
UnsetComponentTools(path)
¶
Bases: ComponentTools
A stub component tools without any implemented operations.
All methods within this class raise a NotImplementedError
.
Source code in src/rats/projects/_component_tools.py
PluginConfigs
¶
Configurable services within the rats.projects module.
PROJECT = apps.ServiceId[ProjectConfig]('project')
class-attribute
instance-attribute
¶
Main config object to change the behavior of rats.projects libraries.
PluginContainer(app)
¶
PluginServices
¶
Services made available from the [rats.projects] module.
CWD_COMPONENT_TOOLS = apps.ServiceId[ComponentTools]('cwd-component-tools')
class-attribute
instance-attribute
¶
The component tools instance for the component the command was run within.
PROJECT_TOOLS = apps.ServiceId[ProjectTools]('project-tools')
class-attribute
instance-attribute
¶
Main project library to interact with the repository and the contained components.
CONFIGS = PluginConfigs
class-attribute
instance-attribute
¶
Alias to the rats.projects.ProjectConfig class.
ComponentNotFoundError
¶
Bases: ValueError
ProjectConfig
¶
Bases: NamedTuple
Settings used by the rats.projects.ProjectTools libraries.
name
instance-attribute
¶
The name of your project.
In monorepos, this is typically the name of the repository. In single-component repositories, we generally expect the name of the repo to match the name of the component/package.
path
instance-attribute
¶
The path to the root of the project.
image_registry
instance-attribute
¶
The name of the container image registry built images will be tagged with.
image_push_on_build
instance-attribute
¶
When enabled, images are automatically pushed to the defined registry when built.
image_tag = None
class-attribute
instance-attribute
¶
The version tag of the container image built images will be tagged with.
ProjectNotFoundError
¶
Bases: ValueError
ProjectTools(config)
¶
Small collection of methods to operate on the project and access component tools.
A config is required to specify the behavior of this instance.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
config
|
apps.Provider[ProjectConfig]
|
the configuration of the project we are operating within. |
required |
Source code in src/rats/projects/_project_tools.py
build_component_images()
¶
Sequentially builds container images for every component in the project.
build_component_image(name)
¶
Builds the container image for a given component in the project.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
the name of the component to be built. |
required |
Source code in src/rats/projects/_project_tools.py
container_image(name)
¶
Get the calculated container image for the given component.
If a tag is not present in the rats.projects.ProjectConfig, one is calculated using rats.projects.ProjectTools.image_context_hash.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
the name of the component for which we want the image. |
required |
Source code in src/rats/projects/_project_tools.py
image_context_hash()
cached
¶
Calculates a hash based on all the files available to the container build context.
The hash is calculated by ignoring all files selected by .gitignore
configs, and hashing
all remaining files from the root of the project, giving us a unique hash of all possible
contents that can be copied into an image.
Source code in src/rats/projects/_project_tools.py
image_context_manifest()
cached
¶
Calculates a manifest of the files in the image context.
When building container images, this hash can be used to determine if any of the files in the image might have changed. This manifest is used by methods like rats.projects.ProjectTools.image_context_hash.
Inspired by https://github.com/5monkeys/docker-image-context-hash-action
Source code in src/rats/projects/_project_tools.py
project_name()
¶
The name of the project, as defined by the provided rats.projects.ProjectConfig.
discover_components()
cached
¶
Looks through the code base for any components containing a pyproject.toml
file.
get_component(name)
¶
Get the component tools for a given component.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
the name of the component within the project. |
required |
Source code in src/rats/projects/_project_tools.py
repo_root()
¶
The path to the root of the repository.
Source code in src/rats/projects/_project_tools.py
find_nearest_component(cwd=None)
¶
Try to find the path to the root of the nearest component.
This method traverses up the directory tree, starting from the working directory, and looks for
the first directory that contains a pyproject.toml
file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
cwd
|
Path | None
|
optionally provide a starting search directory |
None
|
Source code in src/rats/projects/_plugin.py
find_repo_root(cwd=None)
¶
Try to find the path to the root of the repo.
This method traverses up the directory tree, starting from the working directory, and looks for
the first directory that contains a .git
directory. This behavior can be overwritten by
defining a DEVTOOLS_PROJECT_ROOT
environment variable.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
cwd
|
Path | None
|
optionally provide a starting search directory |
None
|