kalbio 0.2.1__py3-none-any.whl → 0.2.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kalbio/__init__.py CHANGED
@@ -1 +1,10 @@
1
- __version__ = "0.2.0"
1
+ from importlib.metadata import version, PackageNotFoundError
2
+
3
+ from kalbio.client import KaleidoscopeClient
4
+
5
+ try:
6
+ __version__ = version("kalbio")
7
+ except PackageNotFoundError:
8
+ __version__ = "unknown"
9
+
10
+ __all__ = ["KaleidoscopeClient"]
kalbio/activities.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Activities Module for Kaleidoscope API Client.
2
2
 
3
- This module provides comprehensive functionality for managing activities (tasks, experiments,
3
+ This module provides functionality for managing activities (tasks, experiments,
4
4
  projects, stages, milestones, and design cycles) within the Kaleidoscope platform. It includes
5
5
  models for activities, activity definitions, and properties, as well as service classes for
6
6
  performing CRUD operations and managing activity workflows.
@@ -65,7 +65,7 @@ from kalbio.entity_fields import DataFieldTypeEnum
65
65
  from kalbio.programs import Program
66
66
  from kalbio.labels import Label
67
67
  from kalbio.workspace import WorkspaceUser, WorkspaceGroup
68
- from typing import Any, BinaryIO, List, Literal, Optional, Union
68
+ from typing import Any, BinaryIO, List, Literal, Optional, TypeAlias, Union
69
69
  from typing import TYPE_CHECKING
70
70
 
71
71
  if TYPE_CHECKING:
@@ -153,7 +153,7 @@ class ActivityStatusEnum(str, Enum):
153
153
  DONE = "done"
154
154
 
155
155
 
156
- type ActivityType = Union[
156
+ ActivityType: TypeAlias = Union[
157
157
  Literal["task"],
158
158
  Literal["experiment"],
159
159
  Literal["project"],
@@ -671,7 +671,7 @@ class Activity(_KaleidoscopeBaseModel):
671
671
  setattr(self, k, v)
672
672
 
673
673
 
674
- type ActivityIdentifier = Union[Activity, str]
674
+ ActivityIdentifier: TypeAlias = Union[Activity, str]
675
675
  """Identifier class for Activity
676
676
 
677
677
  Activities are able to be identified by:
@@ -681,7 +681,7 @@ Activities are able to be identified by:
681
681
  * UUID
682
682
  """
683
683
 
684
- type DefinitionIdentifier = Union[ActivityDefinition, str]
684
+ DefinitionIdentifier: TypeAlias = Union[ActivityDefinition, str]
685
685
  """Identifier class for ActivityDefinition
686
686
 
687
687
  ActivityDefinitions are able to be identified by:
@@ -876,12 +876,11 @@ class ActivitiesService:
876
876
 
877
877
  try:
878
878
  payload = {
879
- "program_ids": program_ids,
880
879
  "title": title,
881
880
  "activity_type": activity_type,
882
881
  "definition_id": self._resolve_definition_id(activity_definition_id),
883
- "record_ids": [],
884
- "assigned_user_ids": assigned_user_ids,
882
+ "program_ids": program_ids if program_ids else [],
883
+ "assigned_user_ids": assigned_user_ids if assigned_user_ids else [],
885
884
  "start_date": start_date.isoformat() if start_date else None,
886
885
  "duration": duration,
887
886
  }
kalbio/client.py CHANGED
@@ -59,8 +59,8 @@ Any file retrieved by the `KaleidoscopeClient` must be of one the above types"""
59
59
  TIMEOUT_MAXIMUM = 10
60
60
  """Maximum timeout for API requests in seconds."""
61
61
 
62
- _api_key = os.getenv("KALEIDOSCOPE_API_CLIENT_ID")
63
- _api_secret = os.getenv("KALEIDOSCOPE_API_CLIENT_SECRET")
62
+ _env_client_id = os.getenv("KALEIDOSCOPE_API_CLIENT_ID")
63
+ _env_client_secret = os.getenv("KALEIDOSCOPE_API_CLIENT_SECRET")
64
64
 
65
65
 
66
66
  class _TokenResponse(BaseModel):
@@ -107,21 +107,36 @@ class KaleidoscopeClient:
107
107
  )
108
108
  # Use the client to interact with various services
109
109
  programs = client.activities.get_activities()
110
+
111
+ # For applications behind Google Cloud IAP:
112
+ client = KaleidoscopeClient(
113
+ client_id="your_api_client_id",
114
+ client_secret="your_api_client_secret",
115
+ iap_client_id="your_iap_client_id.apps.googleusercontent.com"
116
+ )
110
117
  ```
111
118
  """
112
119
 
113
120
  _client_id: str
114
121
  _client_secret: str
122
+ _additional_headers: dict
123
+ _iap_client_id: Optional[str]
115
124
 
116
- _refresh_token: str
117
- _access_token: str
118
- _refresh_before: datetime
125
+ _refresh_token: str = None
126
+ _access_token: str = None
127
+ _auth_refresh_before: Optional[datetime] = None
128
+
129
+ _iap_token: Optional[str] = None
130
+ _iap_refresh_before: Optional[datetime] = None
119
131
 
120
132
  def __init__(
121
133
  self,
122
- client_id: Optional[str] = _api_key,
123
- client_secret: Optional[str] = _api_secret,
134
+ client_id: Optional[str] = _env_client_id,
135
+ client_secret: Optional[str] = _env_client_secret,
124
136
  url: str = PROD_API_URL,
137
+ additional_headers: dict = {},
138
+ iap_client_id: Optional[str] = None,
139
+ verify_ssl: bool = True,
125
140
  ):
126
141
  """Initialize the Kaleidoscope API client.
127
142
 
@@ -133,6 +148,9 @@ class KaleidoscopeClient:
133
148
  client_secret (str): The API client secret for authentication.
134
149
  url (Optional[str]): The base URL for the API. Defaults to the production
135
150
  API URL if not provided.
151
+ iap_client_id (Optional[str]): The OAuth client ID for Google Cloud
152
+ Identity-Aware Proxy. If provided, the client will automatically
153
+ fetch and refresh IAP tokens. Requires the `google-auth` package.
136
154
 
137
155
  Example:
138
156
  ```python
@@ -141,6 +159,13 @@ class KaleidoscopeClient:
141
159
 
142
160
  # Or rely on environment variables KALEIDOSCOPE_API_CLIENT_ID/SECRET
143
161
  client = KaleidoscopeClient()
162
+
163
+ # For applications behind Google Cloud IAP
164
+ client = KaleidoscopeClient(
165
+ client_id="id",
166
+ client_secret="secret",
167
+ iap_client_id="your_iap_client_id.apps.googleusercontent.com"
168
+ )
144
169
  ```
145
170
  """
146
171
  if client_id is None:
@@ -183,9 +208,35 @@ class KaleidoscopeClient:
183
208
 
184
209
  self._client_id = client_id
185
210
  self._client_secret = client_secret
186
- self._get_auth_token()
211
+ self.additional_headers = additional_headers
212
+ self._iap_client_id = iap_client_id
213
+ self._verify_ssl = verify_ssl
214
+
215
+ def _refresh_iap_token(self):
216
+ """Fetch or refresh the IAP ID token.
217
+
218
+ Uses google-auth to obtain an ID token for the configured IAP client ID.
219
+ Supports both service account credentials and user credentials from
220
+ `gcloud auth application-default login`.
221
+
222
+ Raises:
223
+ ImportError: If google-auth is not installed.
224
+ google.auth.exceptions.DefaultCredentialsError: If no valid credentials found.
225
+ """
226
+ try:
227
+ from google.auth.transport.requests import Request
228
+ from google.oauth2 import id_token
229
+ except ImportError:
230
+ raise ImportError(
231
+ "The 'google-auth' package is required for IAP authentication. "
232
+ "Install it with: pip install google-auth or re-install kalbio with the iap option: "
233
+ "pip install kalbio[iap]"
234
+ )
235
+ self._iap_token = id_token.fetch_id_token(Request(), self._iap_client_id)
236
+ # IAP tokens typically expire in 1 hour; refresh 10 minutes early
237
+ self._iap_refresh_before = datetime.now() + timedelta(minutes=50)
187
238
 
188
- def _update_tokens(self, resp: _TokenResponse):
239
+ def _update_auth_tokens(self, resp: _TokenResponse):
189
240
  """Persist access and refresh tokens and compute the next refresh time.
190
241
 
191
242
  Args:
@@ -193,7 +244,7 @@ class KaleidoscopeClient:
193
244
  """
194
245
  self._access_token = resp.access_token
195
246
  self._refresh_token = resp.refresh_token
196
- self._last_refreshed_at = datetime.now() + timedelta(
247
+ self._auth_refresh_before = datetime.now() + timedelta(
197
248
  seconds=resp.expires_in - (60 * 10) # add a 10 minute buffer
198
249
  )
199
250
 
@@ -210,14 +261,16 @@ class KaleidoscopeClient:
210
261
  "client_id": self._client_id,
211
262
  "client_secret": self._client_secret,
212
263
  },
264
+ headers={**self._get_iap_headers(), **self.additional_headers},
213
265
  timeout=TIMEOUT_MAXIMUM,
266
+ verify=self._verify_ssl,
214
267
  )
215
268
  if auth_resp.status_code >= 400:
216
269
  raise RuntimeError(
217
270
  f"Could not connect to server with client_id {self._client_id}: {auth_resp.content}"
218
271
  )
219
272
 
220
- self._update_tokens(_TokenResponse.model_validate(auth_resp.json()))
273
+ self._update_auth_tokens(_TokenResponse.model_validate(auth_resp.json()))
221
274
 
222
275
  def _refresh_auth_token(self):
223
276
  """Refresh the access token using the stored refresh token.
@@ -234,27 +287,54 @@ class KaleidoscopeClient:
234
287
  "grant_type": "refresh_token",
235
288
  "refresh_token": self._refresh_token,
236
289
  },
290
+ headers={**self._get_iap_headers(), **self.additional_headers},
237
291
  timeout=TIMEOUT_MAXIMUM,
292
+ verify=self._verify_ssl,
238
293
  )
239
294
  if auth_resp.status_code >= 400:
240
295
  raise RuntimeError(f"Could not refresh access token: {auth_resp.content}")
241
296
 
242
- self._update_tokens(_TokenResponse.model_validate(auth_resp.json()))
297
+ self._update_auth_tokens(_TokenResponse.model_validate(auth_resp.json()))
298
+
299
+ def _get_iap_headers(self) -> dict:
300
+ """Build IAP headers, refreshing tokens if needed.
301
+
302
+ Returns:
303
+ dict: HTTP header for IAP (Proxy-Authorization)
304
+ """
305
+ headers = {}
306
+ if self._iap_client_id:
307
+ if (
308
+ self._iap_refresh_before is None
309
+ or datetime.now() > self._iap_refresh_before
310
+ ):
311
+ self._refresh_iap_token()
312
+ headers["Authorization"] = f"Bearer {self._iap_token}"
313
+
314
+ return headers
243
315
 
244
316
  def _get_headers(self) -> dict:
245
317
  """Build authorization headers, refreshing tokens if needed.
246
318
 
247
319
  Returns:
248
- dict: HTTP headers including `Authorization` and `Content-Type`.
320
+ dict: HTTP headers including `Authorization`, `Content-Type`,
321
+ and optionally `Proxy-Authorization` for IAP.
249
322
  """
250
- if datetime.now() > self._last_refreshed_at:
323
+ if (
324
+ self._auth_refresh_before is None
325
+ or datetime.now() > self._auth_refresh_before
326
+ ):
251
327
  self._refresh_auth_token()
252
328
 
253
- return {
329
+ headers = {
254
330
  "Content-Type": "application/json",
255
- "Authorization": f"Bearer {self._access_token}",
331
+ "X-Kal-Authorization": f"Bearer {self._access_token}",
332
+ **self._get_iap_headers(),
333
+ **self.additional_headers,
256
334
  }
257
335
 
336
+ return headers
337
+
258
338
  def _post(self, url: str, payload: dict) -> Any:
259
339
  """Send a POST request to the specified URL with the given payload.
260
340
 
@@ -277,6 +357,7 @@ class KaleidoscopeClient:
277
357
  data=json.dumps(payload),
278
358
  headers=self._get_headers(),
279
359
  timeout=TIMEOUT_MAXIMUM,
360
+ verify=self._verify_ssl,
280
361
  )
281
362
  if resp.status_code >= 400:
282
363
  print(f"POST {url} received {resp.status_code}: ", resp.content)
@@ -317,6 +398,7 @@ class KaleidoscopeClient:
317
398
  data=form_data,
318
399
  headers=self._get_headers(),
319
400
  timeout=TIMEOUT_MAXIMUM,
401
+ verify=self._verify_ssl,
320
402
  )
321
403
  if resp.status_code >= 400:
322
404
  print(f"POST {url} received {resp.status_code}: ", resp.content)
@@ -346,6 +428,7 @@ class KaleidoscopeClient:
346
428
  data=json.dumps(payload),
347
429
  headers=self._get_headers(),
348
430
  timeout=TIMEOUT_MAXIMUM,
431
+ verify=self._verify_ssl,
349
432
  )
350
433
  if resp.status_code >= 400:
351
434
  print(f"PUT {url} received {resp.status_code}: ", resp.content)
@@ -374,7 +457,12 @@ class KaleidoscopeClient:
374
457
  if params:
375
458
  url += "?" + urllib.parse.urlencode(params)
376
459
 
377
- resp = requests.get(url, headers=self._get_headers(), timeout=TIMEOUT_MAXIMUM)
460
+ resp = requests.get(
461
+ url,
462
+ headers=self._get_headers(),
463
+ timeout=TIMEOUT_MAXIMUM,
464
+ verify=self._verify_ssl,
465
+ )
378
466
  if resp.status_code >= 400:
379
467
  print(f"GET {url} received {resp.status_code}", resp.content)
380
468
  return None
@@ -412,7 +500,11 @@ class KaleidoscopeClient:
412
500
  url += "?" + urllib.parse.urlencode(params)
413
501
 
414
502
  resp = requests.get(
415
- url, headers=self._get_headers(), stream=True, timeout=TIMEOUT_MAXIMUM
503
+ url,
504
+ headers=self._get_headers(),
505
+ stream=True,
506
+ timeout=TIMEOUT_MAXIMUM,
507
+ verify=self._verify_ssl,
416
508
  )
417
509
  if resp.status_code >= 400:
418
510
  print(f"GET {url} received {resp.status_code}", resp.content)
@@ -452,7 +544,10 @@ class KaleidoscopeClient:
452
544
  url += "?" + urllib.parse.urlencode(params)
453
545
 
454
546
  resp = requests.delete(
455
- url, headers=self._get_headers(), timeout=TIMEOUT_MAXIMUM
547
+ url,
548
+ headers=self._get_headers(),
549
+ timeout=TIMEOUT_MAXIMUM,
550
+ verify=self._verify_ssl,
456
551
  )
457
552
  if resp.status_code >= 400:
458
553
  print(f"DELETE {url} received {resp.status_code}", resp.content)
kalbio/dashboards.py CHANGED
@@ -21,11 +21,11 @@ from functools import lru_cache
21
21
  from kalbio._kaleidoscope_model import _KaleidoscopeBaseModel
22
22
  from kalbio.client import KaleidoscopeClient
23
23
  from pydantic import TypeAdapter
24
- from typing import List, Literal, Union
24
+ from typing import List, Literal, TypeAlias, Union
25
25
 
26
26
  _logger = logging.getLogger(__name__)
27
27
 
28
- type DashboardType = Union[
28
+ DashboardType: TypeAlias = Union[
29
29
  Literal["decision"],
30
30
  Literal["data"],
31
31
  Literal["chart"],
kalbio/entity_fields.py CHANGED
@@ -41,7 +41,7 @@ from functools import lru_cache
41
41
  from kalbio._kaleidoscope_model import _KaleidoscopeBaseModel
42
42
  from kalbio.client import KaleidoscopeClient
43
43
  from pydantic import TypeAdapter
44
- from typing import List, Optional, Union
44
+ from typing import List, Optional, TypeAlias, Union
45
45
 
46
46
  _logger = logging.getLogger(__name__)
47
47
 
@@ -151,7 +151,7 @@ class EntityField(_KaleidoscopeBaseModel):
151
151
  return f"{self.field_name}"
152
152
 
153
153
 
154
- type EntityFieldIdentifier = Union[EntityField, str]
154
+ EntityFieldIdentifier: TypeAlias = Union[EntityField, str]
155
155
  """An Identifier Type for Entity Fields.
156
156
 
157
157
  An EntityField should be able to be identified by:
kalbio/exports.py CHANGED
@@ -119,7 +119,7 @@ class ExportsService:
119
119
  url = "/records/export/csv"
120
120
  file = self._client._get_file(
121
121
  url,
122
- f"{download_path if download_path else "/tmp"}/{filename}",
122
+ f"{download_path if download_path else '/tmp'}/{filename}",
123
123
  params,
124
124
  )
125
125
 
kalbio/programs.py CHANGED
@@ -1,10 +1,10 @@
1
- """Programs module for interacting with Kaleidoscope programs/experiments.
1
+ """Programs module for interacting with Kaleidoscope programs.
2
2
 
3
3
  The service allows users to retrieve all available programs in a workspace
4
4
  and filter programs by specific IDs.
5
5
 
6
6
  Classes:
7
- Program: Data model for a Kaleidoscope program/experiment.
7
+ Program: Data model for a Kaleidoscope program.
8
8
  ProgramsService: Service for managing program retrieval operations.
9
9
 
10
10
  Example:
@@ -64,12 +64,12 @@ class ProgramsService:
64
64
 
65
65
  @lru_cache
66
66
  def get_programs(self) -> List[Program]:
67
- """Retrieve all programs (experiments) available in the workspace.
67
+ """Retrieve all programs available in the workspace.
68
68
 
69
69
  This method caches its values.
70
70
 
71
71
  Returns:
72
- List[Program]: A list of Program objects representing the experiments in the workspace.
72
+ List[Program]: A list of Program objects in the workspace.
73
73
 
74
74
  Note:
75
75
  If an exception occurs during the API request, it logs the error,
kalbio/records.py CHANGED
@@ -62,6 +62,7 @@ from typing import (
62
62
  Dict,
63
63
  List,
64
64
  Optional,
65
+ TypeAlias,
65
66
  TypedDict,
66
67
  Union,
67
68
  Unpack,
@@ -631,7 +632,7 @@ class Record(_KaleidoscopeBaseModel):
631
632
  setattr(self, k, v)
632
633
 
633
634
 
634
- type RecordIdentifier = Union[Record, str, dict[EntityFieldIdentifier, str]]
635
+ RecordIdentifier: TypeAlias = Union[Record, str, dict[EntityFieldIdentifier, str]]
635
636
  """Identifier type for Record
636
637
 
637
638
  Record can be identified by:
@@ -1154,7 +1155,7 @@ class RecordsService:
1154
1155
  ]
1155
1156
  # fmt: on
1156
1157
 
1157
- resp = self._client._get(f"/records?record_ids={",".join(to_fetch)}") or []
1158
+ resp = self._client._get(f"/records?record_ids={','.join(to_fetch)}") or []
1158
1159
  self._create_record_list(resp)
1159
1160
 
1160
1161
  ordered = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kalbio
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: Python client for kaleidoscope.bio
5
5
  License: MIT
6
6
  Author: Ahmed Elnaiem
@@ -11,6 +11,9 @@ Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
+ Provides-Extra: iap
15
+ Requires-Dist: cachetools (>=6.2.5,<7.0.0)
16
+ Requires-Dist: google-auth (>=2.0.0,<3.0.0) ; extra == "iap"
14
17
  Requires-Dist: pydantic (>=2.9.2,<3.0.0)
15
18
  Requires-Dist: requests (>=2.32.3,<3.0.0)
16
19
  Project-URL: Documentation, https://api.docs.kaleidoscope.bio
@@ -32,7 +35,6 @@ Kalbio is a Python Client library for building applications with the Kaleidoscop
32
35
  - **Intuitive Resource Management**: Clean, object-oriented interface for programs, activities, records, and more
33
36
  - **Advanced Search & Filtering**: Powerful query capabilities with type-safe filter operators
34
37
  - **File Upload Support**: Direct file upload to record fields with support for multiple file types
35
- - **Comprehensive Coverage**: Access all Kaleidoscope platform resources through a unified client
36
38
  - **Bulk Operations**: Import and export capabilities for efficient data management
37
39
 
38
40
  ## Requirements
@@ -147,13 +149,13 @@ with open("experiment_data.csv", "rb") as file:
147
149
  )
148
150
  ```
149
151
 
150
- ### Comprehensive Resource Management
152
+ ### Resource Management
151
153
 
152
- Kalbio provides services for all Kaleidoscope resources:
154
+ Kalbio provides services for the following Kaleidoscope resources:
153
155
 
154
156
  - **Programs**: Organize your work
155
157
  - **Activities**: Tasks, experiments, projects, etc.
156
- - **Records**: Structured data storage
158
+ - **Records**: Structured entity records
157
159
  - **Entity Types**: Define your data schemas
158
160
  - **Entity Fields**: Manage field definitions
159
161
  - **Labels**: Tag and categorize
@@ -170,7 +172,7 @@ Once you have a client instance, you have access to:
170
172
  | ---------------------- | ------------------------------------------- |
171
173
  | `client.programs` | Program management |
172
174
  | `client.activities` | Activities (tasks, experiments, projects) |
173
- | `client.records` | Record CRUD operations |
175
+ | `client.records` | Entity record CRUD operations |
174
176
  | `client.entity_types` | Entity type definitions |
175
177
  | `client.entity_fields` | Field definitions (key fields, data fields) |
176
178
  | `client.labels` | Label management |
@@ -0,0 +1,19 @@
1
+ kalbio/__init__.py,sha256=6Po_T4MM5m2qNTYgLe4E89C57OVwDaRQ9pXTJTuJsM4,240
2
+ kalbio/_kaleidoscope_model.py,sha256=UnSpiubaEkoyOLjAmKzQGZdXOUMthuP0HiYU1Lo2sFM,4465
3
+ kalbio/activities.py,sha256=UBvQGvQpuOirkWNX_3MNxNAstfo500PgJ6oVBf7HTCA,40654
4
+ kalbio/client.py,sha256=C6r-yuHqlk-dAq55Ur9y7FrowhLvGSR2qzb5YPvf09k,20486
5
+ kalbio/dashboards.py,sha256=Hj3mFjIBIualk5FXC1CLyLFbfvqGdYYLfdpFeigk1jw,9351
6
+ kalbio/entity_fields.py,sha256=mqE4VP2g1-XR2vLUt1TIvX9Drv71NCCYPKBh03f0zO0,15201
7
+ kalbio/entity_types.py,sha256=THXGbIV9dFU2DvIuDd7Q29onmEs9KdeqsB_tq6ZXmR4,6527
8
+ kalbio/exports.py,sha256=IiAk4ZnjU59N4lrKeDRD60ZViOigR0QDd3XcNaWq5O0,5236
9
+ kalbio/helpers.py,sha256=TBPVls1GzfUygDAwCldI5sXYTgBC2pEUSEU0OtrQi3I,1955
10
+ kalbio/imports.py,sha256=s7LIETRQtT6MXEmsbIT2FwFJdE3eh25ujbs4ZFbWYns,3523
11
+ kalbio/labels.py,sha256=Vy7PiZ8vFXIBbrCmdHyz7ANooO0-giTvTLH7WwU_Mo8,2704
12
+ kalbio/programs.py,sha256=svYmZLhN2pwT9cAB8IfvyIbUmFnMVxcoUeeUxs_uESs,2951
13
+ kalbio/property_fields.py,sha256=eCYzSnG-HQB6ECHFNpaGkpm3azHe-lDYVNJUpq5TOtc,2763
14
+ kalbio/record_views.py,sha256=M3NEOhnN4JHA8ZO0I91L9pAVdVY0kmqSent3HehzFTI,7208
15
+ kalbio/records.py,sha256=sQiGnXQaiS6VNj0n2mn8tw7u8kquHLhcAI5fpHjYL8U,40501
16
+ kalbio/workspace.py,sha256=YpeLtzo3o8um_CQLyTT8GnvkF6I195y43JhNN2GmM0M,11670
17
+ kalbio-0.2.3.dist-info/METADATA,sha256=VK7xMMAwxXl-v6kOdNMRisHf2hv3t1rrt74XmSCJb6o,7993
18
+ kalbio-0.2.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
19
+ kalbio-0.2.3.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- kalbio/__init__.py,sha256=Zn1KFblwuFHiDRdRAiRnDBRkbPttWh44jKa5zG2ov0E,22
2
- kalbio/_kaleidoscope_model.py,sha256=UnSpiubaEkoyOLjAmKzQGZdXOUMthuP0HiYU1Lo2sFM,4465
3
- kalbio/activities.py,sha256=zvemwfuiPgTjhpMhzsHon7UselKmuqw9tWpM766m5F4,40621
4
- kalbio/client.py,sha256=a2NP-FfIbIuRXQ-19KSxcbjyvCpfSXdkUiypgp2-jh8,16822
5
- kalbio/dashboards.py,sha256=0P8lNiTmyaQj0y8B7AKf1VWU0qHuTUGJ_4xDVtr9jXA,9334
6
- kalbio/entity_fields.py,sha256=HnvOSE9C_UB59ioY5mB5Sn_V3OwnfRuYZ_IJtEw2vUY,15184
7
- kalbio/entity_types.py,sha256=THXGbIV9dFU2DvIuDd7Q29onmEs9KdeqsB_tq6ZXmR4,6527
8
- kalbio/exports.py,sha256=xFdNzajrGUlPZx6tNhgqiUg1lVnrayVQW12d-SmKWA4,5236
9
- kalbio/helpers.py,sha256=TBPVls1GzfUygDAwCldI5sXYTgBC2pEUSEU0OtrQi3I,1955
10
- kalbio/imports.py,sha256=s7LIETRQtT6MXEmsbIT2FwFJdE3eh25ujbs4ZFbWYns,3523
11
- kalbio/labels.py,sha256=Vy7PiZ8vFXIBbrCmdHyz7ANooO0-giTvTLH7WwU_Mo8,2704
12
- kalbio/programs.py,sha256=SKVJbF08Pp4r7dXfy9NNQnJRnSh-kOpDVdib197EWUM,3017
13
- kalbio/property_fields.py,sha256=eCYzSnG-HQB6ECHFNpaGkpm3azHe-lDYVNJUpq5TOtc,2763
14
- kalbio/record_views.py,sha256=M3NEOhnN4JHA8ZO0I91L9pAVdVY0kmqSent3HehzFTI,7208
15
- kalbio/records.py,sha256=BXuFCA90ViSMp_TtnWJYfQnJgH9Hz-5u4iT0wF0B1UM,40480
16
- kalbio/workspace.py,sha256=YpeLtzo3o8um_CQLyTT8GnvkF6I195y43JhNN2GmM0M,11670
17
- kalbio-0.2.1.dist-info/METADATA,sha256=hzK2SQ3YjZaTLsATC3a1cg1bGOMpm3ge9vVGNxRK1BU,7969
18
- kalbio-0.2.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
19
- kalbio-0.2.1.dist-info/RECORD,,
File without changes