Python API

Use VcsExtension.ext() for Catalogs, Collections, Items, Assets, and Links.

pystac.extensions.vcs

Read and write VCS v0.1.0 metadata on PySTAC objects, assets, and links.

Use VcsExtension.ext(target, add_if_missing=True) to declare the extension on a STAC object or the owner of an asset or link before setting its fields.

VCS_EXTENSION_HOOKS: ExtensionHooks = VcsExtensionHooks() module-attribute

SCHEMA_URI = 'https://stac-extensions.github.io/vcs/v0.1.0/schema.json' module-attribute

VcsExtension

Bases: Generic[T], PropertiesExtension, ExtensionManagementMixin[Catalog | Collection | Item]

Access version-control metadata stored directly on a PySTAC target.

Catalogs and Collections store fields at the top level; Items use their properties. Assets and Links use their own extra fields, without inheriting metadata from their owners. Use ext() to check the schema declaration.

Attributes:
  • obj –

    The target whose metadata is mutated by this wrapper.

Source code in pystac/extensions/vcs.py
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
class VcsExtension(
    Generic[T],
    PropertiesExtension,
    ExtensionManagementMixin[pystac.Catalog | pystac.Collection | pystac.Item],
):
    """Access version-control metadata stored directly on a PySTAC target.

    Catalogs and Collections store fields at the top level; Items use their
    properties. Assets and Links use their own extra fields, without inheriting
    metadata from their owners. Use ``ext()`` to check the schema declaration.

    Attributes:
        obj: The target whose metadata is mutated by this wrapper.
    """

    name: Literal["vcs"] = "vcs"

    def __init__(self, obj: T) -> None:
        """Wrap a target's metadata without checking its extension declaration."""
        self.obj = obj
        if isinstance(obj, pystac.Item):
            self.properties = obj.properties
        elif isinstance(obj, (pystac.Catalog, pystac.Asset, pystac.Link)):
            self.properties = obj.extra_fields
        else:
            raise pystac.ExtensionTypeError(self._ext_error_message(obj))

    def apply(
        self,
        vcs_type: str | None = None,
        branch: str | None = None,
        revision: str | None = None,
        tag: str | None = None,
    ) -> None:
        """Replace all four VCS fields in place, clearing omitted fields.

        Args:
            vcs_type: Version-control system name, such as ``git`` or ``svn``.
            branch: Line of development, such as ``main``.
            revision: Exact revision identifier, such as a commit hash.
            tag: Release marker, such as ``v1.0.0``.

        Values are serialized as supplied; call STAC validation separately to
        enforce the schema's nonempty-string constraints.
        """
        self.vcs_type = vcs_type
        self.branch = branch
        self.revision = revision
        self.tag = tag

    @property
    def vcs_type(self) -> str | None:
        """The version-control system name, or None when absent."""
        return self._get_property(TYPE_PROP, str)

    @vcs_type.setter
    def vcs_type(self, value: str | None) -> None:
        self._set_property(TYPE_PROP, value)

    @property
    def branch(self) -> str | None:
        """The line of development, or None when absent."""
        return self._get_property(BRANCH_PROP, str)

    @branch.setter
    def branch(self, value: str | None) -> None:
        self._set_property(BRANCH_PROP, value)

    @property
    def revision(self) -> str | None:
        """The exact revision identifier, or None when absent."""
        return self._get_property(REVISION_PROP, str)

    @revision.setter
    def revision(self, value: str | None) -> None:
        self._set_property(REVISION_PROP, value)

    @property
    def tag(self) -> str | None:
        """The release marker, or None when absent."""
        return self._get_property(TAG_PROP, str)

    @tag.setter
    def tag(self, value: str | None) -> None:
        self._set_property(TAG_PROP, value)

    @classmethod
    def get_schema_uri(cls) -> str:
        """Return the VCS v0.1.0 schema identifier."""
        return SCHEMA_URI

    @classmethod
    def ext(cls, obj: T, add_if_missing: bool = False) -> VcsExtension[T]:
        """Wrap a target after checking its VCS extension declaration.

        Args:
            obj: Catalog, Collection, Item, Asset, or Link to extend.
            add_if_missing: Add the schema URI to the target or its owner.
                Unowned Assets and Links can be wrapped only when False.

        Raises:
            pystac.ExtensionNotImplemented: If the target or its owner has no
                VCS declaration and ``add_if_missing`` is False.
            pystac.STACError: If adding the declaration to an unowned target.
            pystac.ExtensionTypeError: If the target type is unsupported.
        """
        if isinstance(obj, (pystac.Catalog, pystac.Item)):
            cls.ensure_has_extension(obj, add_if_missing)
        elif isinstance(obj, (pystac.Asset, pystac.Link)):
            cls.ensure_owner_has_extension(obj, add_if_missing)
        else:
            raise pystac.ExtensionTypeError(cls._ext_error_message(obj))
        return cls(obj)

    def __repr__(self) -> str:
        return f"<VcsExtension {self.obj!r}>"

branch: str | None property writable

The line of development, or None when absent.

revision: str | None property writable

The exact revision identifier, or None when absent.

tag: str | None property writable

The release marker, or None when absent.

vcs_type: str | None property writable

The version-control system name, or None when absent.

__init__(obj: T) -> None

Wrap a target's metadata without checking its extension declaration.

Source code in pystac/extensions/vcs.py
56
57
58
59
60
61
62
63
64
def __init__(self, obj: T) -> None:
    """Wrap a target's metadata without checking its extension declaration."""
    self.obj = obj
    if isinstance(obj, pystac.Item):
        self.properties = obj.properties
    elif isinstance(obj, (pystac.Catalog, pystac.Asset, pystac.Link)):
        self.properties = obj.extra_fields
    else:
        raise pystac.ExtensionTypeError(self._ext_error_message(obj))

apply(vcs_type: str | None = None, branch: str | None = None, revision: str | None = None, tag: str | None = None) -> None

Replace all four VCS fields in place, clearing omitted fields.

Parameters:
  • vcs_type (str | None, default: None ) –

    Version-control system name, such as git or svn.

  • branch (str | None, default: None ) –

    Line of development, such as main.

  • revision (str | None, default: None ) –

    Exact revision identifier, such as a commit hash.

  • tag (str | None, default: None ) –

    Release marker, such as v1.0.0.

Values are serialized as supplied; call STAC validation separately to enforce the schema's nonempty-string constraints.

Source code in pystac/extensions/vcs.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
def apply(
    self,
    vcs_type: str | None = None,
    branch: str | None = None,
    revision: str | None = None,
    tag: str | None = None,
) -> None:
    """Replace all four VCS fields in place, clearing omitted fields.

    Args:
        vcs_type: Version-control system name, such as ``git`` or ``svn``.
        branch: Line of development, such as ``main``.
        revision: Exact revision identifier, such as a commit hash.
        tag: Release marker, such as ``v1.0.0``.

    Values are serialized as supplied; call STAC validation separately to
    enforce the schema's nonempty-string constraints.
    """
    self.vcs_type = vcs_type
    self.branch = branch
    self.revision = revision
    self.tag = tag

ext(obj: T, add_if_missing: bool = False) -> VcsExtension[T] classmethod

Wrap a target after checking its VCS extension declaration.

Parameters:
  • obj (T) –

    Catalog, Collection, Item, Asset, or Link to extend.

  • add_if_missing (bool, default: False ) –

    Add the schema URI to the target or its owner. Unowned Assets and Links can be wrapped only when False.

Raises:
  • ExtensionNotImplemented –

    If the target or its owner has no VCS declaration and add_if_missing is False.

  • STACError –

    If adding the declaration to an unowned target.

  • ExtensionTypeError –

    If the target type is unsupported.

Source code in pystac/extensions/vcs.py
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
@classmethod
def ext(cls, obj: T, add_if_missing: bool = False) -> VcsExtension[T]:
    """Wrap a target after checking its VCS extension declaration.

    Args:
        obj: Catalog, Collection, Item, Asset, or Link to extend.
        add_if_missing: Add the schema URI to the target or its owner.
            Unowned Assets and Links can be wrapped only when False.

    Raises:
        pystac.ExtensionNotImplemented: If the target or its owner has no
            VCS declaration and ``add_if_missing`` is False.
        pystac.STACError: If adding the declaration to an unowned target.
        pystac.ExtensionTypeError: If the target type is unsupported.
    """
    if isinstance(obj, (pystac.Catalog, pystac.Item)):
        cls.ensure_has_extension(obj, add_if_missing)
    elif isinstance(obj, (pystac.Asset, pystac.Link)):
        cls.ensure_owner_has_extension(obj, add_if_missing)
    else:
        raise pystac.ExtensionTypeError(cls._ext_error_message(obj))
    return cls(obj)

get_schema_uri() -> str classmethod

Return the VCS v0.1.0 schema identifier.

Source code in pystac/extensions/vcs.py
125
126
127
128
@classmethod
def get_schema_uri(cls) -> str:
    """Return the VCS v0.1.0 schema identifier."""
    return SCHEMA_URI

VcsExtensionHooks

Bases: ExtensionHooks

Identify VCS metadata for PySTAC extension migration hooks.

Source code in pystac/extensions/vcs.py
157
158
159
160
161
162
163
164
165
166
class VcsExtensionHooks(ExtensionHooks):
    """Identify VCS metadata for PySTAC extension migration hooks."""

    schema_uri = SCHEMA_URI
    prev_extension_ids: ClassVar[set[str]] = set()
    stac_object_types: ClassVar[set[pystac.STACObjectType]] = {
        pystac.STACObjectType.CATALOG,
        pystac.STACObjectType.COLLECTION,
        pystac.STACObjectType.ITEM,
    }