licos-dev-cli 0.3.9__tar.gz → 0.4.0__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.
- {licos_dev_cli-0.3.9 → licos_dev_cli-0.4.0}/PKG-INFO +2 -2
- {licos_dev_cli-0.3.9 → licos_dev_cli-0.4.0}/pyproject.toml +2 -2
- {licos_dev_cli-0.3.9 → licos_dev_cli-0.4.0}/src/licos_dev_cli/main.py +83 -8
- {licos_dev_cli-0.3.9 → licos_dev_cli-0.4.0}/tests/test_document_read_cli.py +49 -0
- {licos_dev_cli-0.3.9 → licos_dev_cli-0.4.0}/.gitignore +0 -0
- {licos_dev_cli-0.3.9 → licos_dev_cli-0.4.0}/src/licos_dev_cli/__init__.py +0 -0
- {licos_dev_cli-0.3.9 → licos_dev_cli-0.4.0}/src/licos_dev_cli/ppt_master.py +0 -0
- {licos_dev_cli-0.3.9 → licos_dev_cli-0.4.0}/tests/test_cli_output_paths.py +0 -0
- {licos_dev_cli-0.3.9 → licos_dev_cli-0.4.0}/tests/test_credit_check.py +0 -0
- {licos_dev_cli-0.3.9 → licos_dev_cli-0.4.0}/tests/test_ppt_master_cli.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: licos-dev-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: LICOS Dev CLI - generate files and call model capabilities
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Requires-Dist: click>=8.1
|
|
7
|
-
Requires-Dist: licos-dev-sdk>=0.
|
|
7
|
+
Requires-Dist: licos-dev-sdk>=0.4.0
|
|
@@ -4,11 +4,11 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "licos-dev-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "LICOS Dev CLI - generate files and call model capabilities"
|
|
9
9
|
requires-python = ">=3.10"
|
|
10
10
|
dependencies = [
|
|
11
|
-
"licos-dev-sdk>=0.
|
|
11
|
+
"licos-dev-sdk>=0.4.0",
|
|
12
12
|
"click>=8.1",
|
|
13
13
|
]
|
|
14
14
|
|
|
@@ -251,16 +251,41 @@ def docx_template(template_path, input_path, data_content, filename, output_dir)
|
|
|
251
251
|
_echo_path(path)
|
|
252
252
|
|
|
253
253
|
|
|
254
|
+
@cli.command("docx-edit")
|
|
255
|
+
@click.option("-s", "--source", "source_path", required=True, type=click.Path(exists=True, dir_okay=False))
|
|
256
|
+
@click.option("-i", "--input", "input_path", help="JSON operation file")
|
|
257
|
+
@click.option("-d", "--data", "data_content", help="JSON operation array")
|
|
258
|
+
@click.option("-f", "--filename", required=True)
|
|
259
|
+
@click.option("-o", "--output-dir", default=None)
|
|
260
|
+
def docx_edit(source_path, input_path, data_content, filename, output_dir):
|
|
261
|
+
"""Edit native tables in an existing DOCX package."""
|
|
262
|
+
from licos_dev_sdk import edit_docx
|
|
263
|
+
|
|
264
|
+
payload = _read_json(input_path, data_content)
|
|
265
|
+
operations = payload.get("operations") if isinstance(payload, dict) else payload
|
|
266
|
+
if not isinstance(operations, list):
|
|
267
|
+
raise click.BadParameter("operations must be a JSON array or an object containing operations")
|
|
268
|
+
path = edit_docx(source_path, operations, filename, output_dir=output_dir)
|
|
269
|
+
_echo_path(path)
|
|
270
|
+
|
|
271
|
+
|
|
254
272
|
@cli.command("docx-read")
|
|
255
273
|
@click.option("-f", "--file", "file_path", required=True, type=click.Path(exists=True, dir_okay=False))
|
|
256
274
|
@click.option("--offset", type=click.IntRange(min=1), default=1, show_default=True)
|
|
257
275
|
@click.option("--limit", type=click.IntRange(min=1), default=20, show_default=True)
|
|
258
276
|
@click.option("--max-chars", type=click.IntRange(min=256), default=8_000, show_default=True)
|
|
259
|
-
|
|
277
|
+
@click.option("--include-styles", is_flag=True, help="Include paragraph, run, row, and cell styles")
|
|
278
|
+
def docx_read(file_path, offset, limit, max_chars, include_styles):
|
|
260
279
|
"""Read DOCX paragraphs and table rows as paginated JSON."""
|
|
261
280
|
from licos_dev_sdk import read_docx
|
|
262
281
|
|
|
263
|
-
report = read_docx(
|
|
282
|
+
report = read_docx(
|
|
283
|
+
file_path,
|
|
284
|
+
offset=offset,
|
|
285
|
+
limit=limit,
|
|
286
|
+
max_chars=max_chars,
|
|
287
|
+
include_styles=include_styles,
|
|
288
|
+
)
|
|
264
289
|
report["path"] = _path_to_cli_output(report["path"])
|
|
265
290
|
_echo_json(report)
|
|
266
291
|
|
|
@@ -275,11 +300,41 @@ def docx_read(file_path, offset, limit, max_chars):
|
|
|
275
300
|
@click.option("--sheet-name", default="Sheet1")
|
|
276
301
|
@click.option("--header-color", default="4472C4")
|
|
277
302
|
@click.option("--theme", default="professional-blue", help="Theme: professional-blue|business|neutral")
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
303
|
+
@click.option("--format", "content_type", type=click.Choice(["json", "html", "docx"]), default="json", show_default=True)
|
|
304
|
+
@click.option("--column", "columns", multiple=True, help="Exact DOCX table header; repeat for each output column")
|
|
305
|
+
def xlsx(input_path, content, filename, output_dir, sheet_name, header_color, theme, content_type, columns):
|
|
306
|
+
"""Generate native XLSX from JSON, HTML, or selected DOCX table columns."""
|
|
307
|
+
if content_type == "docx":
|
|
308
|
+
from licos_dev_sdk import create_xlsx_from_docx
|
|
309
|
+
|
|
310
|
+
if not input_path:
|
|
311
|
+
raise click.BadParameter("--input is required for DOCX input", param_hint="--input")
|
|
312
|
+
if content is not None:
|
|
313
|
+
raise click.BadParameter("--content is not supported for DOCX input", param_hint="--content")
|
|
314
|
+
if not columns:
|
|
315
|
+
raise click.BadParameter("at least one --column is required for DOCX input", param_hint="--column")
|
|
316
|
+
path = create_xlsx_from_docx(
|
|
317
|
+
input_path,
|
|
318
|
+
columns,
|
|
319
|
+
filename,
|
|
320
|
+
output_dir=output_dir,
|
|
321
|
+
sheet_name=sheet_name,
|
|
322
|
+
theme=theme,
|
|
323
|
+
)
|
|
324
|
+
elif content_type == "html":
|
|
325
|
+
from licos_dev_sdk import create_xlsx_from_html
|
|
326
|
+
|
|
327
|
+
path = create_xlsx_from_html(
|
|
328
|
+
_read_input(input_path, content),
|
|
329
|
+
filename,
|
|
330
|
+
output_dir=output_dir,
|
|
331
|
+
sheet_name=sheet_name,
|
|
332
|
+
)
|
|
333
|
+
else:
|
|
334
|
+
from licos_dev_sdk import create_xlsx
|
|
335
|
+
|
|
336
|
+
data = _read_json(input_path, content)
|
|
337
|
+
path = create_xlsx(data, filename, output_dir=output_dir, sheet_name=sheet_name, header_color=header_color, theme=theme)
|
|
283
338
|
_echo_path(path)
|
|
284
339
|
|
|
285
340
|
|
|
@@ -324,7 +379,8 @@ def xlsx_inspect(file_path):
|
|
|
324
379
|
@click.option("--offset", type=click.IntRange(min=1), default=1, show_default=True)
|
|
325
380
|
@click.option("--limit", type=click.IntRange(min=1), default=20, show_default=True)
|
|
326
381
|
@click.option("--max-chars", type=click.IntRange(min=256), default=8_000, show_default=True)
|
|
327
|
-
|
|
382
|
+
@click.option("--include-styles", is_flag=True, help="Include cell number, font, fill, and alignment styles")
|
|
383
|
+
def xlsx_read(file_path, sheet, cell_range, offset, limit, max_chars, include_styles):
|
|
328
384
|
"""List XLSX worksheets or read rows from a selected worksheet."""
|
|
329
385
|
from licos_dev_sdk import read_xlsx
|
|
330
386
|
|
|
@@ -335,11 +391,30 @@ def xlsx_read(file_path, sheet, cell_range, offset, limit, max_chars):
|
|
|
335
391
|
offset=offset,
|
|
336
392
|
limit=limit,
|
|
337
393
|
max_chars=max_chars,
|
|
394
|
+
include_styles=include_styles,
|
|
338
395
|
)
|
|
339
396
|
report["path"] = _path_to_cli_output(report["path"])
|
|
340
397
|
_echo_json(report)
|
|
341
398
|
|
|
342
399
|
|
|
400
|
+
@cli.command("xlsx-edit")
|
|
401
|
+
@click.option("-s", "--source", "source_path", required=True, type=click.Path(exists=True, dir_okay=False))
|
|
402
|
+
@click.option("-i", "--input", "input_path", help="JSON operation file")
|
|
403
|
+
@click.option("-d", "--data", "data_content", help="JSON operation array")
|
|
404
|
+
@click.option("-f", "--filename", required=True)
|
|
405
|
+
@click.option("-o", "--output-dir", default=None)
|
|
406
|
+
def xlsx_edit(source_path, input_path, data_content, filename, output_dir):
|
|
407
|
+
"""Edit an existing native XLSX workbook."""
|
|
408
|
+
from licos_dev_sdk import edit_xlsx
|
|
409
|
+
|
|
410
|
+
payload = _read_json(input_path, data_content)
|
|
411
|
+
operations = payload.get("operations") if isinstance(payload, dict) else payload
|
|
412
|
+
if not isinstance(operations, list):
|
|
413
|
+
raise click.BadParameter("operations must be a JSON array or an object containing operations")
|
|
414
|
+
path = edit_xlsx(source_path, operations, filename, output_dir=output_dir)
|
|
415
|
+
_echo_path(path)
|
|
416
|
+
|
|
417
|
+
|
|
343
418
|
# ── CSV ──────────────────────────────────────────────────────────────────────
|
|
344
419
|
|
|
345
420
|
@cli.command()
|
|
@@ -46,3 +46,52 @@ def test_xlsx_read_without_sheet_returns_workbook_structure(tmp_path: Path):
|
|
|
46
46
|
payload = json.loads(result.output)
|
|
47
47
|
assert payload["mode"] == "workbook_overview"
|
|
48
48
|
assert payload["sheet_names"] == ["Overview", "Details"]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_xlsx_command_extracts_selected_docx_columns(tmp_path: Path, monkeypatch):
|
|
52
|
+
from docx import Document
|
|
53
|
+
from openpyxl import load_workbook
|
|
54
|
+
|
|
55
|
+
project = tmp_path / "projects"
|
|
56
|
+
project.mkdir()
|
|
57
|
+
source = project / "source.docx"
|
|
58
|
+
document = Document()
|
|
59
|
+
table = document.add_table(rows=2, cols=4)
|
|
60
|
+
for column, value in enumerate(["序号", "名称", "单位", "数量"]):
|
|
61
|
+
table.cell(0, column).text = value
|
|
62
|
+
for column, value in enumerate(["1", "泵", "台", "2"]):
|
|
63
|
+
table.cell(1, column).text = value
|
|
64
|
+
document.save(source)
|
|
65
|
+
monkeypatch.setenv("LICOS_PROJECT_PATH", str(project))
|
|
66
|
+
|
|
67
|
+
result = CliRunner().invoke(
|
|
68
|
+
cli,
|
|
69
|
+
[
|
|
70
|
+
"xlsx",
|
|
71
|
+
"--format",
|
|
72
|
+
"docx",
|
|
73
|
+
"--input",
|
|
74
|
+
str(source),
|
|
75
|
+
"--column",
|
|
76
|
+
"名称",
|
|
77
|
+
"--column",
|
|
78
|
+
"单位",
|
|
79
|
+
"--column",
|
|
80
|
+
"数量",
|
|
81
|
+
"--filename",
|
|
82
|
+
"result",
|
|
83
|
+
"--output-dir",
|
|
84
|
+
str(project),
|
|
85
|
+
],
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
assert result.exit_code == 0, result.output
|
|
89
|
+
assert result.output.strip() == "result.xlsx"
|
|
90
|
+
workbook = load_workbook(project / "result.xlsx")
|
|
91
|
+
try:
|
|
92
|
+
assert list(workbook.active.values) == [
|
|
93
|
+
("名称", "单位", "数量"),
|
|
94
|
+
("泵", "台", "2"),
|
|
95
|
+
]
|
|
96
|
+
finally:
|
|
97
|
+
workbook.close()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|