Skip to content

Projects

albert.collections.projects

logger module-attribute

logger = create_logger()

AlbertHTTPError

AlbertHTTPError(response: Response)

Bases: AlbertException

Base class for all erors due to HTTP responses.

Source code in src/albert/exceptions.py
def __init__(self, response: requests.Response):
    message = self._format_message(response)
    super().__init__(message)
    self.response = response

response instance-attribute

response = response

AlbertPaginator

AlbertPaginator(
    *,
    path: str,
    mode: PaginationMode,
    session: AlbertSession,
    deserialize: Callable[
        [Iterable[dict]], Iterable[ItemType]
    ],
    params: dict[str, str] | None = None,
)

Bases: Iterator[ItemType]

Helper class for pagination through Albert endpoints.

Two pagination modes are possible: - Offset-based via by the offset query parameter - Key-based via by the startKey query parameter and 'lastKey' response field

A custom deserialize function is provided when additional logic is required to load the raw items returned by the search listing, e.g., making additional Albert API calls.

Source code in src/albert/core/pagination.py
def __init__(
    self,
    *,
    path: str,
    mode: PaginationMode,
    session: AlbertSession,
    deserialize: Callable[[Iterable[dict]], Iterable[ItemType]],
    params: dict[str, str] | None = None,
):
    self.path = path
    self.mode = mode
    self.session = session
    self.deserialize = deserialize

    params = params or {}
    self.params = {k: v for k, v in params.items() if v is not None}

    if "startKey" in self.params:
        self.params["startKey"] = quote_plus(self.params["startKey"])

    self._iterator = self._create_iterator()

deserialize instance-attribute

deserialize = deserialize

mode instance-attribute

mode = mode

params instance-attribute

params = {k: _ffor (k, v) in items() if v is not None}

path instance-attribute

path = path

session instance-attribute

session = session

AlbertSession

AlbertSession(
    *,
    base_url: str,
    token: str | None = None,
    auth_manager: AlbertClientCredentials
    | AlbertSSOClient
    | None = None,
    retries: int | None = None,
)

Bases: Session

A session that has a base URL, which is prefixed to all request URLs.

Parameters:

Name Type Description Default
base_url str

The base URL to prefix to all relative request paths (e.g., "https://app.albertinvent.com").

required
token str | None

A static JWT token for authentication. Ignored if auth_manager is provided.

None
auth_manager AlbertClientCredentials | AlbertSSOClient

An authentication manager used to dynamically fetch and refresh tokens. If provided, it overrides token.

None
retries int

The number of automatic retries on failed requests (default is 3).

None

Methods:

Name Description
request
Source code in src/albert/core/session.py
def __init__(
    self,
    *,
    base_url: str,
    token: str | None = None,
    auth_manager: AlbertClientCredentials | AlbertSSOClient | None = None,
    retries: int | None = None,
):
    super().__init__()
    self.base_url = base_url
    self.headers.update(
        {
            "Content-Type": "application/json",
            "Accept": "application/json",
            "User-Agent": f"albert-SDK V.{albert.__version__}",
        }
    )

    if token is None and auth_manager is None:
        raise ValueError("Either `token` or `auth_manager` must be specified.")

    self._auth_manager = auth_manager
    self._provided_token = token

    # Set up retry logic
    retries = retries if retries is not None else 3
    retry = Retry(
        total=retries,
        read=retries,
        connect=retries,
        backoff_factor=0.3,
        status_forcelist=(500, 502, 503, 504, 403),
        raise_on_status=False,
    )
    adapter = HTTPAdapter(max_retries=retry)
    self.mount("http://", adapter)
    self.mount("https://", adapter)

base_url instance-attribute

base_url = base_url

request

request(
    method: str, path: str, *args, **kwargs
) -> Response
Source code in src/albert/core/session.py
def request(self, method: str, path: str, *args, **kwargs) -> requests.Response:
    self.headers["Authorization"] = f"Bearer {self._access_token}"
    full_url = urljoin(self.base_url, path) if not path.startswith("http") else path
    with handle_http_errors():
        response = super().request(method, full_url, *args, **kwargs)
        response.raise_for_status()
        return response

BaseCollection

BaseCollection(*, session: AlbertSession)

BaseCollection is the base class for all collection classes.

Parameters:

Name Type Description Default
session AlbertSession

The Albert API Session instance.

required
Source code in src/albert/collections/base.py
def __init__(self, *, session: AlbertSession):
    self.session = session

session instance-attribute

session = session

PaginationMode

Bases: str, Enum

KEY class-attribute instance-attribute

KEY = 'key'

OFFSET class-attribute instance-attribute

OFFSET = 'offset'

Project

Bases: BaseResource

A project in Albert.

Attributes:

Name Type Description
description str

The description of the project. Used as the name of the project as well.

id str | None

The Albert ID of the project. Set when the project is retrieved from Albert.

locations list[Location] | None

The locations associated with the project. Optional.

project_class ProjectClass

The class of the project. Defaults to PRIVATE.

metadata dict[str, str | list[EntityLink] | EntityLink] | None

The metadata of the project. Optional. Metadata allowed values can be found using the Custom Fields API.

prefix str | None

The prefix of the project. Optional.

acl list[ACL] | None

The ACL of the project. Optional.

task_config list[TaskConfig] | None

The task configuration of the project. Optional.

grid GridDefault | None

The default grid of the project. Optional.

state State | None

The state/status of the project. Allowed states are customizeable using the entitystatus API. Optional.

application_engineering_inventory_ids list[str] | None

Inventory Ids to be added as application engineering. Optional.

Methods:

Name Description
validate_status

Somehow, some statuses are capitalized in the API response. This ensures they are always lowercase.

acl class-attribute instance-attribute

acl: list[ACL] | None = Field(
    default_factory=list, alias="ACL"
)

application_engineering_inventory_ids class-attribute instance-attribute

application_engineering_inventory_ids: list[str] | None = (
    Field(
        default=None,
        alias="appEngg",
        description="Inventory Ids to be added as application engineering",
    )
)

description class-attribute instance-attribute

description: str = Field(min_length=1, max_length=2000)

grid class-attribute instance-attribute

grid: GridDefault | None = None

id class-attribute instance-attribute

id: ProjectId | None = Field(None, alias='albertId')

locations class-attribute instance-attribute

locations: list[SerializeAsEntityLink[Location]] | None = (
    Field(
        default=None,
        min_length=1,
        max_length=20,
        alias="Locations",
    )
)

metadata class-attribute instance-attribute

metadata: dict[str, MetadataItem] | None = Field(
    alias="Metadata", default=None
)

old_api_params class-attribute instance-attribute

old_api_params: dict | None = None

prefix class-attribute instance-attribute

prefix: str | None = Field(default=None)

project_class class-attribute instance-attribute

project_class: ProjectClass | None = Field(
    default=PRIVATE, alias="class"
)

state class-attribute instance-attribute

state: State | None = Field(default=None, exclude=True)

status class-attribute instance-attribute

status: str | None = Field(
    default=None, exclude=True, frozen=True
)

task_config class-attribute instance-attribute

task_config: list[TaskConfig] | None = Field(
    default_factory=list
)

validate_status

validate_status(value)

Somehow, some statuses are capitalized in the API response. This ensures they are always lowercase.

Source code in src/albert/resources/projects.py
@field_validator("status", mode="before")
def validate_status(cls, value):
    """Somehow, some statuses are capitalized in the API response. This ensures they are always lowercase."""
    if isinstance(value, str):
        return value.lower()
    return value

ProjectCollection

ProjectCollection(*, session: AlbertSession)

Bases: BaseCollection

ProjectCollection is a collection class for managing Project entities in the Albert platform.

Parameters:

Name Type Description Default
session AlbertSession

The Albert session instance.

required

Methods:

Name Description
create

Create a new project.

delete

Delete a project by its ID.

get_all

Retrieve fully hydrated Project entities with optional filters.

get_by_id

Retrieve a project by its ID.

search

Search for Project matching the provided criteria.

update

Update a project.

Source code in src/albert/collections/projects.py
def __init__(self, *, session: AlbertSession):
    """
    Initialize a ProjectCollection object.

    Parameters
    ----------
    session : AlbertSession
        The Albert session instance.
    """
    super().__init__(session=session)
    self.base_path = f"/api/{ProjectCollection._api_version}/projects"

base_path instance-attribute

base_path = f'/api/{_api_version}/projects'

create

create(*, project: Project) -> Project

Create a new project.

Parameters:

Name Type Description Default
project Project

The project to create.

required

Returns:

Type Description
Optional[Project]

The created project object if successful, None otherwise.

Source code in src/albert/collections/projects.py
def create(self, *, project: Project) -> Project:
    """
    Create a new project.

    Parameters
    ----------
    project : Project
        The project to create.

    Returns
    -------
    Optional[Project]
        The created project object if successful, None otherwise.
    """
    response = self.session.post(
        self.base_path, json=project.model_dump(by_alias=True, exclude_unset=True, mode="json")
    )
    return Project(**response.json())

delete

delete(*, id: str) -> None

Delete a project by its ID.

Parameters:

Name Type Description Default
id str

The ID of the project to delete.

required

Returns:

Type Description
None
Source code in src/albert/collections/projects.py
def delete(self, *, id: str) -> None:
    """
    Delete a project by its ID.

    Parameters
    ----------
    id : str
        The ID of the project to delete.

    Returns
    -------
    None
    """
    url = f"{self.base_path}/{id}"
    self.session.delete(url)

get_all

get_all(
    *, params: ProjectFilterParams | None = None
) -> Iterator[Project]

Retrieve fully hydrated Project entities with optional filters.

This method returns complete entity data using get_by_id. Use :meth:search for faster retrieval when you only need lightweight, partial (unhydrated) entities.

Parameters:

Name Type Description Default
params ProjectFilterParams

Structured query parameters to filter, sort, and paginate projects.

None

Returns:

Type Description
Iterator[Project]

An iterator of fully hydrated Project entities.

Source code in src/albert/collections/projects.py
def get_all(self, *, params: ProjectFilterParams | None = None) -> Iterator[Project]:
    """Retrieve fully hydrated Project entities with optional filters.

    This method returns complete entity data using `get_by_id`.
    Use :meth:`search` for faster retrieval when you only need lightweight, partial (unhydrated) entities.

    Parameters
    ----------
    params : ProjectFilterParams, optional
        Structured query parameters to filter, sort, and paginate projects.

    Returns
    -------
    Iterator[Project]
        An iterator of fully hydrated Project entities.
    """
    params = params or ProjectFilterParams()

    for project in self.search(params=params):
        project_id = getattr(project, "albertId", None) or getattr(project, "id", None)
        if not project_id:
            continue

        id = project_id if project_id.startswith("PRO") else f"PRO{project_id}"

        try:
            yield self.get_by_id(id=id)
        except AlbertHTTPError as e:
            logger.warning(f"Error fetching project details {id}: {e}")

get_by_id

get_by_id(*, id: str) -> Project

Retrieve a project by its ID.

Parameters:

Name Type Description Default
id str

The ID of the project to retrieve.

required

Returns:

Type Description
Project

The project object if found

Source code in src/albert/collections/projects.py
def get_by_id(self, *, id: str) -> Project:
    """
    Retrieve a project by its ID.

    Parameters
    ----------
    id : str
        The ID of the project to retrieve.

    Returns
    -------
    Project
        The project object if found
    """
    url = f"{self.base_path}/{id}"
    response = self.session.get(url)

    return Project(**response.json())

search

search(
    *, params: ProjectFilterParams | None = None
) -> Iterator[ProjectSearchItem]

Search for Project matching the provided criteria.

⚠️ This method returns partial (unhydrated) entities to optimize performance. To retrieve fully detailed entities, use :meth:get_all instead.

Parameters:

Name Type Description Default
params ProjectFilterParams

Structured query parameters to filter, sort, and paginate projects.

None

Returns:

Type Description
Iterator[Project]

An iterator of Project resources.

Source code in src/albert/collections/projects.py
def search(self, *, params: ProjectFilterParams | None = None) -> Iterator[ProjectSearchItem]:
    """Search for Project matching the provided criteria.

    ⚠️ This method returns partial (unhydrated) entities to optimize performance.
    To retrieve fully detailed entities, use :meth:`get_all` instead.

    Parameters
    ----------
    params : ProjectFilterParams, optional
        Structured query parameters to filter, sort, and paginate projects.

    Returns
    -------
    Iterator[Project]
        An iterator of Project resources.
    """
    params = params or ProjectFilterParams()

    query_params = {
        "limit": params.limit,
        "order": params.order_by.value,
        "text": params.text,
        "sortBy": params.sort_by,
        "status": params.status,
        "marketSegment": params.market_segment,
        "application": params.application,
        "technology": params.technology,
        "createdBy": params.created_by,
        "location": params.location,
        "fromCreatedAt": params.from_created_at,
        "toCreatedAt": params.to_created_at,
        "facetField": params.facet_field,
        "facetText": params.facet_text,
        "containsField": params.contains_field,
        "containsText": params.contains_text,
        "linkedTo": params.linked_to,
        "myProjects": params.my_projects,
        "myRole": params.my_role,
    }

    return AlbertPaginator(
        mode=PaginationMode.OFFSET,
        path=f"{self.base_path}/search",
        session=self.session,
        params=query_params,
        deserialize=lambda items: [
            ProjectSearchItem(**item)._bind_collection(self) for item in items
        ],
    )

update

update(*, project: Project) -> Project

Update a project.

Parameters:

Name Type Description Default
project Project

The updated project object.

required

Returns:

Type Description
Project

The updated project object as returned by the server.

Source code in src/albert/collections/projects.py
def update(self, *, project: Project) -> Project:
    """Update a project.

    Parameters
    ----------
    project : Project
        The updated project object.

    Returns
    -------
    Project
        The updated project object as returned by the server.
    """
    existing_project = self.get_by_id(id=project.id)
    patch_data = self._generate_patch_payload(existing=existing_project, updated=project)
    url = f"{self.base_path}/{project.id}"

    self.session.patch(url, json=patch_data.model_dump(mode="json", by_alias=True))

    return self.get_by_id(id=project.id)

ProjectFilterParams pydantic-model

Bases: BaseAlbertModel

Filtering and query parameters for retrieving Projects via search() or get_all().

This model centralizes all supported filters, sorting, and pagination options. It is used to construct query payloads for partial or fully hydrated project listings.

Show JSON schema:
{
  "$defs": {
    "OrderBy": {
      "enum": [
        "desc",
        "asc"
      ],
      "title": "OrderBy",
      "type": "string"
    }
  },
  "description": "Filtering and query parameters for retrieving Projects via `search()` or `get_all()`.\n\nThis model centralizes all supported filters, sorting, and pagination options.\nIt is used to construct query payloads for partial or fully hydrated project listings.",
  "properties": {
    "text": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Full-text search across multiple fields of the project.",
      "title": "Text"
    },
    "status": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "List of project statuses to filter by.",
      "title": "Status"
    },
    "market_segment": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Market segments to include in the result set.",
      "title": "Market Segment"
    },
    "application": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Application types associated with the projects.",
      "title": "Application"
    },
    "technology": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Technology tags used in the projects.",
      "title": "Technology"
    },
    "created_by": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Filter projects created by specific users.",
      "title": "Created By"
    },
    "location": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Geographic or facility locations for the projects.",
      "title": "Location"
    },
    "from_created_at": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Lower bound of project creation date (inclusive), formatted as 'YYYY-MM-DD'.",
      "title": "From Created At"
    },
    "to_created_at": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Upper bound of project creation date (inclusive), formatted as 'YYYY-MM-DD'.",
      "title": "To Created At"
    },
    "facet_field": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Field name for facet search (e.g., status, application).",
      "title": "Facet Field"
    },
    "facet_text": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Text to match within the given facet field.",
      "title": "Facet Text"
    },
    "contains_field": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "List of fields to check for specific content (used in advanced filters).",
      "title": "Contains Field"
    },
    "contains_text": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Text snippets to search for within the specified `contains_field`.",
      "title": "Contains Text"
    },
    "linked_to": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional ID or label to find projects linked to a specific entity (e.g., in Task creation).",
      "title": "Linked To"
    },
    "my_projects": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "If True, return only projects owned by the authenticated user.",
      "title": "My Projects"
    },
    "my_role": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Roles the user has in projects to filter (e.g., Lead, Reviewer).",
      "title": "My Role"
    },
    "order_by": {
      "$ref": "#/$defs/OrderBy",
      "default": "desc",
      "description": "Ordering of results, either ascending or descending."
    },
    "sort_by": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Field to sort by (e.g., createdAt, updatedAt, name).",
      "title": "Sort By"
    },
    "limit": {
      "default": 50,
      "description": "Maximum number of items to return (default is 50, max is 1000).",
      "maximum": 1000,
      "minimum": 1,
      "title": "Limit",
      "type": "integer"
    }
  },
  "title": "ProjectFilterParams",
  "type": "object"
}

Fields:

application pydantic-field

application: list[str] | None = None

Application types associated with the projects.

contains_field pydantic-field

contains_field: list[str] | None = None

List of fields to check for specific content (used in advanced filters).

contains_text pydantic-field

contains_text: list[str] | None = None

Text snippets to search for within the specified contains_field.

created_by pydantic-field

created_by: list[str] | None = None

Filter projects created by specific users.

facet_field pydantic-field

facet_field: str | None = None

Field name for facet search (e.g., status, application).

facet_text pydantic-field

facet_text: str | None = None

Text to match within the given facet field.

from_created_at pydantic-field

from_created_at: str | None = None

Lower bound of project creation date (inclusive), formatted as 'YYYY-MM-DD'.

limit pydantic-field

limit: int = 50

Maximum number of items to return (default is 50, max is 1000).

linked_to pydantic-field

linked_to: str | None = None

Optional ID or label to find projects linked to a specific entity (e.g., in Task creation).

location pydantic-field

location: list[str] | None = None

Geographic or facility locations for the projects.

market_segment pydantic-field

market_segment: list[str] | None = None

Market segments to include in the result set.

my_projects pydantic-field

my_projects: bool | None = None

If True, return only projects owned by the authenticated user.

my_role pydantic-field

my_role: list[str] | None = None

Roles the user has in projects to filter (e.g., Lead, Reviewer).

order_by pydantic-field

order_by: OrderBy = DESCENDING

Ordering of results, either ascending or descending.

sort_by pydantic-field

sort_by: str | None = None

Field to sort by (e.g., createdAt, updatedAt, name).

status pydantic-field

status: list[str] | None = None

List of project statuses to filter by.

technology pydantic-field

technology: list[str] | None = None

Technology tags used in the projects.

text pydantic-field

text: str | None = None

Full-text search across multiple fields of the project.

to_created_at pydantic-field

to_created_at: str | None = None

Upper bound of project creation date (inclusive), formatted as 'YYYY-MM-DD'.

ProjectSearchItem pydantic-model

Bases: BaseAlbertModel, HydrationMixin[Project]

Show JSON schema:
{
  "properties": {
    "albertId": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Albertid"
    },
    "description": {
      "maxLength": 2000,
      "minLength": 1,
      "title": "Description",
      "type": "string"
    },
    "status": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Status"
    }
  },
  "required": [
    "description"
  ],
  "title": "ProjectSearchItem",
  "type": "object"
}

Fields:

description pydantic-field

description: str

id pydantic-field

id: ProjectId | None = None

status pydantic-field

status: str | None = None