maxc-cli 0.4.0__tar.gz → 0.4.2__tar.gz

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.
Files changed (95) hide show
  1. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/PKG-INFO +1 -1
  2. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/setup.py +1 -1
  3. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/__init__.py +1 -1
  4. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/app.py +12 -3
  5. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/backend/data.py +31 -0
  6. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/cli.py +16 -0
  7. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli.egg-info/PKG-INFO +1 -1
  8. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/MANIFEST.in +0 -0
  9. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/README.md +0 -0
  10. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/pyproject.toml +0 -0
  11. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/scripts/pyinstaller_entry.py +0 -0
  12. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/scripts/regression_test.py +0 -0
  13. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/setup.cfg +0 -0
  14. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/__main__.py +0 -0
  15. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/_samples.py +0 -0
  16. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/agent_platforms.py +0 -0
  17. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/audit.py +0 -0
  18. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/auth_providers.py +0 -0
  19. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/backend/__init__.py +0 -0
  20. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/backend/auth.py +0 -0
  21. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/backend/catalog.py +0 -0
  22. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/backend/job.py +0 -0
  23. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/backend/meta.py +0 -0
  24. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/backend/odps.py +0 -0
  25. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/backend/query.py +0 -0
  26. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/cache.py +0 -0
  27. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/catalog_bootstrap.py +0 -0
  28. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/config.py +0 -0
  29. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/exceptions.py +0 -0
  30. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/help_format.py +0 -0
  31. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/helpers.py +0 -0
  32. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/masking.py +0 -0
  33. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/models.py +0 -0
  34. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/output.py +0 -0
  35. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/setting_parser.py +0 -0
  36. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/SKILL.md +0 -0
  37. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/agents/openai.yaml +0 -0
  38. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/bootstrap-auth.md +0 -0
  39. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/bootstrap-flow.md +0 -0
  40. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/command-patterns.md +0 -0
  41. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/json-output-format.md +0 -0
  42. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/maxcompute-select-guide.md +0 -0
  43. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/maxcompute-sql-notes.md +0 -0
  44. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/migrate-from-odpscmd.md +0 -0
  45. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/partition-guide.md +0 -0
  46. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/red-lines.md +0 -0
  47. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/setup-install.md +0 -0
  48. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/sql-common-errors.md +0 -0
  49. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/sql-query-patterns.md +0 -0
  50. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/skills/references/text2sql-principles.md +0 -0
  51. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/store.py +0 -0
  52. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli/utils.py +0 -0
  53. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli.egg-info/SOURCES.txt +0 -0
  54. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli.egg-info/dependency_links.txt +0 -0
  55. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli.egg-info/entry_points.txt +0 -0
  56. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli.egg-info/requires.txt +0 -0
  57. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/src/maxc_cli.egg-info/top_level.txt +0 -0
  58. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_agent_hints_and_cli.py +0 -0
  59. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_agent_platforms.py +0 -0
  60. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_agent_skill_commands.py +0 -0
  61. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_agent_skill_commands_context.py +0 -0
  62. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_backend_data.py +0 -0
  63. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_backend_data_serialization.py +0 -0
  64. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_backend_meta.py +0 -0
  65. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_build_release_script.py +0 -0
  66. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_cache.py +0 -0
  67. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_catalog.py +0 -0
  68. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_catalog_bootstrap.py +0 -0
  69. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_cli_arg_validation.py +0 -0
  70. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_cli_mock.py +0 -0
  71. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_cli_query_parse_and_sanitize.py +0 -0
  72. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_compat.py +0 -0
  73. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_e2e_smoke.py +0 -0
  74. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_envelope_shape.py +0 -0
  75. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_error_self_correction.py +0 -0
  76. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_error_translation.py +0 -0
  77. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_exit_codes.py +0 -0
  78. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_external_auth.py +0 -0
  79. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_flag_hoist.py +0 -0
  80. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_help_format.py +0 -0
  81. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_help_version_e2e.py +0 -0
  82. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_helpers.py +0 -0
  83. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_helpers_csv.py +0 -0
  84. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_integration.py +0 -0
  85. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_integration_real.py +0 -0
  86. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_job_improvements.py +0 -0
  87. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_masking.py +0 -0
  88. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_meta_schema_and_partition_cols.py +0 -0
  89. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_phase1_improvements.py +0 -0
  90. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_pyinstaller_bundle.py +0 -0
  91. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_query_auto_promote.py +0 -0
  92. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_query_result_csv_fallback.py +0 -0
  93. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_setting_parser.py +0 -0
  94. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_skill_cli_consistency.py +0 -0
  95. {maxc_cli-0.4.0 → maxc_cli-0.4.2}/tests/test_skill_renderer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maxc-cli
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Agent-native MaxCompute CLI for external coding agents
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: Programming Language :: Python :: 3.9
@@ -9,7 +9,7 @@ README = ROOT / "README.md"
9
9
 
10
10
  setup(
11
11
  name="maxc-cli",
12
- version="0.4.0",
12
+ version="0.4.2",
13
13
  description="Agent-native MaxCompute CLI for external coding agents",
14
14
  long_description=README.read_text(encoding="utf-8"),
15
15
  long_description_content_type="text/markdown",
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.4.0"
5
+ __version__ = "0.4.2"
@@ -607,6 +607,7 @@ class MaxCApp:
607
607
  cost_check: 'float | None' = None,
608
608
  idempotency_key: 'str | None' = None,
609
609
  force: 'bool' = False,
610
+ dry_run: 'bool' = False,
610
611
  ) -> 'Envelope':
611
612
  return self.query(
612
613
  command="job.submit",
@@ -617,6 +618,7 @@ class MaxCApp:
617
618
  cost_check=cost_check,
618
619
  idempotency_key=idempotency_key,
619
620
  force=force,
621
+ dry_run=dry_run,
620
622
  )
621
623
 
622
624
  def job_status(self, job_id: 'str') -> 'Envelope':
@@ -2465,6 +2467,7 @@ class MaxCApp:
2465
2467
  block_size: 'int' = 10000,
2466
2468
  project: 'str | None' = None,
2467
2469
  schema: 'str | None' = None,
2470
+ dry_run: 'bool' = False,
2468
2471
  ) -> 'Envelope':
2469
2472
  target_project = project or self.config.default_project
2470
2473
  result = self.backend.upload_table(
@@ -2473,6 +2476,7 @@ class MaxCApp:
2473
2476
  delimiter=delimiter, has_header=has_header,
2474
2477
  null_marker=null_marker, block_size=block_size,
2475
2478
  project=project, schema=schema,
2479
+ dry_run=dry_run,
2476
2480
  )
2477
2481
  metadata = {
2478
2482
  "project": target_project,
@@ -2480,16 +2484,21 @@ class MaxCApp:
2480
2484
  "delimiter": delimiter,
2481
2485
  "block_size": block_size,
2482
2486
  }
2487
+ if dry_run:
2488
+ actions = [action("data.upload", data=result, metadata=metadata)]
2489
+ insights = ["Dry-run validated table schema and CSV file. Re-run without --dry-run to upload."]
2490
+ else:
2491
+ actions = [action("data.sample", data=result, metadata=metadata)]
2492
+ insights = []
2483
2493
  envelope = Envelope(
2484
2494
  command="data.upload",
2485
2495
  status="success",
2486
2496
  data=result,
2487
2497
  metadata=metadata,
2488
2498
  agent_hints=AgentHints(
2489
- actions=[
2490
- action("data.sample", data=result, metadata=metadata),
2491
- ],
2499
+ actions=actions,
2492
2500
  warnings=result.get("warnings", []),
2501
+ insights=insights,
2493
2502
  ),
2494
2503
  )
2495
2504
  self.log("data.upload", envelope.status, envelope.metadata)
@@ -228,6 +228,7 @@ class DataMixin:
228
228
  block_size: 'int' = 10000,
229
229
  project: 'str | None' = None,
230
230
  schema: 'str | None' = None,
231
+ dry_run: 'bool' = False,
231
232
  ) -> 'dict[str, Any]':
232
233
  """Upload a CSV/TSV file into an existing table or partition via Tunnel.
233
234
 
@@ -295,6 +296,36 @@ class DataMixin:
295
296
  )
296
297
 
297
298
  bytes_read = os.path.getsize(file_path)
299
+
300
+ if dry_run:
301
+ warnings: list[str] = []
302
+ rows_found = 0
303
+ with open(file_path, encoding="utf-8", newline="") as fh:
304
+ reader = csv.reader(fh, delimiter=delimiter)
305
+ if has_header:
306
+ try:
307
+ header = next(reader)
308
+ except StopIteration:
309
+ header = []
310
+ column_mapping = _resolve_header_mapping(header, data_columns, warnings)
311
+ else:
312
+ column_mapping = [c.name for c in data_columns]
313
+ for _ in reader:
314
+ rows_found += 1
315
+ warnings.append("Dry-run: file and table schema validated, no data was uploaded.")
316
+ return {
317
+ "table": definition.name,
318
+ "applied_partition": partition,
319
+ "rows_written": 0,
320
+ "rows_found": rows_found,
321
+ "bytes_read": bytes_read,
322
+ "column_mapping": column_mapping,
323
+ "blocks": 0,
324
+ "overwrite": overwrite,
325
+ "dry_run": True,
326
+ "warnings": warnings,
327
+ }
328
+
298
329
  block_ids: list[int] = []
299
330
  rows_written = 0
300
331
  warnings: list[str] = []
@@ -250,6 +250,7 @@ def build_parser() -> argparse.ArgumentParser:
250
250
  job_submit.add_argument("--max-rows", type=positive_int, default=100, help="Maximum rows to return (default: 100)")
251
251
  job_submit.add_argument("--cost-check", type=float, help="Abort if estimated cost exceeds threshold (CU)")
252
252
  job_submit.add_argument("--idempotency-key", help="Deduplication key for retries")
253
+ job_submit.add_argument("--dry-run", action="store_true", help="Estimate cost without submitting")
253
254
  job_submit.add_argument("--force", action="store_true", default=False, help=argparse.SUPPRESS)
254
255
  job_submit.set_defaults(handler=_handle_job_submit)
255
256
 
@@ -453,6 +454,7 @@ def build_parser() -> argparse.ArgumentParser:
453
454
  data_upload.add_argument("--schema", help="Schema name (overrides session default)")
454
455
  data_upload.add_argument("--block-size", type=positive_int, default=10000,
455
456
  help="Rows per Tunnel block (default: 10000)")
457
+ data_upload.add_argument("--dry-run", action="store_true", help="Validate table and CSV without uploading")
456
458
  data_upload.add_argument("--project", help="Target MaxCompute project")
457
459
  data_upload.add_argument("--json", action="store_true", help="Output as JSON envelope")
458
460
  data_upload.set_defaults(handler=_handle_data_upload)
@@ -775,8 +777,20 @@ def _configure_stdio_encoding() -> None:
775
777
  pass
776
778
 
777
779
 
780
+ def _configure_user_agent() -> None:
781
+ from . import __version__
782
+ try:
783
+ from odps import options
784
+ except ImportError:
785
+ return
786
+ options.user_agent_pattern = (
787
+ f"maxc-cli/{__version__} $pyodps_version $python_version $os_version"
788
+ )
789
+
790
+
778
791
  def main(argv: Sequence[str] | None = None) -> int:
779
792
  _configure_stdio_encoding()
793
+ _configure_user_agent()
780
794
  return run(argv=argv)
781
795
 
782
796
 
@@ -1088,6 +1102,7 @@ def _handle_job_submit(app: MaxCApp, args: argparse.Namespace, stdout: TextIO) -
1088
1102
  cost_check=args.cost_check,
1089
1103
  idempotency_key=args.idempotency_key,
1090
1104
  force=args.force,
1105
+ dry_run=args.dry_run,
1091
1106
  )
1092
1107
  _emit_envelope(envelope, args=args, stdout=stdout, default_format="json")
1093
1108
 
@@ -1360,6 +1375,7 @@ def _handle_data_upload(app: MaxCApp, args: argparse.Namespace, stdout: TextIO)
1360
1375
  block_size=args.block_size,
1361
1376
  project=args.project,
1362
1377
  schema=getattr(args, "schema", None),
1378
+ dry_run=args.dry_run,
1363
1379
  )
1364
1380
  _emit_envelope(envelope, args=args, stdout=stdout, default_format="json")
1365
1381
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maxc-cli
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Agent-native MaxCompute CLI for external coding agents
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: Programming Language :: Python :: 3.9
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes