Skip to content

Context API

Context reads the resource information advertised by a Science Platform Server. The returned mapping can guide Session.create() resource requests.

from canfar.context import Context

with Context() as context:
    resources = context.resources()
    print(resources["cores"])
    print(resources.get("memoryGB"))
    print(resources.get("gpus"))

The response is a dict[str, Any] whose keys and values are supplied by the server; common keys include cores, memoryGB, gpus, and maxInteractiveSessions. Resource limits are server metadata, not a second Configuration model: Server discovery reads this payload with ServerResources.from_context() and saves the result as each Server's resources.

from canfar.context import Context
from canfar.models.http import ServerResources

with Context() as context:
    resources = ServerResources.from_context(context.resources())
    print(resources.flexible.cores)  # guaranteed request to burst limit
    print(resources.fixed.ram)  # smallest to largest fixed memory, in GB

A value the Server does not advertise is None. from_context() raises ValueError when the payload holds no limit it recognizes, as from older platform versions.

Bases: HTTPClient

CANFAR Context.

This class is a subclass of the HTTPClient class and inherits its attributes and methods.

Examples:

>>> from canfar.context import Context
>>> context = Context()
>>> context.resources()
Source code in canfar/context.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
class Context(HTTPClient):
    """CANFAR Context.

    This class is a subclass of the `HTTPClient` class and inherits its
    attributes and methods.

    Examples:
        >>> from canfar.context import Context
        >>> context = Context()
        >>> context.resources()
    """

    def resources(self) -> dict[str, Any]:
        """Get available resources from the canfar server.

        ``canfar.models.http.ServerResources.from_context()`` reads this payload
        into flexible and fixed limits; discovery saves them as
        ``Server.resources``.

        Returns:
            A dictionary of available resources.

        Raises:
            httpx2.HTTPStatusError: If the Server answers with an error status.

        Examples:
            >>> from canfar.context import Context
            >>> context = Context()
            >>> context.resources()
            {'cores': {
              'default': 1,
              'defaultRequest': 1,
              'defaultLimit': 16,
              'options': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
              },
             'memoryGB': {
              'default': 2,
              'defaultRequest': 4,
              'defaultLimit': 32,
              'options': [1,2,4...192]
             },
            'gpus': {
             'options': [1,2, ... 28]
             },
            'maxInteractiveSessions': 5
            }
        """
        response: Response = self.client.get(url="context")
        response.raise_for_status()
        return dict(response.json())

resources

resources()

Get available resources from the canfar server.

canfar.models.http.ServerResources.from_context() reads this payload into flexible and fixed limits; discovery saves them as Server.resources.

RETURNS DESCRIPTION
dict[str, Any]

A dictionary of available resources.

RAISES DESCRIPTION
HTTPStatusError

If the Server answers with an error status.

Examples:

>>> from canfar.context import Context
>>> context = Context()
>>> context.resources()
{'cores': {
  'default': 1,
  'defaultRequest': 1,
  'defaultLimit': 16,
  'options': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
  },
 'memoryGB': {
  'default': 2,
  'defaultRequest': 4,
  'defaultLimit': 32,
  'options': [1,2,4...192]
 },
'gpus': {
 'options': [1,2, ... 28]
 },
'maxInteractiveSessions': 5
}
Source code in canfar/context.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
def resources(self) -> dict[str, Any]:
    """Get available resources from the canfar server.

    ``canfar.models.http.ServerResources.from_context()`` reads this payload
    into flexible and fixed limits; discovery saves them as
    ``Server.resources``.

    Returns:
        A dictionary of available resources.

    Raises:
        httpx2.HTTPStatusError: If the Server answers with an error status.

    Examples:
        >>> from canfar.context import Context
        >>> context = Context()
        >>> context.resources()
        {'cores': {
          'default': 1,
          'defaultRequest': 1,
          'defaultLimit': 16,
          'options': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
          },
         'memoryGB': {
          'default': 2,
          'defaultRequest': 4,
          'defaultLimit': 32,
          'options': [1,2,4...192]
         },
        'gpus': {
         'options': [1,2, ... 28]
         },
        'maxInteractiveSessions': 5
        }
    """
    response: Response = self.client.get(url="context")
    response.raise_for_status()
    return dict(response.json())

Bases: BaseModel

Session resource limits advertised by a Science Platform Server.

None marks a value the Server does not advertise.

Source code in canfar/models/http.py
 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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
class ServerResources(BaseModel):
    """Session resource limits advertised by a Science Platform Server.

    ``None`` marks a value the Server does not advertise.
    """

    model_config = ConfigDict(extra="forbid")

    flexible: SessionResources = Field(
        default_factory=SessionResources,
        title="Flexible Resources",
        description=(
            "Sessions without explicit CPU or memory: the guaranteed request (min) "
            "and the burst limit (max)."
        ),
    )
    fixed: SessionResources = Field(
        default_factory=SessionResources,
        title="Fixed Resources",
        description=(
            "Sessions with explicit CPU or memory: the smallest (min) and largest "
            "(max) values the Server accepts."
        ),
    )
    gpus: ResourceRange | None = Field(
        default=None,
        title="GPUs",
        description="GPU counts a Session can request; 0 to 0 when none are offered.",
    )
    sessions: int | None = Field(
        default=None,
        title="Interactive Session Limit",
        description=(
            "Maximum Pending or Running interactive Sessions per user; headless "
            "Sessions do not count."
        ),
        ge=1,
    )

    @classmethod
    def from_context(cls, payload: Mapping[str, Any]) -> Self:
        """Read limits from a Science Platform Server context payload.

        Values the payload omits or malforms stay ``None``, so older platform
        versions produce partial resources.

        Args:
            payload: JSON object from the Server's context endpoint, as returned
                by ``canfar.context.Context().resources()``.

        Returns:
            Limits for each Resource Allocation Mode, GPUs, and Sessions.

        Raises:
            ValueError: If the payload advertises no recognizable limit.

        Examples:
            >>> from canfar.models.http import ServerResources
            >>> ServerResources.from_context(
            ...     {
            ...         "cores": {
            ...             "defaultRequest": 1,
            ...             "defaultLimit": 2,
            ...             "options": [1, 2, 4],
            ...         },
            ...         "gpus": {"options": []},
            ...     }
            ... ).fixed.cores
            ResourceRange(min=1, max=4)
        """
        cores = _section(payload, "cores")
        memory = _section(payload, "memoryGB")
        resources = cls(
            flexible=SessionResources(
                cores=_bounds(cores.get("defaultRequest"), cores.get("defaultLimit")),
                ram=_bounds(memory.get("defaultRequest"), memory.get("defaultLimit")),
            ),
            fixed=SessionResources(
                cores=_span(cores.get("options")),
                ram=_span(memory.get("options")),
            ),
            gpus=_span(
                _section(payload, "gpus").get("options"),
                empty=ResourceRange(min=0, max=0),
            ),
            sessions=_sessions(payload.get("maxInteractiveSessions")),
        )
        if resources == cls():
            msg = "Context payload advertises no recognizable resource limits."
            raise ValueError(msg)
        return resources

from_context classmethod

from_context(payload)

Read limits from a Science Platform Server context payload.

Values the payload omits or malforms stay None, so older platform versions produce partial resources.

PARAMETER DESCRIPTION
payload

JSON object from the Server's context endpoint, as returned by canfar.context.Context().resources().

TYPE: Mapping[str, Any]

RETURNS DESCRIPTION
Self

Limits for each Resource Allocation Mode, GPUs, and Sessions.

RAISES DESCRIPTION
ValueError

If the payload advertises no recognizable limit.

Examples:

>>> from canfar.models.http import ServerResources
>>> ServerResources.from_context(
...     {
...         "cores": {
...             "defaultRequest": 1,
...             "defaultLimit": 2,
...             "options": [1, 2, 4],
...         },
...         "gpus": {"options": []},
...     }
... ).fixed.cores
ResourceRange(min=1, max=4)
Source code in canfar/models/http.py
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
@classmethod
def from_context(cls, payload: Mapping[str, Any]) -> Self:
    """Read limits from a Science Platform Server context payload.

    Values the payload omits or malforms stay ``None``, so older platform
    versions produce partial resources.

    Args:
        payload: JSON object from the Server's context endpoint, as returned
            by ``canfar.context.Context().resources()``.

    Returns:
        Limits for each Resource Allocation Mode, GPUs, and Sessions.

    Raises:
        ValueError: If the payload advertises no recognizable limit.

    Examples:
        >>> from canfar.models.http import ServerResources
        >>> ServerResources.from_context(
        ...     {
        ...         "cores": {
        ...             "defaultRequest": 1,
        ...             "defaultLimit": 2,
        ...             "options": [1, 2, 4],
        ...         },
        ...         "gpus": {"options": []},
        ...     }
        ... ).fixed.cores
        ResourceRange(min=1, max=4)
    """
    cores = _section(payload, "cores")
    memory = _section(payload, "memoryGB")
    resources = cls(
        flexible=SessionResources(
            cores=_bounds(cores.get("defaultRequest"), cores.get("defaultLimit")),
            ram=_bounds(memory.get("defaultRequest"), memory.get("defaultLimit")),
        ),
        fixed=SessionResources(
            cores=_span(cores.get("options")),
            ram=_span(memory.get("options")),
        ),
        gpus=_span(
            _section(payload, "gpus").get("options"),
            empty=ResourceRange(min=0, max=0),
        ),
        sessions=_sessions(payload.get("maxInteractiveSessions")),
    )
    if resources == cls():
        msg = "Context payload advertises no recognizable resource limits."
        raise ValueError(msg)
    return resources