lkr-dev-cli 0.0.30__py3-none-any.whl → 0.0.31__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.
lkr/tools/classes.py CHANGED
@@ -1,6 +1,5 @@
1
1
  from typing import Literal, Optional, Self, cast
2
2
 
3
- from fastapi import Request
4
3
  from looker_sdk.sdk.api40.methods import Looker40SDK
5
4
  from looker_sdk.sdk.api40.models import (
6
5
  UserAttributeGroupValue,
@@ -46,10 +45,12 @@ class UserAttributeUpdater(BaseModel):
46
45
  )
47
46
  return self
48
47
 
49
- def get_request_authorization_for_value(self, request: Request):
50
- authorization_token = request.headers.get("Authorization")
48
+ def get_request_authorization_for_value(self, headers: list[tuple[str, str]]):
49
+ authorization_token = next(
50
+ (header for header in headers if header[0] == "Authorization"), None
51
+ )
51
52
  if authorization_token:
52
- self.value = authorization_token
53
+ self.value = authorization_token[1]
53
54
  else:
54
55
  logger.error("No authorization token found")
55
56
 
lkr/tools/main.py CHANGED
@@ -22,7 +22,7 @@ def user_attribute_updater(
22
22
  @api.post("/identity_token")
23
23
  def identity_token(request: Request, body: UserAttributeUpdater):
24
24
  try:
25
- body.get_request_authorization_for_value(request)
25
+ body.get_request_authorization_for_value(request.headers.items())
26
26
  body.update_user_attribute_value()
27
27
  raw_urls = os.getenv("LOOKER_WHITELISTED_BASE_URLS", "")
28
28
  whitelisted_base_urls = (
@@ -1,23 +1,32 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lkr-dev-cli
3
- Version: 0.0.30
3
+ Version: 0.0.31
4
4
  Summary: lkr: a command line interface for looker
5
5
  Author: bwebs
6
6
  License-Expression: MIT
7
7
  License-File: LICENSE
8
8
  Requires-Python: >=3.12
9
9
  Requires-Dist: cryptography>=42.0.0
10
- Requires-Dist: duckdb>=1.2.2
11
- Requires-Dist: fastapi>=0.115.12
12
10
  Requires-Dist: looker-sdk>=25.4.0
13
- Requires-Dist: mcp[cli]>=1.9.2
14
11
  Requires-Dist: pydantic>=2.11.4
15
12
  Requires-Dist: pydash>=8.0.5
16
13
  Requires-Dist: questionary>=2.1.0
17
14
  Requires-Dist: requests>=2.31.0
18
- Requires-Dist: selenium>=4.32.0
19
15
  Requires-Dist: structlog>=25.3.0
20
16
  Requires-Dist: typer>=0.15.2
17
+ Provides-Extra: all
18
+ Requires-Dist: duckdb>=1.2.2; extra == 'all'
19
+ Requires-Dist: fastapi>=0.115.12; extra == 'all'
20
+ Requires-Dist: mcp[cli]>=1.9.2; extra == 'all'
21
+ Requires-Dist: selenium>=4.32.0; extra == 'all'
22
+ Provides-Extra: embed-observability
23
+ Requires-Dist: fastapi>=0.115.12; extra == 'embed-observability'
24
+ Requires-Dist: selenium>=4.32.0; extra == 'embed-observability'
25
+ Provides-Extra: mcp
26
+ Requires-Dist: duckdb>=1.2.2; extra == 'mcp'
27
+ Requires-Dist: mcp[cli]>=1.9.2; extra == 'mcp'
28
+ Provides-Extra: user-attribute-updater
29
+ Requires-Dist: fastapi>=0.115.12; extra == 'user-attribute-updater'
21
30
  Description-Content-Type: text/markdown
22
31
 
23
32
  # lkr cli
@@ -214,10 +223,13 @@ This can also be used to stress test your Looker environment as it serves an API
214
223
  ## User Attribute Updater (OIDC Token)
215
224
 
216
225
  1. Create a new cloud run using the `lkr-cli` public docker image `us-central1-docker.pkg.dev/lkr-dev-production/lkr-cli/cli:latest`
217
- 2. Put in the environment variables LOOKERSDK_CLIENT_ID, LOOKERSDK_CLIENT_SECRET, LOOKERSDK_BASE_URL, LOOKER_WHITELISTED_BASE_URLS. The `LOOKER_WHITELISTED_BASE_URLS` would be the same url as the `LOOKERSDK_BASE_URL` if you are only using this for a single Looker instance. For more advanced use cases, you can set the `LOOKER_WHITELISTED_BASE_URLS` to a comma separated list of urls. The body of the request also accepts a `base_url`, `client_id`, and `client_secret` key that will override these settings.
218
- 3. Deploy the cloud run
219
- 4. Retrieve the URL of the cloud run
220
- 5. Create the user attribute
226
+ 2. Put in the environment variables LOOKERSDK_CLIENT_ID, LOOKERSDK_CLIENT_SECRET, LOOKERSDK_BASE_URL, LOOKER_WHITELISTED_BASE_URLS. The `LOOKER_WHITELISTED_BASE_URLS` would be the same url as the `LOOKERSDK_BASE_URL` if you are only using this for a single Looker instance. For more advanced use cases, you can set the `LOOKER_WHITELISTED_BASE_URLS` to a comma separated list of urls. The body of the request also accepts a `base_url`, `client_id`, and `client_secret` key that will override these settings. See example [`gcloud` command](#example-gcloud-command)
227
+ 3. For the command and arguments use:
228
+ - command: `lkr`
229
+ - args: `tools` `user-attribute-updater`
230
+ 4. Deploy the cloud run
231
+ 5. Retrieve the URL of the cloud run
232
+ 6. Create the user attribute
221
233
  - Name: cloud_run_access_token
222
234
  - Data Type: String
223
235
  - User Access: None
@@ -250,6 +262,23 @@ This can also be used to stress test your Looker environment as it serves an API
250
262
  9. Check the logs of the cloud run to see if there was a 200 response
251
263
 
252
264
 
265
+ ### Example `gcloud` command
266
+ ```bash
267
+ export REGION=<your region>
268
+ export PROJECT=<your project id>
269
+
270
+ gcloud run deploy lkr-access-token-updater \
271
+ --image us-central1-docker.pkg.dev/lkr-dev-production/lkr-cli/cli:latest \
272
+ --command lkr \
273
+ --args tools,user-attribute-updater \
274
+ --platform managed \
275
+ --region $REGION \
276
+ --project $PROJECT \
277
+ --cpu 1 \
278
+ --memory 2Gi \
279
+ --set-env-vars LOOKERSDK_CLIENT_ID=<your client id>,LOOKERSDK_CLIENT_SECRET=<your client secret>,LOOKERSDK_BASE_URL=<your instance url>,LOOKER_WHITELISTED_BASE_URLS=<your instance url>
280
+ ```
281
+
253
282
  ## UserAttributeUpdater `lkr-dev-cli`
254
283
 
255
284
  Exported from the `lkr-dev-cli` package is the `UserAttributeUpdater` pydantic class. This class has all the necessary logic to update a user attribute value.
@@ -301,12 +330,12 @@ from lkr import UserAttributeUpdater
301
330
  def request_authorization(request: Request):
302
331
  body = await request.json()
303
332
  updater = UserAttributeUpdater.model_validate(body)
304
- updater.get_request_authorization_for_value(request)
333
+ updater.get_request_authorization_for_value(request.headers.items())
305
334
  updater.update_user_attribute_value()
306
335
 
307
336
  @app.post("/as_body")
308
337
  def as_body(request: Request, body: UserAttributeUpdater):
309
- body.get_request_authorization_for_value(request)
338
+ body.get_request_authorization_for_value(request.headers.items())
310
339
  body.update_user_attribute_value()
311
340
 
312
341
  @app.post("/assigning_value")
@@ -317,4 +346,64 @@ def assigning_value(request: Request):
317
346
  )
318
347
  updater.value = request.headers.get("my_custom_header")
319
348
  updater.update_user_attribute_value()
349
+
350
+ @app.delete("/:user_attribute_name/:email")
351
+ def delete_user_attribute(user_attribute_name: str, email: str):
352
+ updater = UserAttributeUpdater(
353
+ user_attribute=user_attribute_name,
354
+ update_type="user",
355
+ email=email,
356
+ )
357
+ updater.delete_user_attribute_value()
358
+
359
+ ## Optional Dependencies
360
+
361
+ The `lkr` CLI supports optional dependencies that enable additional functionality. You can install these individually or all at once.
362
+
363
+ ### Available Extras
364
+
365
+ - **`mcp`**: Enables the MCP (Model Context Protocol) server functionality
366
+ - Includes: `mcp[cli]>=1.9.2`, `duckdb>=1.2.2`
367
+ - **`embed-observability`**: Enables the observability embed monitoring features
368
+ - Includes: `fastapi>=0.115.12`, `selenium>=4.32.0`
369
+ - **`user-attribute-updater`**: Enables the user attribute updater functionality
370
+ - Includes: `fastapi>=0.115.12`
371
+
372
+ ### Installing Optional Dependencies
373
+
374
+ **Install all optional dependencies:**
375
+ ```bash
376
+ uv sync --extra all
377
+ ```
378
+
379
+ **Install specific extras:**
380
+ ```bash
381
+ # Install MCP functionality
382
+ uv sync --extra mcp
383
+
384
+ # Install observability features
385
+ uv sync --extra embed-observability
386
+
387
+ # Install user attribute updater
388
+ uv sync --extra user-attribute-updater
389
+
390
+ # Install multiple extras
391
+ uv sync --extra mcp --extra embed-observability
392
+ ```
393
+
394
+ **Using pip:**
395
+ ```bash
396
+ # Install all optional dependencies
397
+ pip install lkr-dev-cli[all]
398
+
399
+ # Install specific extras
400
+ pip install lkr-dev-cli[mcp,embed-observability,user-attribute-updater]
320
401
  ```
402
+
403
+ ### What Each Extra Enables
404
+
405
+ - **`mcp`**: Use the MCP server with tools like Cursor for enhanced IDE integration
406
+ - **`embed-observability`**: Run the observability embed server for monitoring Looker dashboard performance
407
+ - **`user-attribute-updater`**: Deploy the user attribute updater service for OIDC token management
408
+
409
+ All extras are designed to work together seamlessly, and installing `all` is equivalent to installing all individual extras.
@@ -16,10 +16,10 @@ lkr/observability/classes.py,sha256=LgGuUnY-J1csPrlAKnw4PPOqOfbvaOx2cxENlQgJYcE,
16
16
  lkr/observability/embed_container.html,sha256=IcDG-QVsYYNGQGrkDrx9OMZ2Pmo4C8oAjRHddFQ7Tlw,2939
17
17
  lkr/observability/main.py,sha256=XbejIdqhNNUMqHVezb5EnLaJ32dO9-Bt0o5d8lc0kyw,9544
18
18
  lkr/observability/utils.py,sha256=UpaBrp_ufaXLoz4p3xG3K6lHKBpP9wBhvP8rDmeGoWg,2148
19
- lkr/tools/classes.py,sha256=tKwHSr5X8SRL-fnBolqV5xe5A4_B8bEeh9UU7glq4wo,7459
20
- lkr/tools/main.py,sha256=W9Q0Qq8rZNmhpAdOvJLm1iWeHBPAIBsIAxod6noskU8,2667
21
- lkr_dev_cli-0.0.30.dist-info/METADATA,sha256=3StSuRBhzSNF-9nlKhsoSvvkXkGmX5Ynl1AFv0Or-Ss,15407
22
- lkr_dev_cli-0.0.30.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
- lkr_dev_cli-0.0.30.dist-info/entry_points.txt,sha256=nn2sFMGDpwUVE61ZUpbDPnQZkW7Gc08nV-tyLGo8q34,37
24
- lkr_dev_cli-0.0.30.dist-info/licenses/LICENSE,sha256=hKnCOORW1JRE_M2vStz8dblS5u1iR-2VpqS9xagKNa0,1063
25
- lkr_dev_cli-0.0.30.dist-info/RECORD,,
19
+ lkr/tools/classes.py,sha256=ZyRRCQjjwV4WVWGmKlTfXiLiOGUf67XgrboYhOLuLts,7508
20
+ lkr/tools/main.py,sha256=u9O5JgGVFscav9wFcrHd5ZPUUue_KpeK0QukYKqzros,2683
21
+ lkr_dev_cli-0.0.31.dist-info/METADATA,sha256=8QimDm78NO_wvLUt3XJ_SlwdMkCY3pk5Jt8KY1FuGxo,18527
22
+ lkr_dev_cli-0.0.31.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ lkr_dev_cli-0.0.31.dist-info/entry_points.txt,sha256=nn2sFMGDpwUVE61ZUpbDPnQZkW7Gc08nV-tyLGo8q34,37
24
+ lkr_dev_cli-0.0.31.dist-info/licenses/LICENSE,sha256=hKnCOORW1JRE_M2vStz8dblS5u1iR-2VpqS9xagKNa0,1063
25
+ lkr_dev_cli-0.0.31.dist-info/RECORD,,