beamlit 0.0.20rc4__py3-none-any.whl → 0.0.20rc5__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,7 @@
1
1
  from .apikey import ApiKeyProvider
2
2
  from .authentication import (PublicProvider, RunClientWithCredentials,
3
+ get_authentication_headers,
4
+ new_client_from_settings,
3
5
  new_client_with_credentials)
4
6
  from .credentials import (Config, ContextConfig, Credentials, WorkspaceConfig,
5
7
  load_credentials, load_credentials_from_settings)
@@ -11,6 +13,8 @@ __all__ = (
11
13
  "PublicProvider",
12
14
  "RunClientWithCredentials",
13
15
  "new_client_with_credentials",
16
+ "new_client_from_settings",
17
+ "get_authentication_headers",
14
18
  "Config",
15
19
  "ContextConfig",
16
20
  "Credentials",
@@ -8,6 +8,12 @@ class ApiKeyProvider(Auth):
8
8
  self.credentials = credentials
9
9
  self.workspace_name = workspace_name
10
10
 
11
+ def get_headers(self):
12
+ return {
13
+ 'X-Beamlit-Api-Key': self.credentials.api_key,
14
+ 'X-Beamlit-Workspace': self.workspace_name
15
+ }
16
+
11
17
  def auth_flow(self, request: Request) -> Generator[Request, Response, None]:
12
18
  request.headers['X-Beamlit-Api-Key'] = self.credentials.api_key
13
19
  request.headers['X-Beamlit-Workspace'] = self.workspace_name
@@ -1,12 +1,13 @@
1
1
  from dataclasses import dataclass
2
- from typing import Generator
2
+ from typing import Dict, Generator
3
3
 
4
+ from beamlit.common.settings import Settings
4
5
  from httpx import Auth, Request, Response
5
6
 
6
7
  from ..client import AuthenticatedClient
7
8
  from .apikey import ApiKeyProvider
8
9
  from .clientcredentials import ClientCredentials
9
- from .credentials import Credentials
10
+ from .credentials import Credentials, load_credentials_from_settings
10
11
  from .device_mode import BearerToken
11
12
 
12
13
 
@@ -24,6 +25,15 @@ class RunClientWithCredentials:
24
25
  run_url: str = "https://run.beamlit.dev/v0"
25
26
 
26
27
 
28
+ def new_client_from_settings(settings: Settings):
29
+ credentials = load_credentials_from_settings(settings)
30
+
31
+ client_config = RunClientWithCredentials(
32
+ credentials=credentials,
33
+ workspace=settings.workspace,
34
+ )
35
+ return new_client_with_credentials(client_config)
36
+
27
37
  def new_client_with_credentials(config: RunClientWithCredentials):
28
38
  provider: Auth = None
29
39
  if config.credentials.api_key:
@@ -36,3 +46,22 @@ def new_client_with_credentials(config: RunClientWithCredentials):
36
46
  provider = PublicProvider()
37
47
 
38
48
  return AuthenticatedClient(base_url=config.api_url, provider=provider)
49
+
50
+ def get_authentication_headers(settings: Settings) -> Dict[str, str]:
51
+ credentials = load_credentials_from_settings(settings)
52
+ config = RunClientWithCredentials(
53
+ credentials=credentials,
54
+ workspace=settings.workspace,
55
+ )
56
+ provider = None
57
+ if config.credentials.api_key:
58
+ provider = ApiKeyProvider(config.credentials, config.workspace)
59
+ elif config.credentials.access_token:
60
+ provider = BearerToken(config.credentials, config.workspace, config.api_url)
61
+ elif config.credentials.client_credentials:
62
+ provider = ClientCredentials(config.credentials, config.workspace, config.api_url)
63
+
64
+ if provider is None:
65
+ return None
66
+
67
+ return provider.get_headers()
@@ -23,7 +23,27 @@ class ClientCredentials(Auth):
23
23
  self.workspace_name = workspace_name
24
24
  self.base_url = base_url
25
25
 
26
+ def get_headers(self):
27
+ err = self.refresh_if_needed()
28
+ if err:
29
+ raise err
30
+
31
+ return {
32
+ 'X-Beamlit-Authorization': f'Bearer {self.credentials.access_token}',
33
+ 'X-Beamlit-Workspace': self.workspace_name
34
+ }
35
+
26
36
  def refresh_if_needed(self) -> Optional[Exception]:
37
+ settings = get_settings()
38
+ if self.credentials.client_credentials and not self.credentials.refresh_token:
39
+ headers = { "Authorization": f"Basic {self.credentials.client_credentials}" }
40
+ body = { "grant_type": "client_credentials" }
41
+ response = requests.post(f"{settings.base_url}/oauth/token", headers=headers, json=body)
42
+ response.raise_for_status()
43
+ self.credentials.access_token = response.json()['access_token']
44
+ self.credentials.refresh_token = response.json()['refresh_token']
45
+ self.credentials.expires_in = response.json()['expires_in']
46
+
27
47
  # Need to refresh token if expires in less than 10 minutes
28
48
  parts = self.credentials.access_token.split('.')
29
49
  if len(parts) != 3:
@@ -42,15 +62,6 @@ class ClientCredentials(Auth):
42
62
  return None
43
63
 
44
64
  def auth_flow(self, request: Request) -> Generator[Request, Response, None]:
45
- settings = get_settings()
46
- if self.credentials.client_credentials and not self.credentials.refresh_token:
47
- headers = { "Authorization": f"Basic {self.credentials.client_credentials}" }
48
- body = { "grant_type": "client_credentials" }
49
- response = requests.post(f"{settings.base_url}/oauth/token", headers=headers, json=body)
50
- response.raise_for_status()
51
- self.credentials.access_token = response.json()['access_token']
52
- self.credentials.refresh_token = response.json()['refresh_token']
53
- self.credentials.expires_in = response.json()['expires_in']
54
65
  err = self.refresh_if_needed()
55
66
  if err:
56
67
  return err
@@ -14,6 +14,7 @@ class Credentials:
14
14
  expires_in: int = 0
15
15
  device_code: str = ""
16
16
  client_credentials: str = ""
17
+
17
18
  @dataclass
18
19
  class WorkspaceConfig:
19
20
  name: str
@@ -2,7 +2,7 @@ import base64
2
2
  import json
3
3
  import time
4
4
  from dataclasses import dataclass
5
- from typing import Generator, Optional
5
+ from typing import Dict, Generator, Optional
6
6
 
7
7
  from httpx import Auth, Request, Response, post
8
8
 
@@ -45,6 +45,15 @@ class BearerToken(Auth):
45
45
  self.workspace_name = workspace_name
46
46
  self.base_url = base_url
47
47
 
48
+ def get_headers(self) -> Dict[str, str]:
49
+ err = self.refresh_if_needed()
50
+ if err:
51
+ raise err
52
+ return {
53
+ 'X-Beamlit-Authorization': f'Bearer {self.credentials.access_token}',
54
+ 'X-Beamlit-Workspace': self.workspace_name
55
+ }
56
+
48
57
  def refresh_if_needed(self) -> Optional[Exception]:
49
58
  # Need to refresh token if expires in less than 10 minutes
50
59
  parts = self.credentials.access_token.split('.')
beamlit/common/logger.py CHANGED
@@ -19,6 +19,8 @@ class ColoredFormatter(logging.Formatter):
19
19
  def init(log_level: str):
20
20
  logging.getLogger("uvicorn.access").handlers.clear()
21
21
  logging.getLogger("uvicorn.access").propagate = False
22
+ logging.getLogger("uvicorn.error").handlers.clear()
23
+ logging.getLogger("uvicorn.error").propagate = False
22
24
  logging.getLogger("httpx").handlers.clear()
23
25
  logging.getLogger("httpx").propagate = False
24
26
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: beamlit
3
- Version: 0.0.20rc4
3
+ Version: 0.0.20rc5
4
4
  Summary: Add your description here
5
5
  Author-email: cploujoux <ch.ploujoux@gmail.com>
6
6
  Requires-Python: >=3.12
@@ -125,14 +125,14 @@ beamlit/api/workspaces/list_workspaces.py,sha256=FnmUumyrJeA-akmKDoz0K_DRiv-iiF_
125
125
  beamlit/api/workspaces/remove_workspace_user.py,sha256=AxEG15Vwe-dFspQD21pYqEjsY-RO0_K-eoLpdkY-VEc,2667
126
126
  beamlit/api/workspaces/update_workspace.py,sha256=qa5DV2UJSUYuB_ibALb4E9ghKpT1HaEIzIb9MOcDKv4,4241
127
127
  beamlit/api/workspaces/update_workspace_user_role.py,sha256=Yn9iuJ4tKtauzBiJyU4-wYUMS9g98X2Om8zs7UkzrY8,4917
128
- beamlit/authentication/__init__.py,sha256=4XS2flLWtu6deM9lE_dAVOMsNF-YzRofu2K0jvW6igw,872
129
- beamlit/authentication/apikey.py,sha256=HvqWEd2IqcUuISvftqpi_lhd2fTQDHTf8M4O_k7HerU,489
130
- beamlit/authentication/authentication.py,sha256=Al_ioKYVfGdS9urfENFqE12drzChD6l3sGWM68jHfXA,1219
131
- beamlit/authentication/clientcredentials.py,sha256=OUzV_Kc5A2BIteM5u8r26NwQMs8oTHPqz9qAkSxwxH0,3744
132
- beamlit/authentication/credentials.py,sha256=Ro7Pb_GRNuLF9MuDdOhRolnksnIFIWn5KPRNnT7c7_w,4830
133
- beamlit/authentication/device_mode.py,sha256=Y4WVDH6guhdQKn8zIV5s93VWvtAIn4BsTikq_UnZw4c,3409
128
+ beamlit/authentication/__init__.py,sha256=H3_0gARm3kJxKp-rZRGOCSlJcoeWYI_aw7T6u1LPxcc,1050
129
+ beamlit/authentication/apikey.py,sha256=qU4NRCgXT9GFJIBGyOcouuNwswMIkk_CQi1gOXrtXgw,658
130
+ beamlit/authentication/authentication.py,sha256=PyxPN8RgteT8MBtPgN2mD0Bc5IpRMljEL_E8mroNdH0,2310
131
+ beamlit/authentication/clientcredentials.py,sha256=i7ko_-vAkPvRoFKxIWX4N7bbjXfXinbZFdJPP2weA4M,4015
132
+ beamlit/authentication/credentials.py,sha256=IsmRbQth95my9kkWCpoPKZLLWDpIUwn5OaGIkK8keeA,4831
133
+ beamlit/authentication/device_mode.py,sha256=cN_bBer0YwNZD1L0_RvW2TL1YveOhJ4L_bIAF5m__iA,3702
134
134
  beamlit/common/generate.py,sha256=C6Z0ifDwrSMrtrHwgC8YQm0JklsDaPCkagzpK9v9SrQ,7172
135
- beamlit/common/logger.py,sha256=zuUVHsSSwH0REij0rDhBgZ0U7YvToDQu-SVS6ZBIDUg,948
135
+ beamlit/common/logger.py,sha256=6VnjHuFHfHQEbWZyDEoPCdArVzhVL7rDGF65ZjXj7aM,1061
136
136
  beamlit/common/settings.py,sha256=FoOymkCcrwzya55ZOxOnNdMePYWBAgMTHxmPxHWGXAE,4186
137
137
  beamlit/common/utils.py,sha256=0KaC8vMa0AyIm4jTNgAJSsOYA1b191Q8AUF1up1RxFs,634
138
138
  beamlit/models/__init__.py,sha256=Jv0iTOtTs9G2zQRjbCmDjmNz8T9fX-MHoSt3b3zlRcI,8929
@@ -277,6 +277,6 @@ beamlit/models/websocket_channel.py,sha256=tyNtsVR0cOwd6BK--ehBCH8bIjxtyPhiAkrxY
277
277
  beamlit/models/workspace.py,sha256=5l6-YSgpEgZEyVoBX3PvE5HVO07j7pe3ZA1jdOBR-Fs,3998
278
278
  beamlit/models/workspace_labels.py,sha256=crX235uLVWlu_R3Y4t5AiELY0OJukNAUF9_RO3mZaj8,1252
279
279
  beamlit/models/workspace_user.py,sha256=yCGwPQsVkbGMDkxbATMoEYRxkdx9yIJSsAunVbf8-14,3429
280
- beamlit-0.0.20rc4.dist-info/METADATA,sha256=gNKtjfqwFOBhTLehc4mKL63lTzmlS8dEmqq3_DkeIVE,1746
281
- beamlit-0.0.20rc4.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
282
- beamlit-0.0.20rc4.dist-info/RECORD,,
280
+ beamlit-0.0.20rc5.dist-info/METADATA,sha256=NBnYBiQDiZepBdzW_VLxiLL7XeXhFIc90G2O8ulpC_0,1746
281
+ beamlit-0.0.20rc5.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
282
+ beamlit-0.0.20rc5.dist-info/RECORD,,