Skip to content

pda.Project

Project(document: 'Document') -> 'None'

Live view of a PDA project or library document.

MethodDescription
addAdd an object and any missing dependencies to the project.
add_libraryAttach a versioned library and its dependencies to the project.
add_module_fileCopy a Python file into the project module, save it, and import it.
add_tagAttach a tag to the project or a specific contained object.
add_versionAdd a version to the project or one object in it, and tag its files.
attachUpload a file and attach it to the project or one of its objects.
attach_queryAttach a pointer to rows held somewhere else.
attachment_statusReport what the project holds and where its gaps are.
attachmentsList attachments bound to the project or one of its objects.
changed_sinceThe saves made after mark: empty, and so falsy, when there were none.
check_accessCheck if the current user can access this project.
componentOne component, by the name it has in the project.
componentsQuery components by exact name, regex, and origin scope.
detachRemove an attachment from the project or one of its components.
download_attachmentDownload the binary content of an attachment.
edit_logEvery save to one document, oldest first, including unversioned ones.
get_infoReturn metadata for the project or one contained object.
get_library_infoReturn metadata for one library or all imported libraries.
grant_permissionGrant access permissions for the project document.
import_moduleImport the project and library Python modules.
latest_headWhere a document stands now: the id of its newest save.
list_permissionsList sharing permissions for the project document.
list_tagsReturn available tags for the project or one contained object.
list_versionsReturn available versions for the project or one contained object.
loadLoad a tagged/versioned snapshot of a project object.
load_latestBring this copy of the project up to date with everyone’s saves.
load_queryRead a pointer back off its attachment.
remove_tagRemove one or more tags from the selected target.
restoreRestore retired technologies/components by name.
retireRetire technologies/components by object instance or name.
retire_unusedRetire project-owned internal components unused by external ones.
revoke_permissionRevoke one permission by its identifier.
run_queryRead the rows a pointer names, through a connection you opened.
save_modulePack the loaded module directory and store it in PDA.
setUpdate editable project fields in-place.
set_externalSet/unset a component as external in the module mapping.
technologiesQuery technologies by exact name, regex, and origin scope.
technologyOne technology, by name, as component finds a component.
traceWalk an attached file back to the design it describes.
traceability_matrixWhich file belongs to which version: a row per file, a column per version.
transfer_ownershipTransfer project ownership to another user identifier.
treeWhat is in the project, as a tree.
updateUpdate an existing project object and optional dependencies.
update_permissionChange the role associated with an existing permission.
version_historyThe numbered versions and tags of the project or one object in it.
watchCall on_change whenever a save to this document reaches you.

add(
self,
new_obj: 'Component | Technology',
*,
tag: 'str | None' = None,
bump_version: "Literal['major', 'minor', 'patch'] | None" = None,
update_existing_dependencies: 'bool' = True,
update_config: 'bool' = True,
project_tag: 'str | None' = '{name}-{version_and_tag}',
set_external: 'bool' = True,
) -> "dict[Literal['added', 'updated'], list[Technology | Component]]"

Add an object and any missing dependencies to the project.

Args

  • new_obj: Component or technology to add.
  • tag: Optional tag applied to changed objects.
  • bump_version: Optional semantic bump for changed objects.
  • update_existing_dependencies: Whether existing dependencies may be updated.
  • update_config: Whether to update project config from current settings.
  • project_tag: If either tag or bump_version is not None, tag to the project using this template, with name, version, tag, version_and_tag and datetime fields. The name is trimmed to keep the tag within the server’s limit, and a label the project already carries is reported, not fatal.
  • set_external: Whether to mark this component to be external in the module pda_components mapping. Dependencies are never marked.

Returns

Mapping with added and updated object lists.

add_library(
self,
name: 'str | None' = None,
*,
version: 'str | None' = None,
library_id: 'str | None' = None,
) -> 'object'

Attach a versioned library and its dependencies to the project.

Args

  • name: Library project name when selecting by name/version.
  • version: Library version when selecting by name/version.
  • library_id: Specific library version record ID.

Returns

None.

add_module_file(self, path: 'str | Path') -> 'ModuleType'

Copy a Python file into the project module, save it, and import it.

A parametric component or technology is Python code, and a component built from code that lives only on your machine can be opened by a colleague but not changed. This puts the file in the project’s code folder, re-exports its parametric_component and parametric_technology functions from the project module, uploads the module, and imports it here. Adding the same file again replaces the code. A file with no such function is added too, for the helpers the others import.

>>> bend = project.add_module_file("bend.py") # doctest: +SKIP
>>> project.add(bend.waveguide_bend(radius=3.0)) # doctest: +SKIP

A colleague gets the code with load_latest and import_module. It runs on import, for everyone.

Args

  • path: A .py file with a plain name, like bend.py. A path inside the module folder is fine: the file is already in place.

Returns

The imported submodule, project_module.<name>. A handle from before the next reload is stale; take a fresh one from import_module.

Raises

  • RuntimeError: The project is read only, has no module loaded, or its code changed on the server since this copy was loaded; call load_latest first, so nobody else’s file is overwritten.
  • ValueError: The name is reserved, or the file exports a function another file already exports.

add_tag(
self,
tag: 'str',
*,
target: 'Component | Technology | str | None' = None,
) -> 'Component | Technology | Project'

Attach a tag to the project or a specific contained object.

Args

  • tag: Tag label to create.
  • target: Optional target object or name. Defaults to project.

Returns

Target object that received the tag.

add_version(
self,
version: 'str | None' = None,
bump_version: "Literal['major', 'minor', 'patch'] | None" = None,
*,
target: 'Component | Technology | str | None' = None,
message: 'str | None' = None,
tag_prefix: 'str | None' = 'version:',
) -> 'Version'

Add a version to the project or one object in it, and tag its files.

A version freezes the document. It does not freeze the list of attachments, because an attachment is a row bound to a document id and a row has no history for a version to pin. So this also writes <tag_prefix><version> onto every attachment on the target that does not already claim one; that tag is what trace and attachment_status read back. Nor does an object’s version pin the rest of the design, so the project’s own pinned ref is recorded with it; load and trace rebuild the whole design from that.

Args

  • version: Explicit version string.
  • bump_version: Bump strategy when version is omitted.
  • target: Object or name to version. Defaults to the project.
  • message: Message recorded with the version, at most 1000 characters. A server that does not record one ignores it; nothing is written elsewhere to compensate, because a tag and a message are different things.
  • tag_prefix: Prefix of the tag written onto the attachments; None leaves them untouched.

Returns

A Version mapping naming the version, and which attachments were stamped, skipped or failed.

Note

Stamping is not atomic, on purpose. A failed stamp leaves the version in place and is reported in Version.failed; calling again with that same explicit version stamps what is left and warns that the version already existed, rather than failing on it. With tag_prefix=None an existing version is an error.

attach(
self,
path: 'str | Path',
*,
target: 'Component | Technology | str | None' = None,
filename: 'str | None' = None,
tags: 'Sequence[str]' = (),
) -> 'dict[str, object]'

Upload a file and attach it to the project or one of its objects.

The file is uploaded and bound to the target document on the server, which grants read access to anyone with access to that document. The binding is the association: nothing is stored in the document itself.

Args

  • path: Path to the file to upload.
  • target: Component or technology (object or name) to attach to; None (default) attaches to the project itself.
  • filename: Optional file name override (defaults to the path name).
  • tags: Optional tags stored on the attachment. Use a tag convention (e.g. “design_manual”, “drc_ruleset”, “cross_section”, “gds”) to categorize attachments and filter them with attachments(tags=).

Returns

Attachment metadata for the uploaded file.

attach_query(
self,
*,
target: 'Component | Technology | str',
table: 'str',
source: 'str',
fixed: 'Mapping[str, object] | None' = None,
filterable: 'Sequence[str]' = (),
columns: 'Sequence[str]' = (),
units: 'Mapping[str, str] | None' = None,
schema: 'str | None' = None,
row_count: 'int | None' = None,
captured_version: 'str | None' = None,
filename: 'str | None' = None,
tags: 'Sequence[str]' = (),
) -> 'BoundQuery'

Attach a pointer to rows held somewhere else.

Measurement data is structured and large; attachments are opaque files. Rather than copy millions of rows into the project, this stores where they are: which table or view, which rows it is always about, and which column a reader may narrow on.

>>> pointer = project.attach_query( # doctest: +SKIP
... target="grating", # the design the rows describe
... source="lab database", # a label for where the rows live
... table="spectra_with_run", # the table or view to read
... fixed={"serial": "GC-01"}, # always these rows
... filterable=["run_id"], # a reader may narrow by run
... )

No SQL is stored. The only statement run_query composes is SELECT <columns> FROM <table> WHERE <column> = <value> AND ..., with identifiers quoted and values bound for the caller’s own driver. Put a join or an aggregate in a database view and point at the view.

Args

  • target: The design the rows describe.
  • table: Table or view to read. A plain identifier.
  • source: A label for the system holding the rows, for a reader. Nothing checks the connection against it.
  • fixed: Values this pointer is always about, as {column: value}, such as the device serial. A reader cannot change them.
  • filterable: Columns a reader may narrow on with run_query(where=...). One the reader leaves unset narrows nothing.
  • columns: Columns to return. Empty (default) returns every column.
  • units: Optional column-to-unit map, for whoever plots the result.
  • schema: Optional namespace for table.
  • row_count: Row count when the pointer was written, as a sanity check.
  • captured_version: Version the pointer was captured against.
  • filename: Attachment name. Defaults to one built from table and fixed, so two pointers on one design do not collide.
  • tags: Extra tags, alongside dataset_pointer.

Returns

A BoundQuery.

Note

No credential is stored. run_query takes a live connection that the caller opens.

attachment_status(
self,
*,
version: 'str | None' = None,
tag_prefix: 'str' = 'version:',
include_empty: 'bool' = False,
) -> 'AttachmentStatus'

Report what the project holds and where its gaps are.

The status check a lead runs. Alongside the inventory it returns the two lists worth acting on: files carrying no version tag, so nothing says which version they belong to, and files naming a version older than their object’s newest one.

Args

  • version: Restrict the summary to one version.
  • tag_prefix: Prefix of the tag that names a version.
  • include_empty: Also list objects carrying no version and no file. A tape-out project holds a cell per DoE variant, and ninety empty rows bury the two that matter.

Returns

A AttachmentStatus mapping, which draws itself when printed or displayed in a notebook.

Note

Whether a measurement taken against an older version still describes the current component is a question for a person. This only says where to ask it.

attachments(
self,
*,
target: 'Component | Technology | str | None' = None,
tags: 'Sequence[str]' = (),
all: 'bool' = False,
search: 'str | None' = None,
) -> 'list[dict[str, object]]'

List attachments bound to the project or one of its objects.

Args

  • target: Component or technology (object or name) to list attachments for; None (default) lists the project’s own attachments.
  • tags: Optional tag filter; only attachments carrying every given tag are returned.
  • all: When True, list attachments across the project and every tracked component and technology. Each returned record carries an extra owner field ({"kind": "project"} or {"kind": "component" | "technology", "name": ...}). Mutually exclusive with target.
  • search: Case-insensitive substring of the filename, matched the same way the browser matches it. Sync-api filters server-side; the filter is applied again locally so an older server that ignores it still returns the right list.

Returns

Attachment metadata records (as returned by attach()), each with id, filename, mimeType, tags, and (when all=True) an extra owner field.

changed_since(
self,
mark: 'Head | Sequence[str] | Component | Technology | str | None' = None,
*,
target: 'Component | Technology | str | None' = None,
fields: 'str | Sequence[str] | None' = None,
ignore: 'Sequence[str] | None' = None,
) -> 'EditLog'

The saves made after mark: empty, and so falsy, when there were none.

>>> mark = project.latest_head("ring") # doctest: +SKIP
>>> ...
>>> if project.changed_since(mark, fields=["parameters"]): # doctest: +SKIP
... raise RuntimeError("somebody else got there first")

Checking narrows the risk of overwriting a colleague; it does not remove it. A save that lands between this check and your own still wins.

Args

  • mark: The result of latest_head. It remembers its object, so no name is needed. A marker kept as a plain list of strings (after a round trip through JSON) needs target.
  • target: The object, when mark is a plain list of strings.
  • fields: Report only these parts of the document, as in edit_log. Without it, any save at all counts.
  • ignore: Top-level fields to leave out; None means the default for the document’s kind.

Returns

An EditLog of the saves after mark that changed something reported.

check_access(self) -> 'tuple[bool, dict[str, object]]'

Check if the current user can access this project.

Args

None.

Returns

Tuple (has_access, payload) from the access endpoint.

component(
self,
name: 'str',
*,
version: 'str | None' = None,
save: 'int | Edit | None' = None,
) -> 'Component'

One component, by the name it has in the project.

>>> bend = project.component("bend") # doctest: +SKIP
>>> wide = project.component("bend", save=5) # doctest: +SKIP

Args

  • name: The component’s name (not the parametric function’s).
  • version: Leave out for your copy as it stands (call load_latest first to include everyone’s saves); give one to rebuild the design at that version, as load does.
  • save: A save number from edit_log, to rebuild the design as it was right after that save, versioned or not.

Returns

The component. Looks in this project first, then its libraries; a library’s component can be read but not rebuilt at a version or save from here, since those belong to the library.

components(
self,
*,
name: 'str | None' = None,
search: 'str | re.Pattern | None' = None,
origin: 'str | DocumentId | None' = None,
external_only: 'bool' = True,
) -> (
'dict[str, dict[str, Component]] | dict[str, Component] | Component'
)

Query components by exact name, regex, and origin scope.

Args

  • name: Exact component name filter.
  • search: Regex or pattern string filter for names.
  • origin: Source scope (“self”, “libraries”, or library name).
  • external_only: Whether listings include only components marked external. Ignored when name or search is provided.

Returns

Filtered component objects grouped by origin when needed.

detach(
self,
attachment: 'Mapping[str, object] | str',
*,
target: 'Component | Technology | str | None' = None,
delete: 'bool' = True,
) -> 'None'

Remove an attachment from the project or one of its components.

Args

  • attachment: Raw attachment ID, attachment reference from attachments(), or metadata returned by attach().
  • target: Component or technology (object or name) the attachment is on; None (default) targets the project.
  • delete: Soft-delete the attachment (default). When False the attachment is only unlinked from the target and kept.

download_attachment(
self, attachment: 'Mapping[str, object] | str'
) -> 'bytes'

Download the binary content of an attachment.

Args

  • attachment: Raw attachment ID, attachment reference from attachments(), or metadata returned by attach().

Returns

Raw file bytes.

edit_log(
self,
target: 'Component | Technology | str | None' = None,
*,
since: 'Sequence[str] | None' = None,
limit: 'int | None' = None,
fields: 'str | Sequence[str] | None' = None,
ignore: 'Sequence[str] | None' = None,
) -> 'EditLog'

Every save to one document, oldest first, including unversioned ones.

version_history lists versions and tags, so a save nobody versioned is invisible to it. The change stream still holds every one; diffing the document after each save against the one before reports what moved as field: before -> after — parameters.radius on a component, layers.SiN.thickness on a technology, components[3] on the project. That is how you recover a value somebody overwrote.

>>> project.edit_log("bend", fields=["parameters"]) # doctest: +SKIP

Args

  • target: The component or technology, or its name (the name it has in the project, not the parametric function’s); None (default) reads the project document itself.
  • since: A marker from latest_head; only the saves after it are returned. When target is not given, the marker’s own object is used.
  • limit: Keep only the newest this many saves.
  • fields: Report only these parts of the document: "parameters" for any knob, "parameters.radius" for one. One string or a list. A field the document does not have is refused. Without it you also see internal fields, such as pfNative, the fingerprint of the stored geometry, which changes on every save.
  • ignore: Top-level fields to leave out of the report. None (default) drops what the system re-derives from the rest of the document — a component’s preview, the project’s schema registries — as listed in photonforge.pda._edits.IGNORED. Pass () to see everything.

Returns

An EditLog, oldest first, which prints as a table. A row whose only changes were ignored is kept with nothing reported; EditLog.effective drops such rows.

Note

The chain carries neither a wall clock nor a user: changes are written with a zero timestamp and an actor that identifies a session, one run of Python. Rows report order and session, never date and person.

get_info(
self, target: 'Component | Technology | str | None' = None
) -> 'dict[str, object]'

Return metadata for the project or one contained object.

Args

  • target: Optional object or name to query instead of the project document.

Returns

Metadata payload with document details, tags, and versions.

get_library_info(
self, name: 'str | None' = None
) -> 'dict[str, object] | list[dict[str, object]]'

Return metadata for one library or all imported libraries.

Args

  • name: Optional library name. If omitted, returns all libraries.

Returns

Metadata payload for one library, or a list of payloads for all imported libraries.

grant_permission(
self,
*,
visibility: "Literal['private', 'organization']",
grantee_id: 'str | None' = None,
role: "Literal['owner', 'editor', 'viewer']" = 'viewer',
) -> 'dict[str, object]'

Grant access permissions for the project document.

Args

  • visibility: Permission visibility scope.
  • grantee_id: User or organization ID who will receive the permission.
  • role: Access role to grant.

Returns

Created permission payload.

Note

For organization visibility, grantee_id defaults to the current organization when available.

Important

Setting public visibility is not allowed, as it shares the contents and all dependencies with all users in the platform. Please contact support if you want to share a public library.

import_module(
self, namespace: 'dict | None', *, reload: 'bool' = True
) -> 'dict[str, object]'

Import the project and library Python modules.

Args

  • namespace: Optional mapping to populate with imported modules.
  • reload: Whether to hard-reload project/library modules from disk.

Returns

Mapping from module name to imported module object.

Each imported module gets two read-only live mappings: pda_components and pda_technologies.

Example

Import parametric components from the project and its libraries in the current namespace (equivalent to using import project_module for each dependency of the project):

>>> project.import_module(globals()) # doctest: +SKIP

latest_head(
self, target: 'Component | Technology | str | None' = None
) -> 'Head'

Where a document stands now: the id of its newest save.

Like Git’s HEAD, but per object: each component and technology has its own history, and the project has its own. It reads the server and changes nothing. Keep it, then ask changed_since whether anyone saved after it:

>>> project.load_latest() # doctest: +SKIP
>>> mark = project.latest_head("bend") # doctest: +SKIP
>>> if project.changed_since(mark, fields=["parameters"]): # doctest: +SKIP
... print("someone changed it; look before you save")

Args

  • target: The component or technology, or its name (the name it has in the project, not the parametric function’s); None (default) for the project document.

Returns

A Head: opaque, safe to keep, and it remembers target.

list_permissions(self) -> 'list[dict[str, object]]'

List sharing permissions for the project document.

Args

None.

Returns

Permission metadata list.

list_tags(
self, target: 'Component | Technology | str | None' = None
) -> 'list[str]'

Return available tags for the project or one contained object.

Args

  • target: Optional object or name to query instead of the project document.

Returns

List of tag strings for the target.

list_versions(
self, target: 'Component | Technology | str | None' = None
) -> 'list[str]'

Return available versions for the project or one contained object.

Args

  • target: Optional object or name to query instead of the project document.

Returns

List of version strings for the target.

load(
self,
target: 'Component | Technology | str',
*,
tag: 'str | None' = None,
version: 'str | None' = None,
save: 'int | Edit | None' = None,
) -> 'Component | Technology'

Load a tagged/versioned snapshot of a project object.

Args

  • target: Component/technology object or exact name.
  • tag: Optional tag filter.
  • version: Optional version filter.
  • save: Instead of a tag or version, a save number from edit_log (or one of its rows): the object as it was right after that save, whether anyone versioned it or not.

Returns

Object snapshot matching the search parameters.

Note

The object comes back as the whole design was at that moment. For a save, that is the project state the same save wrote. For a version or tag, it is the project state add_version and update record with every version and tag they make, which supplies the technology, subcomponents and configuration of that moment. A version or tag recorded without one, by an older server, raises rather than guessing, and the message names the save to load instead. Grid and tolerance stay the session’s.

load_latest(
self,
*,
module_path: 'str | Path | None' = None,
set_config: 'bool' = True,
reload_module: 'bool' = True,
) -> 'Project'

Bring this copy of the project up to date with everyone’s saves.

This is the live state, not a numbered version (load rebuilds one of those), and it uploads nothing of yours. An open copy does not update by itself, so call this before editing: a save from an out-of-date copy can undo someone else’s work, or write nothing.

With reload_module, the project’s code is unpacked again and, if it had been imported, imported again, so parametric components stay editable. Components you hold in variables are not changed; take fresh ones from components.

Args

  • module_path: Root directory where modules are unpacked.
  • set_config: Whether to apply project config to PhotonForge.
  • reload_module: Whether to reload the project module.

Returns

This project, reloaded in its latest, writable version.

load_query(self, attachment: 'Mapping[str, object] | str') -> 'BoundQuery'

Read a pointer back off its attachment.

Args

  • attachment: The pointer attachment record or its id.

Returns

A BoundQuery. Its names are re-checked on the way in, because the attachment may have been written by somebody else.

remove_tag(
self,
tag: 'str | Sequence[str]',
*,
target: 'Component | Technology | str | None' = None,
) -> 'Component | Technology | Project'

Remove one or more tags from the selected target.

Args

  • tag: Tag label or labels to remove.
  • target: Optional target object or name. Defaults to project.

Returns

Target object from which tags were removed.

restore(self, names: 'Sequence[str]', *, external: 'bool' = False) -> 'None'

Restore retired technologies/components by name.

The most recently retired object with each name is restored.

Args

  • names: Names of retired components/technologies.
  • external: Whether restored components are marked external.

Returns

None.

retire(self, targets: 'Sequence[Component | Technology | str]') -> 'None'

Retire technologies/components by object instance or name.

Objects still referenced by remaining project content are kept and reported through a runtime warning.

Args

  • targets: Components/technologies (or names) to retire.

Returns

None.

retire_unused(self) -> 'None'

Retire project-owned internal components unused by external ones.

revoke_permission(self, permission_id: 'str') -> 'None'

Revoke one permission by its identifier.

Args

  • permission_id: Permission identifier.

Returns

None.

run_query(
self,
attachment: 'Mapping[str, object] | str | BoundQuery',
*,
connection: 'object',
where: 'Mapping[str, object] | None' = None,
limit: 'int | None' = None,
) -> 'object'

Read the rows a pointer names, through a connection you opened.

The statement is composed here from the pointer’s pieces, quoted and parameterised for whatever driver connection belongs to, so the same pointer reads from PostgreSQL, SQLite, MySQL, SQL Server, Oracle or DuckDB without being rewritten.

Args

  • attachment: A BoundQuery, or the pointer attachment.
  • connection: An open DB-API or SQLAlchemy connection. Never stored.
  • where: Values for the columns the pointer offers as filters. A key it does not offer is refused rather than appended; one left out narrows nothing.
  • limit: Stop after this many rows. Applied while fetching, since no row-limit syntax is common to every dialect.

Returns

A pandas.DataFrame when pandas is available, else a list of rows.

save_module(self) -> 'None'

Pack the loaded module directory and store it in PDA.

The module includes all files in the directory project.module_path / project.module_name.

set(
self,
*,
name: 'str | None' = None,
description: 'str | None' = None,
labels: 'Sequence[str] | None' = None,
module_name: 'str | None' = None,
) -> 'None'

Update editable project fields in-place.

Args

  • name: Optional replacement project name.
  • description: Optional replacement project description.
  • labels: Optional replacement label collection.
  • module_name: Optional replacement Python module name. Only allowed before the module is first saved; afterwards the name is pinned to the stored archive.

set_external(
self, component: 'Component | str', external: 'bool' = True
) -> 'None'

Set/unset a component as external in the module mapping.

Args

  • component: Component object or component name to set.
  • external: Set/unset flag.

technologies(
self,
*,
name: 'str | None' = None,
search: 'str | re.Pattern | None' = None,
origin: 'str | DocumentId | None' = None,
) -> (
'dict[str, dict[str, Technology]] | dict[str, Technology] | Technology'
)

Query technologies by exact name, regex, and origin scope.

Args

  • name: Exact technology name filter.
  • search: Regex or pattern string filter for names.
  • origin: Source scope (“self”, “libraries”, or library name).

Returns

Filtered technology objects grouped by origin when needed.

technology(
self,
name: 'str',
*,
version: 'str | None' = None,
save: 'int | Edit | None' = None,
) -> 'Technology'

One technology, by name, as component finds a component.

trace(
self,
attachment: 'Mapping[str, object] | str',
*,
tag_prefix: 'str' = 'version:',
rebuild: 'bool' = True,
) -> 'Trace'

Walk an attached file back to the design it describes.

Four hops: the file’s version: tag names a version, that version is a row on the document the file is bound to, the row carries a reference pinning one exact moment, and resolving it rebuilds the object as the whole design was then; see load.

Args

  • attachment: An attachment record or its id.
  • tag_prefix: Prefix of the tag that names a version.
  • rebuild: Resolve the reference and return the rebuilt object as Trace.component or Trace.technology.

Returns

A Trace mapping, which draws the chain when printed or displayed and reports how solid the first hop was.

Note

Only the first hop is a convention. Trace.confidence is "tag" when the file named a version, "unambiguous" when it did not but the document has exactly one, "missing" when the tag names a version that does not exist, and "none" otherwise. In the last two cases the candidates are returned rather than guessed between.

traceability_matrix(
self,
target: 'Component | Technology | str | None' = None,
*,
tag_prefix: 'str' = 'version:',
) -> 'TraceabilityMatrix'

Which file belongs to which version: a row per file, a column per version.

✓ marks the version a file is labelled for; · a version its target has that the file is not labelled for. A file labelled with a version its target does not have, a typo such as version:1.0 for 1.0.0, is flagged.

Args

  • target: Only the files on this component or technology; None for every file.
  • tag_prefix: Prefix of the tag that names a version.

Returns

A TraceabilityMatrix; .data_frame for pandas.

transfer_ownership(self, grantee_id: 'str') -> 'dict[str, object]'

Transfer project ownership to another user identifier.

Args

  • grantee_id: Identifier of the new owner.

Returns

Updated owner permission payload.

tree(
self, target: 'Component | Technology | str | None' = None
) -> 'ProjectTree'

What is in the project, as a tree.

Its technologies with the files kept with them, its libraries, its source files and their unsaved changes, its top-level components with their newest version and how many cells and files each holds, the cells inside, and the files with the version each names. It is an overview, so it stays readable at any size: a component with many files or cells gets one summary line, which says tree(target=...) lists them. A notebook draws it; print gives it like the tree command; .mermaid() and .svg() are the drawings.

>>> project.tree() # doctest: +SKIP
>>> project.tree("gc_doe_reticle") # one component, with far more listed # doctest: +SKIP

Args

  • target: One component or technology to zoom into; None for the whole project.

update(
self,
upd_obj: 'Component | Technology',
*,
tag: 'str | None' = None,
bump_version: "Literal['major', 'minor', 'patch'] | None" = None,
update_existing_dependencies: 'bool' = True,
update_config: 'bool' = True,
project_tag: 'str | None' = '{name}-{version_and_tag}',
) -> "dict[Literal['added', 'updated'], list[Technology | Component]]"

Update an existing project object and optional dependencies.

Args

  • upd_obj: Component or technology to update.
  • tag: Optional tag applied to changed objects.
  • bump_version: Optional semantic bump for changed objects.
  • update_existing_dependencies: Whether existing dependencies may be updated.
  • update_config: Whether to update project config from current setting.
  • project_tag: If either tag or bump_version is not None, tag to the project using this template, with name, version, tag, version_and_tag and datetime fields. The name is trimmed to keep the tag within the server’s limit, and a label the project already carries is reported, not fatal.

Returns

Mapping with added and updated object lists.

update_permission(
self, permission_id: 'str', *, role: "Literal['editor', 'viewer']"
) -> 'dict[str, object]'

Change the role associated with an existing permission.

Args

  • permission_id: Permission identifier.
  • role: New role value.

Returns

Updated permission payload.

version_history(
self,
target: 'Component | Technology | str | None' = None,
*,
kinds: 'Sequence[str]' = ('version', 'tag'),
limit: 'int | None' = None,
all: 'bool' = False,
diff: 'bool' = False,
) -> 'History'

The numbered versions and tags of the project or one object in it.

Each entry says who made it and when. For every save in between, versioned or not, see edit_log.

Args

  • target: Object or name to query instead of the project document.
  • kinds: Entry kinds to include, from "version" and "tag".
  • limit: Keep only this many entries, after sorting newest first.
  • all: Merge the project and every component and technology it owns into one view, each on its own lane. Cannot be combined with target.
  • diff: Report what changed between consecutive versions.

Returns

A History: with the sequence of events.

watch(
self,
target: 'Component | Technology | str | None' = None,
*,
on_change: 'Callable[[EditLog], object]',
interval: 'float' = 0.5,
fields: 'str | Sequence[str] | None' = None,
ignore: 'Sequence[str] | None' = None,
) -> 'Watcher'

Call on_change whenever a save to this document reaches you.

It runs in the background, from now until cancel() or until this Python process ends: saves made while it is not running are not reported, so keep a latest_head marker and call changed_since when you come back. It fires on anyone’s saves, your own included, not when you use the object. It checks every interval seconds; a save from another machine usually arrives within a second or two.

The callback runs on the client’s event loop, so it cannot call this project’s methods and should be short: print, set a flag, queue something. It is handed the EditLog of what arrived, reduced to the saves that changed something reported. If it raises, the watch stops and Watcher.error holds the reason.

Args

  • target: The component or technology, or its name; None (default) for the project document.
  • on_change: Called with one EditLog argument.
  • interval: Seconds between checks.
  • fields: Only fire for changes to these parts, as in edit_log.
  • ignore: Top-level fields to leave out; None means the default for the document’s kind.

Returns

A Watcher. Call cancel() when you are done.

PropertyDescription
descriptionProject description.
idProject ID.
is_read_onlyProject read-only state.
labelsProject labels.
module_nameSanitized Python module name for this project.
module_pathFilesystem path where the project Python module is loaded.
nameProject name.

Project description.

Project ID.

Project read-only state.

Project labels.

Sanitized Python module name for this project.

Filesystem path where the project Python module is loaded.

Project name.