tinybird 0.0.1.dev216__py3-none-any.whl → 0.0.1.dev220__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.

Potentially problematic release.


This version of tinybird might be problematic. Click here for more details.

@@ -242,3 +242,16 @@ FORBIDDEN_SQL_KEYWORDS = {
242
242
 
243
243
  CH_SETTINGS_JOIN_ALGORITHM_HASH = "hash" # uses 'hash' by default, https://clickhouse.com/docs/en/operations/settings/settings/#settings-join_algorithm
244
244
  CH_SETTINGS_JOIN_ALGORITHM_AUTO = "auto,hash"
245
+
246
+ VALID_QUERY_FORMATS = (
247
+ "JSON",
248
+ "CSV",
249
+ "CSVWithNames",
250
+ "TSV",
251
+ "TSVWithNames",
252
+ "PrettyCompact",
253
+ "JSONEachRow",
254
+ "Parquet",
255
+ "JSONStrings",
256
+ "Prometheus",
257
+ )
@@ -1710,6 +1710,8 @@ def parse(
1710
1710
  "s3_access_key": assign_var("s3_access_key"),
1711
1711
  "s3_secret": assign_var("s3_secret"),
1712
1712
  "gcs_service_account_credentials_json": assign_var_json("gcs_service_account_credentials_json"),
1713
+ "gcs_hmac_access_id": assign_var("gcs_hmac_access_id"),
1714
+ "gcs_hmac_secret": assign_var("gcs_hmac_secret"),
1713
1715
  "include": include,
1714
1716
  },
1715
1717
  }
tinybird/prompts.py CHANGED
@@ -1,3 +1,4 @@
1
+ from datetime import date
1
2
  from typing import Optional
2
3
 
3
4
  general_functions = [
@@ -453,6 +454,8 @@ Use the following format to generate the response and do not wrap it in any othe
453
454
 
454
455
 
455
456
  def mock_prompt(rows: int, feedback: str = "") -> str:
457
+ today = date.today().isoformat()
458
+
456
459
  if feedback:
457
460
  feedback = f"""In case the <feedback> tag is present and not empty,
458
461
  it means there was a previous attempt to generate the resources and the system provided feedback about the previous response.
@@ -495,6 +498,10 @@ FROM numbers({rows})
495
498
  - The query MUST return a sample of EXACTLY {rows} rows.
496
499
  - The query MUST be valid for clickhouse and Tinybird.
497
500
  - FROM numbers({rows}) part is mandatory.
501
+ - If json paths are present (e.g. `userAgent` String `json:$.userAgent`), rely on the json paths to generate the sample record.
502
+ - If the schema has nested json paths (e.g. `json:$.location.country`), generate nested JSON objects accordingly.
503
+ - When working with dates, take into account that the current date is {today}.
504
+ - Use recent dates to avoid generating dates that are too far in the past.
498
505
  - Do NOT include ```clickhouse or ```sql or any other wrapping text to the sql query.
499
506
  - Do NOT use any of these functions: elementAt
500
507
  - Do NOT add a semicolon at the end of the query
@@ -539,58 +546,55 @@ SELECT
539
546
  arrayMap(x -> concat('item_', toString(x)), range(1, rand() % 5 + 1)) AS items
540
547
  FROM numbers(ROWS)
541
548
 
542
- ## Example schema with a nested JSON field:
549
+ ## Example schema with nested JSON paths:
543
550
 
544
551
  ### Schema:
545
552
 
546
553
  SCHEMA >
547
- `request_id` String `json:$.request_id`,
548
554
  `timestamp` DateTime `json:$.timestamp`,
549
- `model` String `json:$.request.model`,
550
- `temperature` Float32 `json:$.request.options.temperature`,
551
- `max_tokens` UInt32 `json:$.request.options.max_tokens`,
552
- `stream` UInt8 `json:$.request.options.stream`
553
-
554
- ### Desired final output of the query:
555
-
556
- Note that the important part is generating the nested fields:
557
- json:$.request.options.max_tokens > this means that the max_tokens field is nested inside the options field inside the request field.
558
-
555
+ `location_country` String `json:$.location.country`,
556
+ `location_region` String `json:$.location.region`,
557
+ `location_city` String `json:$.location.city`,
558
+ `location_latitude` String `json:$.location.latitude`,
559
+ `location_longitude` String `json:$.location.longitude`
560
+
561
+ ### Important: Understanding JSON paths
562
+ When you see json paths like `json:$.location.country`, it means the data should be structured as nested JSON:
563
+ - `json:$.location.country` the country field is nested inside the location object
564
+ - `json:$.location.region` → the region field is nested inside the location object
565
+
566
+ ### Desired final output structure:
559
567
  {{
560
- "request_id": "req_abc123",
561
568
  "timestamp": "2024-11-30T10:30:00.000Z",
562
- "request": {{
563
- "model": "gpt-4",
564
- "options": {{
565
- "temperature": 0.7,
566
- "max_tokens": 1000,
567
- "stream": false
568
- }}
569
+ "location": {{
570
+ "country": "United States",
571
+ "region": "California",
572
+ "city": "San Francisco",
573
+ "latitude": "37.7749",
574
+ "longitude": "-122.4194"
569
575
  }}
570
576
  }}
571
577
 
572
- ### Example SQL output with nested fields:
578
+ ### Example SQL output for nested JSON paths:
573
579
 
574
580
  SELECT
575
- request_id,
576
581
  timestamp,
577
582
  CAST(concat('{{
578
- "model": "', model, '",
579
- "options": {{
580
- "temperature": ', temperature, ',
581
- "max_tokens": ', max_tokens, ',
582
- "stream": ', IF(stream = 1, 'true', 'false'), '
583
- }}
584
- }}'), 'JSON') AS request
583
+ "country": "', country, '",
584
+ "region": "', region, '",
585
+ "city": "', city, '",
586
+ "latitude": "', latitude, '",
587
+ "longitude": "', longitude, '"
588
+ }}'), 'JSON') AS location
585
589
  FROM
586
590
  (
587
591
  SELECT
588
- concat('req_', lower(hex(randomString(6)))) AS request_id,
589
- (now() - toIntervalDay(rand() % 30)) + toIntervalSecond(rand() % 86400) AS timestamp,
590
- ['gpt-4', 'gpt-3.5-turbo', 'gpt-4-turbo'][(rand() % 3) + 1] AS model,
591
- round(rand() / 10, 2) AS temperature,
592
- 500 + (rand() % 2500) AS max_tokens,
593
- rand() % 2 AS stream
592
+ now() - rand() % 86400 AS timestamp,
593
+ ['United States', 'Canada', 'United Kingdom', 'Germany', 'France'][(rand() % 5) + 1] AS country,
594
+ ['California', 'Texas', 'New York', 'Ontario', 'London'][(rand() % 5) + 1] AS region,
595
+ ['San Francisco', 'Los Angeles', 'New York', 'Toronto', 'London'][(rand() % 5) + 1] AS city,
596
+ toString(round(rand() * 180 - 90, 4)) AS latitude,
597
+ toString(round(rand() * 360 - 180, 4)) AS longitude
594
598
  FROM numbers(ROWS)
595
599
  )
596
600
  </more_examples>
tinybird/tb/__cli__.py CHANGED
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
4
4
  __url__ = 'https://www.tinybird.co/docs/forward/commands'
5
5
  __author__ = 'Tinybird'
6
6
  __author_email__ = 'support@tinybird.co'
7
- __version__ = '0.0.1.dev216'
8
- __revision__ = 'b1646cc'
7
+ __version__ = '0.0.1.dev220'
8
+ __revision__ = 'd9c7b3e'
@@ -379,6 +379,15 @@ async def create_ctx_client(ctx: Context, config: Dict[str, Any], cloud: bool, s
379
379
  click.echo(
380
380
  FeedbackManager.gray(message=f"Running against Tinybird Cloud: Workspace {config.get('name', 'default')}")
381
381
  )
382
+
383
+ method = None
384
+ if ctx.params.get("token"):
385
+ method = "token via --token option"
386
+ elif os.environ.get("TB_TOKEN"):
387
+ method = "token from TB_TOKEN environment variable"
388
+ if method:
389
+ click.echo(FeedbackManager.gray(message=f"Authentication method: {method}"))
390
+
382
391
  return _get_tb_client(config.get("token", None), config["host"], staging=staging)
383
392
  local = command in commands_always_local
384
393
  test = command in command_always_test
@@ -101,7 +101,7 @@ async def create(
101
101
  if prompt:
102
102
  prompt_result = await create_resources_from_prompt(tb_client, user_token, prompt, project)
103
103
  result.extend(prompt_result)
104
- readme_path = Path(root_folder) / "README.md"
104
+ readme_path = folder_path / "README.md"
105
105
  if readme_path.exists():
106
106
  click.echo(FeedbackManager.highlight(message="\n» Updating project description..."))
107
107
  else:
@@ -98,8 +98,9 @@ async def stop() -> None:
98
98
 
99
99
 
100
100
  @local.command()
101
+ @click.pass_context
101
102
  @coro
102
- async def status() -> None:
103
+ async def status(ctx: click.Context) -> None:
103
104
  """Check status of Tinybird Local"""
104
105
  docker_client = get_docker_client()
105
106
  container = get_existing_container_with_matching_env(docker_client, TB_CONTAINER_NAME, {})
@@ -110,6 +111,11 @@ async def status() -> None:
110
111
 
111
112
  if status == "running" and health == "healthy":
112
113
  click.echo(FeedbackManager.success(message="✓ Tinybird Local is ready!"))
114
+ click.echo(FeedbackManager.highlight(message="\n» Tinybird Local:"))
115
+ from tinybird.tb.modules.info import get_local_info
116
+
117
+ config = ctx.ensure_object(dict).get("config", {})
118
+ await get_local_info(config)
113
119
  elif status == "restarting" or (status == "running" and health == "starting"):
114
120
  click.echo(FeedbackManager.highlight(message="* Tinybird Local is starting..."))
115
121
  elif status == "removing":
@@ -288,14 +288,25 @@ async def clear_workspace() -> None:
288
288
 
289
289
  ws = next((ws for ws in local_workspaces if ws["name"] == ws_name), None)
290
290
 
291
+ if not ws:
292
+ raise CLIWorkspaceException(FeedbackManager.error(message=f"Workspace '{ws_name}' not found."))
293
+
294
+ requests.delete(f"{TB_LOCAL_ADDRESS}/v1/workspaces/{ws['id']}?token={user_token}&hard_delete_confirmation=yes") # noqa: ASYNC210
295
+ user_workspaces = await user_client.user_workspaces(version="v1")
296
+ ws = next((ws for ws in user_workspaces["workspaces"] if ws["name"] == ws_name), None)
297
+
291
298
  if ws:
292
- requests.delete(f"{TB_LOCAL_ADDRESS}/v1/workspaces/{ws['id']}?token={user_token}&hard_delete_confirmation=yes") # noqa: ASYNC210
293
- ws = None
299
+ raise CLIWorkspaceException(
300
+ FeedbackManager.error(message=f"Workspace '{ws_name}' was not cleared properly. Please try again.")
301
+ )
302
+
303
+ await user_client.create_workspace(ws_name, assign_to_organization_id=user_org_id, version="v1")
304
+ user_workspaces = requests.get(f"{TB_LOCAL_ADDRESS}/v1/user/workspaces?token={admin_token}").json() # noqa: ASYNC210
305
+ ws = next((ws for ws in user_workspaces["workspaces"] if ws["name"] == ws_name), None)
294
306
 
295
307
  if not ws:
296
- await user_client.create_workspace(ws_name, assign_to_organization_id=user_org_id, version="v1")
297
- user_workspaces = requests.get(f"{TB_LOCAL_ADDRESS}/v1/user/workspaces?token={admin_token}").json() # noqa: ASYNC210
298
- ws = next((ws for ws in user_workspaces["workspaces"] if ws["name"] == ws_name), None)
308
+ raise CLIWorkspaceException(
309
+ FeedbackManager.error(message=f"Workspace '{ws_name}' was not cleared properly. Please try again.")
310
+ )
299
311
 
300
- if ws:
301
- click.echo(FeedbackManager.success(message=f"\n✓ Workspace '{ws_name}' cleared"))
312
+ click.echo(FeedbackManager.success(message=f"✓ Workspace '{ws_name}' cleared"))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird
3
- Version: 0.0.1.dev216
3
+ Version: 0.0.1.dev220
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/forward/commands
6
6
  Author: Tinybird
@@ -3,33 +3,33 @@ tinybird/context.py,sha256=FfqYfrGX_I7PKGTQo93utaKPDNVYWelg4Hsp3evX5wM,1291
3
3
  tinybird/datatypes.py,sha256=r4WCvspmrXTJHiPjjyOTiZyZl31FO3Ynkwq4LQsYm6E,11059
4
4
  tinybird/feedback_manager.py,sha256=1INQFfRfuMCb9lfB8KNf4r6qC2khW568hoHjtk-wshI,69305
5
5
  tinybird/git_settings.py,sha256=Sw_8rGmribEFJ4Z_6idrVytxpFYk7ez8ei0qHULzs3E,3934
6
- tinybird/prompts.py,sha256=ZdpY7FyJh9vg7SfZkR0h5h-dy2VecbBMkli3nI7-eVo,38006
6
+ tinybird/prompts.py,sha256=6lr5EaSUzdh7dqOg2BFba8q8HKy3rfFG5SNw1rnAdtA,38656
7
7
  tinybird/sql.py,sha256=BufnOgclQokDyihtuXesOwHBsebN6wRXIxO5wKRkOwE,48299
8
8
  tinybird/sql_template.py,sha256=WjsTBjpQLVBHGZbY2dZuhZUurFR-rbJ_KRRy5vx4Y5E,99967
9
9
  tinybird/sql_template_fmt.py,sha256=KUHdj5rYCYm_rKKdXYSJAE9vIyXUQLB0YSZnUXHeBlY,10196
10
10
  tinybird/sql_toolset.py,sha256=M2rpLYkgV2W8NnYEYPC1tJdpy4uZHXVF64NBSKLQka4,19549
11
11
  tinybird/syncasync.py,sha256=IPnOx6lMbf9SNddN1eBtssg8vCLHMt76SuZ6YNYm-Yk,27761
12
12
  tinybird/tornado_template.py,sha256=jjNVDMnkYFWXflmT8KU_Ssbo5vR8KQq3EJMk5vYgXRw,41959
13
- tinybird/ch_utils/constants.py,sha256=aYvg2C_WxYWsnqPdZB1ZFoIr8ZY-XjUXYyHKE9Ansj0,3890
13
+ tinybird/ch_utils/constants.py,sha256=F19-_nQ7uNmayD0T9pO1Qu7bh9MFowwj0b6ATH45vwk,4083
14
14
  tinybird/ch_utils/engine.py,sha256=X4tE9OrfaUy6kO9cqVEzyI9cDcmOF3IAssRRzsTsfEQ,40781
15
- tinybird/datafile/common.py,sha256=JPhLqYfmGYCc5dln7zMbr4m2TvUwbqZTxmC_pF5BzJY,91534
15
+ tinybird/datafile/common.py,sha256=9hC1APatnfFeYXyTm_s47VmXP0JUajvpkw1vsrSXo70,91664
16
16
  tinybird/datafile/exceptions.py,sha256=8rw2umdZjtby85QbuRKFO5ETz_eRHwUY5l7eHsy1wnI,556
17
17
  tinybird/datafile/parse_connection.py,sha256=tRyn2Rpr1TeWet5BXmMoQgaotbGdYep1qiTak_OqC5E,1825
18
18
  tinybird/datafile/parse_datasource.py,sha256=ssW8QeFSgglVFi3sDZj_HgkJiTJ2069v2JgqnH3CkDE,1825
19
19
  tinybird/datafile/parse_pipe.py,sha256=xf4m0Tw44QWJzHzAm7Z7FwUoUUtr7noMYjU1NiWnX0k,3880
20
- tinybird/tb/__cli__.py,sha256=mA8tARgcpYXiyhPqdbnpYFDjf_bvSisl_rENpsTa58Y,247
20
+ tinybird/tb/__cli__.py,sha256=Tub058Oz-n2aVt35P5GpJu4UOrSf1cvZsXjKxAWsm10,247
21
21
  tinybird/tb/check_pypi.py,sha256=i3l2L8IajeB7sreikR7oPlYJki9MtS3c_M4crnmbByc,760
22
22
  tinybird/tb/cli.py,sha256=0xYk2Ip4vb3nNFbxfTdG3VoIgdRvUKVbUVU_mviErPA,1107
23
23
  tinybird/tb/client.py,sha256=FKj61vY9STPW03kfVcxYuY1_csI-kP-mc1ERQfqJtg8,56505
24
24
  tinybird/tb/config.py,sha256=jT9xndpeCY_g0HdB5qE2EquC0TFRRnkPnQFWZWd04jo,3998
25
25
  tinybird/tb/modules/build.py,sha256=T36msoBK5g9AZlrJnFRPvlZbrdE265LY1q3Y4YqvS3w,20067
26
26
  tinybird/tb/modules/cicd.py,sha256=Njb6eZOHHbUkoJJx6KoixO9PsfA_T-3Ybkya9-50Ca8,7328
27
- tinybird/tb/modules/cli.py,sha256=k6Bp-lWC-ruMMB47lxwsinLQt4qJL_n84hjyxi9JYt4,15676
27
+ tinybird/tb/modules/cli.py,sha256=zTUob6oSZszCx-lk6MJbQ_VuNOXBo8b0DOHPWezzMOg,15997
28
28
  tinybird/tb/modules/common.py,sha256=WWvbDSQmyYUy9Xyc_BqtrdRzpDdzLuE9i_pWhoA1a8k,83440
29
29
  tinybird/tb/modules/config.py,sha256=VnzYVUo4q1RBEEMMce4_OCrKp4erhgkRPHElydVlKj0,11488
30
30
  tinybird/tb/modules/connection.py,sha256=rdEsdcP-AqyHiW3KNoETGPeTjk7Wt3It6z_SnmInGcc,18648
31
31
  tinybird/tb/modules/copy.py,sha256=zHN1d5NA-MFsgbk2kKJq2P9qA8dNOnIsIa60QpVnSwc,4458
32
- tinybird/tb/modules/create.py,sha256=sncG6iaeS_AApY1EmmfYEdj9B6-1CPZJzvTmfJQj_Rc,22112
32
+ tinybird/tb/modules/create.py,sha256=l3Q3QG8R-CXP-gj5rIXI3uD9tPBnQmzdklgkxt_ggNY,22106
33
33
  tinybird/tb/modules/datasource.py,sha256=jpe5-C-rZ5Dnitwo_t84OPqS_bV44Sz1y1u85-2djnQ,39362
34
34
  tinybird/tb/modules/deployment.py,sha256=ByXIgEvwxB49pJEKKj0EJIfORWyflCYr04k8961nBkA,28391
35
35
  tinybird/tb/modules/deprecations.py,sha256=rrszC1f_JJeJ8mUxGoCxckQTJFBCR8wREf4XXXN-PRc,4507
@@ -42,7 +42,7 @@ tinybird/tb/modules/infra.py,sha256=fve30Gj3mG9zbquGxS2e4ipcOYOxviWQCpNFfEzJN_Q,
42
42
  tinybird/tb/modules/job.py,sha256=AsUCRNzy7HG5oJ4fyk9NpIm5NtNJgBZSy8MtJdXBe5A,3167
43
43
  tinybird/tb/modules/llm.py,sha256=KfsCYmKeW1VQz0iDZhGKCRkQv_Y3kTHh6JuxvofOguE,1076
44
44
  tinybird/tb/modules/llm_utils.py,sha256=nS9r4FAElJw8yXtmdYrx-rtI2zXR8qXfi1QqUDCfxvg,3469
45
- tinybird/tb/modules/local.py,sha256=mLSgMMP3H1MdanVLsFZieeqOANSnctPLey3pJ_L1ZBI,5807
45
+ tinybird/tb/modules/local.py,sha256=TWT7pGXQ3cOy0M_piyw7WhrzoxZE18PmfOLzHD5CoEc,6096
46
46
  tinybird/tb/modules/local_common.py,sha256=8CSEVygFi0fIISatYxCStcHizugXCA9WNTLO_zDKmXw,17195
47
47
  tinybird/tb/modules/login.py,sha256=qfY17J3FryTPl8A0ucQgxiyJ7jLy81qHdlHXgqohi0c,10170
48
48
  tinybird/tb/modules/logout.py,sha256=sniI4JNxpTrVeRCp0oGJuQ3yRerG4hH5uz6oBmjv724,1009
@@ -60,7 +60,7 @@ tinybird/tb/modules/telemetry.py,sha256=T9gtsQffWqG_4hRBaUJPzOfMkPwz7mH-R6Bn1XRY
60
60
  tinybird/tb/modules/test.py,sha256=XakpYi0Q2gGKItpPdtRVLKzQldkvCPqzPhwwbUxyrmc,13292
61
61
  tinybird/tb/modules/token.py,sha256=2fmKwu10_M0pqs6YmJVeILR9ZQB0ejRAET86agASbKM,13488
62
62
  tinybird/tb/modules/watch.py,sha256=HhruZoUrehlxL_nFIK3BlpHp2uyzKAM9cmNXBCa4Zgs,8965
63
- tinybird/tb/modules/workspace.py,sha256=WDi3Vu9t60b4Ht5vbPsakUErFmsECtFRcfXb1l300xc,11057
63
+ tinybird/tb/modules/workspace.py,sha256=ngn5yGG9K9sFaUzm0W42j_vQnm3pQS2Jh38GNgbMtP0,11607
64
64
  tinybird/tb/modules/workspace_members.py,sha256=RYLpyPM1ECCasHRg3uvpckzXplX0_KgNFsSPZn_i6qk,8744
65
65
  tinybird/tb/modules/datafile/build.py,sha256=SinuhM61FKdEt0MTV_4qfJFQ78dYndcmWHf_LMGe7Z8,51351
66
66
  tinybird/tb/modules/datafile/build_common.py,sha256=LU24kAQmxDJIyoIapDaYG-SU3P4FrMG9UBf8m9PgVSI,4565
@@ -82,8 +82,8 @@ tinybird/tb_cli_modules/config.py,sha256=IsgdtFRnUrkY8-Zo32lmk6O7u3bHie1QCxLwgp4
82
82
  tinybird/tb_cli_modules/exceptions.py,sha256=pmucP4kTF4irIt7dXiG-FcnI-o3mvDusPmch1L8RCWk,3367
83
83
  tinybird/tb_cli_modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
84
84
  tinybird/tb_cli_modules/telemetry.py,sha256=Hh2Io8ZPROSunbOLuMvuIFU4TqwWPmQTqal4WS09K1A,10449
85
- tinybird-0.0.1.dev216.dist-info/METADATA,sha256=OFw1ggbnDCkrP-xifq_bE75sbm4GxpPP5CEK0KjDAG0,1682
86
- tinybird-0.0.1.dev216.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
87
- tinybird-0.0.1.dev216.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
88
- tinybird-0.0.1.dev216.dist-info/top_level.txt,sha256=VqqqEmkAy7UNaD8-V51FCoMMWXjLUlR0IstvK7tJYVY,54
89
- tinybird-0.0.1.dev216.dist-info/RECORD,,
85
+ tinybird-0.0.1.dev220.dist-info/METADATA,sha256=2cTr-wmJ-MMHiCt8oqOc45VR0WMwEDu5HE0kotkXWaQ,1682
86
+ tinybird-0.0.1.dev220.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
87
+ tinybird-0.0.1.dev220.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
88
+ tinybird-0.0.1.dev220.dist-info/top_level.txt,sha256=VqqqEmkAy7UNaD8-V51FCoMMWXjLUlR0IstvK7tJYVY,54
89
+ tinybird-0.0.1.dev220.dist-info/RECORD,,