mtchart-sdk 0.1.0__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.
@@ -0,0 +1,31 @@
1
+ from mtchart_sdk.models import (
2
+ PartItem,
3
+ PenConfig,
4
+ ProcessInput,
5
+ ProcessRecord,
6
+ ReadingEvaluation,
7
+ )
8
+ from mtchart_sdk.rules import (
9
+ calculate_exit_timing,
10
+ clean_identifier,
11
+ evaluate_temperature,
12
+ normalize_item,
13
+ total_quantity,
14
+ )
15
+ from mtchart_sdk.service import MTChartService
16
+ from mtchart_sdk.storage import PartsCatalog
17
+
18
+ __all__ = [
19
+ "MTChartService",
20
+ "PartItem",
21
+ "PartsCatalog",
22
+ "PenConfig",
23
+ "ProcessInput",
24
+ "ProcessRecord",
25
+ "ReadingEvaluation",
26
+ "calculate_exit_timing",
27
+ "clean_identifier",
28
+ "evaluate_temperature",
29
+ "normalize_item",
30
+ "total_quantity",
31
+ ]
mtchart_sdk/cli.py ADDED
@@ -0,0 +1,87 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ from datetime import datetime
6
+ from pathlib import Path
7
+
8
+ from mtchart_sdk.models import PartItem, PenConfig, ProcessInput
9
+ from mtchart_sdk.service import MTChartService
10
+
11
+
12
+ def _build_parser() -> argparse.ArgumentParser:
13
+ parser = argparse.ArgumentParser(
14
+ prog="mtchart-sdk-demo",
15
+ description="Executa uma demonstracao local do MTChart SDK.",
16
+ )
17
+ parser.add_argument("--catalog-db", default="mtchart_sdk_demo.db", help="Caminho do catalogo SQLite.")
18
+ parser.add_argument("--report-number", default="CH-DEMO-001", help="Numero do relatorio.")
19
+ parser.add_argument("--project", default="OS-DEMO", help="Projeto ou ordem de servico.")
20
+ parser.add_argument("--process-name", default="Alivio de fragilizacao", help="Nome do processo.")
21
+ parser.add_argument("--oven", default="Forno Demo", help="Nome do forno.")
22
+ parser.add_argument("--relief-hours", type=float, default=3.0, help="Horas de permanencia do processo.")
23
+ parser.add_argument("--pen-id", default="1", help="Identificador da pena.")
24
+ parser.add_argument("--target", type=float, default=189.0, help="Temperatura alvo para iniciar processo.")
25
+ parser.add_argument("--low-limit", type=float, default=175.9, help="Limite inferior de temperatura.")
26
+ parser.add_argument("--high-limit", type=float, default=220.0, help="Limite superior de temperatura.")
27
+ parser.add_argument("--value", default="188.7", help="Leitura de temperatura a avaliar.")
28
+ parser.add_argument("--part-name", default="Suporte Demo", help="Nome da peca.")
29
+ parser.add_argument("--pn", default="PN-DEMO-001", help="Part number da peca.")
30
+ parser.add_argument("--sn", default="SN-DEMO-001", help="Serial number da peca.")
31
+ parser.add_argument("--qty", type=int, default=1, help="Quantidade da peca.")
32
+ return parser
33
+
34
+
35
+ def run_demo(args: argparse.Namespace) -> dict[str, object]:
36
+ service = MTChartService(catalog_db=Path(args.catalog_db))
37
+ started_at = datetime.now().replace(microsecond=0)
38
+ process = service.create_process(
39
+ ProcessInput(
40
+ report_number=args.report_number,
41
+ project=args.project,
42
+ process_name=args.process_name,
43
+ oven=args.oven,
44
+ relief_hours=args.relief_hours,
45
+ pen=PenConfig(
46
+ id=args.pen_id,
47
+ name=f"Pena {args.pen_id}",
48
+ stabilization_target=args.target,
49
+ low_limit=args.low_limit,
50
+ high_limit=args.high_limit,
51
+ ),
52
+ items=[
53
+ PartItem(
54
+ name=args.part_name,
55
+ pn=args.pn,
56
+ sn=args.sn,
57
+ qty=args.qty,
58
+ )
59
+ ],
60
+ started_at=started_at,
61
+ )
62
+ )
63
+ reading = service.evaluate_reading(process, args.value, now=started_at)
64
+ return {
65
+ "report_number": process.report_number,
66
+ "project": process.project,
67
+ "expected_exit_at": process.expected_exit_at.isoformat(),
68
+ "total_quantity": process.total_quantity,
69
+ "reading": {
70
+ "value": reading.value,
71
+ "status": reading.status,
72
+ "can_start_process": reading.can_start_process,
73
+ "remaining_seconds": reading.remaining_seconds,
74
+ },
75
+ "catalog_matches": service.search_parts(args.pn, limit=5),
76
+ }
77
+
78
+
79
+ def main(argv: list[str] | None = None) -> int:
80
+ parser = _build_parser()
81
+ result = run_demo(parser.parse_args(argv))
82
+ print(json.dumps(result, indent=2, ensure_ascii=False))
83
+ return 0
84
+
85
+
86
+ if __name__ == "__main__":
87
+ raise SystemExit(main())
mtchart_sdk/models.py ADDED
@@ -0,0 +1,63 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+ from datetime import datetime
5
+ from typing import Any
6
+
7
+
8
+ @dataclass(frozen=True)
9
+ class PartItem:
10
+ name: str = ""
11
+ pn: str = ""
12
+ sn: str = ""
13
+ qty: int = 1
14
+ project: str = ""
15
+
16
+
17
+ @dataclass(frozen=True)
18
+ class PenConfig:
19
+ id: str
20
+ name: str = ""
21
+ stabilization_target: float | None = None
22
+ low_limit: float | None = None
23
+ high_limit: float | None = None
24
+ tolerance: float = 0.5
25
+
26
+
27
+ @dataclass(frozen=True)
28
+ class ProcessInput:
29
+ report_number: str
30
+ project: str
31
+ process_name: str
32
+ oven: str
33
+ relief_hours: float
34
+ pen: PenConfig
35
+ items: list[PartItem | dict[str, Any]] = field(default_factory=list)
36
+ started_at: datetime | None = None
37
+ metadata: dict[str, Any] = field(default_factory=dict)
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class ProcessRecord:
42
+ report_number: str
43
+ project: str
44
+ process_name: str
45
+ oven: str
46
+ relief_hours: float
47
+ pen: PenConfig
48
+ items: list[PartItem]
49
+ started_at: datetime
50
+ expected_exit_at: datetime
51
+ total_quantity: int
52
+ metadata: dict[str, Any] = field(default_factory=dict)
53
+
54
+
55
+ @dataclass(frozen=True)
56
+ class ReadingEvaluation:
57
+ value: float | None
58
+ status: str
59
+ is_numeric: bool
60
+ is_within_limits: bool
61
+ is_low_temperature: bool
62
+ can_start_process: bool
63
+ remaining_seconds: float
mtchart_sdk/rules.py ADDED
@@ -0,0 +1,101 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from datetime import datetime, timedelta
5
+ from typing import Any
6
+
7
+ from mtchart_sdk.models import PartItem, PenConfig, ReadingEvaluation
8
+
9
+
10
+ def to_float_or_none(value: Any) -> float | None:
11
+ try:
12
+ if value in ("", None):
13
+ return None
14
+ return float(value)
15
+ except (TypeError, ValueError):
16
+ return None
17
+
18
+
19
+ def clean_identifier(value: Any) -> str:
20
+ text = str(value or "").strip()
21
+ return re.sub(r"^\s*(PN|P/N|LOTE|BATCH)\s*:\s*", "", text, flags=re.IGNORECASE).strip()
22
+
23
+
24
+ def normalize_item(item: PartItem | dict[str, Any] | str) -> PartItem:
25
+ if isinstance(item, PartItem):
26
+ return item
27
+ if isinstance(item, dict):
28
+ try:
29
+ qty = max(1, int(str(item.get("qty", 1)).strip() or "1"))
30
+ except (TypeError, ValueError):
31
+ qty = 1
32
+ return PartItem(
33
+ name=str(item.get("name", item.get("nome", ""))).strip(),
34
+ pn=clean_identifier(item.get("pn", "")),
35
+ sn=str(item.get("sn", "")).strip(),
36
+ qty=qty,
37
+ project=str(item.get("project", item.get("projeto", ""))).strip(),
38
+ )
39
+ return PartItem(sn=str(item or "").strip())
40
+
41
+
42
+ def total_quantity(items: list[PartItem | dict[str, Any] | str]) -> int:
43
+ return sum(normalize_item(item).qty for item in items or [])
44
+
45
+
46
+ def calculate_exit_timing(started_at: datetime, relief_hours: float, now: datetime | None = None) -> tuple[datetime, float]:
47
+ now = now or datetime.now()
48
+ expected_exit_at = started_at + timedelta(hours=float(relief_hours or 0))
49
+ return expected_exit_at, (expected_exit_at - now).total_seconds()
50
+
51
+
52
+ def evaluate_temperature(
53
+ value: Any,
54
+ pen: PenConfig,
55
+ started_at: datetime,
56
+ relief_hours: float,
57
+ now: datetime | None = None,
58
+ ) -> ReadingEvaluation:
59
+ numeric_value = to_float_or_none(value)
60
+ expected_exit_at, remaining_seconds = calculate_exit_timing(started_at, relief_hours, now)
61
+ del expected_exit_at
62
+
63
+ if numeric_value is None:
64
+ return ReadingEvaluation(
65
+ value=None,
66
+ status="N/A",
67
+ is_numeric=False,
68
+ is_within_limits=False,
69
+ is_low_temperature=False,
70
+ can_start_process=False,
71
+ remaining_seconds=remaining_seconds,
72
+ )
73
+
74
+ low_limit = pen.low_limit
75
+ high_limit = pen.high_limit
76
+ has_low = low_limit is not None
77
+ has_high = high_limit is not None
78
+ is_low = has_low and numeric_value < float(low_limit)
79
+ is_high = has_high and numeric_value > float(high_limit)
80
+ is_within = not is_low and not is_high
81
+ target = pen.stabilization_target
82
+ can_start = target is not None and numeric_value >= float(target) - float(pen.tolerance)
83
+
84
+ if is_low:
85
+ status = "LOW"
86
+ elif is_high:
87
+ status = "HIGH"
88
+ elif is_within:
89
+ status = "OK"
90
+ else:
91
+ status = "UNKNOWN"
92
+
93
+ return ReadingEvaluation(
94
+ value=numeric_value,
95
+ status=status,
96
+ is_numeric=True,
97
+ is_within_limits=is_within,
98
+ is_low_temperature=is_low,
99
+ can_start_process=can_start,
100
+ remaining_seconds=remaining_seconds,
101
+ )
mtchart_sdk/service.py ADDED
@@ -0,0 +1,51 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import datetime
4
+ from pathlib import Path
5
+
6
+ from mtchart_sdk.models import PartItem, ProcessInput, ProcessRecord, ReadingEvaluation
7
+ from mtchart_sdk.rules import calculate_exit_timing, evaluate_temperature, normalize_item, total_quantity
8
+ from mtchart_sdk.storage import PartsCatalog
9
+
10
+
11
+ class MTChartService:
12
+ def __init__(self, catalog_db: str | Path | None = None) -> None:
13
+ self.catalog = PartsCatalog(catalog_db or "mtchart_sdk.db")
14
+
15
+ def create_process(self, data: ProcessInput) -> ProcessRecord:
16
+ started_at = data.started_at or datetime.now()
17
+ items = [normalize_item(item) for item in data.items]
18
+ for item in items:
19
+ if item.name and item.pn:
20
+ self.catalog.save(item.name, item.pn)
21
+ expected_exit_at, _remaining = calculate_exit_timing(started_at, data.relief_hours, started_at)
22
+ return ProcessRecord(
23
+ report_number=data.report_number,
24
+ project=data.project,
25
+ process_name=data.process_name,
26
+ oven=data.oven,
27
+ relief_hours=float(data.relief_hours or 0),
28
+ pen=data.pen,
29
+ items=items,
30
+ started_at=started_at,
31
+ expected_exit_at=expected_exit_at,
32
+ total_quantity=total_quantity(items),
33
+ metadata=dict(data.metadata or {}),
34
+ )
35
+
36
+ def evaluate_reading(
37
+ self,
38
+ process: ProcessRecord,
39
+ value: float | str | None,
40
+ now: datetime | None = None,
41
+ ) -> ReadingEvaluation:
42
+ return evaluate_temperature(
43
+ value=value,
44
+ pen=process.pen,
45
+ started_at=process.started_at,
46
+ relief_hours=process.relief_hours,
47
+ now=now,
48
+ )
49
+
50
+ def search_parts(self, term: str = "", limit: int = 100) -> list[dict[str, object]]:
51
+ return self.catalog.search(term, limit)
mtchart_sdk/storage.py ADDED
@@ -0,0 +1,98 @@
1
+ from __future__ import annotations
2
+
3
+ import sqlite3
4
+ from contextlib import contextmanager
5
+ from datetime import datetime
6
+ from pathlib import Path
7
+ from typing import Iterator
8
+
9
+ from mtchart_sdk.rules import clean_identifier
10
+
11
+
12
+ class PartsCatalog:
13
+ def __init__(self, db_path: str | Path = "mtchart_sdk.db") -> None:
14
+ self.db_path = Path(db_path)
15
+ if self.db_path.parent != Path("."):
16
+ self.db_path.parent.mkdir(parents=True, exist_ok=True)
17
+ self.init_db()
18
+
19
+ @contextmanager
20
+ def connect(self) -> Iterator[sqlite3.Connection]:
21
+ conn = sqlite3.connect(self.db_path)
22
+ try:
23
+ yield conn
24
+ conn.commit()
25
+ except Exception:
26
+ conn.rollback()
27
+ raise
28
+ finally:
29
+ conn.close()
30
+
31
+ def init_db(self) -> None:
32
+ with self.connect() as conn:
33
+ conn.execute(
34
+ """
35
+ CREATE TABLE IF NOT EXISTS catalog_parts (
36
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
37
+ name TEXT NOT NULL,
38
+ pn TEXT NOT NULL,
39
+ name_norm TEXT NOT NULL,
40
+ pn_norm TEXT NOT NULL,
41
+ use_count INTEGER DEFAULT 1,
42
+ last_used_at TEXT NOT NULL,
43
+ UNIQUE(name_norm, pn_norm)
44
+ )
45
+ """
46
+ )
47
+ conn.execute("CREATE INDEX IF NOT EXISTS idx_catalog_parts_name ON catalog_parts(name_norm)")
48
+ conn.execute("CREATE INDEX IF NOT EXISTS idx_catalog_parts_pn ON catalog_parts(pn_norm)")
49
+
50
+ def save(self, name: str, pn: str, increment: bool = True) -> None:
51
+ name = clean_identifier(name)
52
+ pn = clean_identifier(pn)
53
+ if not name or not pn:
54
+ raise ValueError("name and pn are required")
55
+ name_norm = name.upper()
56
+ pn_norm = pn.upper()
57
+ increment_by = 1 if increment else 0
58
+ now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
59
+ with self.connect() as conn:
60
+ conn.execute(
61
+ """
62
+ INSERT INTO catalog_parts (name, pn, name_norm, pn_norm, use_count, last_used_at)
63
+ VALUES (?, ?, ?, ?, 1, ?)
64
+ ON CONFLICT(name_norm, pn_norm) DO UPDATE SET
65
+ name = excluded.name,
66
+ pn = excluded.pn,
67
+ use_count = catalog_parts.use_count + ?,
68
+ last_used_at = excluded.last_used_at
69
+ """,
70
+ (name, pn, name_norm, pn_norm, now, increment_by),
71
+ )
72
+
73
+ def search(self, term: str = "", limit: int = 100) -> list[dict[str, object]]:
74
+ term_norm = clean_identifier(term).upper()
75
+ limit = max(1, min(1000, int(limit or 100)))
76
+ query = """
77
+ SELECT id, name, pn, use_count, last_used_at
78
+ FROM catalog_parts
79
+ """
80
+ params: tuple[object, ...]
81
+ if term_norm:
82
+ query += " WHERE name_norm LIKE ? OR pn_norm LIKE ?"
83
+ params = (f"%{term_norm}%", f"%{term_norm}%", limit)
84
+ else:
85
+ params = (limit,)
86
+ query += " ORDER BY use_count DESC, id DESC LIMIT ?"
87
+ with self.connect() as conn:
88
+ rows = conn.execute(query, params).fetchall()
89
+ return [
90
+ {
91
+ "id": row[0],
92
+ "name": row[1],
93
+ "pn": row[2],
94
+ "use_count": row[3],
95
+ "last_used_at": row[4],
96
+ }
97
+ for row in rows
98
+ ]
@@ -0,0 +1,123 @@
1
+ Metadata-Version: 2.4
2
+ Name: mtchart-sdk
3
+ Version: 0.1.0
4
+ Summary: SDK para criar sistemas de monitoramento termico, rastreabilidade e relatorios derivados do MTChart Pro.
5
+ Author: MTD Softwares
6
+ License-Expression: LicenseRef-Proprietary
7
+ Project-URL: Homepage, https://github.com/Romero-Softwares/mtchart_sdk
8
+ Project-URL: Repository, https://github.com/Romero-Softwares/mtchart_sdk
9
+ Project-URL: Documentation, https://github.com/Romero-Softwares/mtchart_sdk#readme
10
+ Project-URL: Issues, https://github.com/Romero-Softwares/mtchart_sdk/issues
11
+ Keywords: monitoramento,processo-termico,rastreabilidade,aviacao,industrial
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE.md
22
+ Provides-Extra: reports
23
+ Requires-Dist: openpyxl>=3.1; extra == "reports"
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=8; extra == "dev"
26
+ Dynamic: license-file
27
+
28
+ # MTChart SDK
29
+
30
+ SDK inicial para desenvolvedores criarem sistemas semelhantes ao MTChart Pro usando classes e metodos reutilizaveis.
31
+
32
+ Esta primeira versao fica separada do aplicativo desktop e entrega um nucleo limpo para:
33
+
34
+ - cadastrar processos termicos;
35
+ - validar leituras de temperatura;
36
+ - calcular previsao de saida;
37
+ - registrar catalogo local de pecas e PN;
38
+ - montar dados de rastreabilidade sem depender da interface Flet.
39
+
40
+ ## Instalacao
41
+
42
+ ```powershell
43
+ python -m pip install mtchart-sdk
44
+ ```
45
+
46
+ ## Exemplo rapido
47
+
48
+ ```python
49
+ from datetime import datetime
50
+
51
+ from mtchart_sdk import MTChartService, PartItem, PenConfig, ProcessInput
52
+
53
+ service = MTChartService()
54
+
55
+ process = service.create_process(
56
+ ProcessInput(
57
+ report_number="CH-0001",
58
+ project="OS-123",
59
+ process_name="Alivio de fragilizacao",
60
+ oven="Forno 01",
61
+ relief_hours=3,
62
+ pen=PenConfig(id="1", name="Pena 1", stabilization_target=189, low_limit=175.9),
63
+ items=[
64
+ PartItem(name="Suporte", pn="PN-001", sn="SN-001", qty=1),
65
+ ],
66
+ started_at=datetime(2026, 6, 28, 8, 0, 0),
67
+ )
68
+ )
69
+
70
+ reading = service.evaluate_reading(process, value=188.7)
71
+
72
+ print(process.report_number)
73
+ print(reading.status)
74
+ print(reading.can_start_process)
75
+ ```
76
+
77
+ ## Estrutura
78
+
79
+ - `mtchart_sdk.models`: modelos de dados do processo.
80
+ - `mtchart_sdk.rules`: regras puras de temperatura e tempo.
81
+ - `mtchart_sdk.storage`: catalogo SQLite local de pecas.
82
+ - `mtchart_sdk.service`: fachada principal para uso por outros sistemas.
83
+ - `mtchart_sdk.cli`: demonstracao de linha de comando para validar instalacao.
84
+ - `examples/basic_process.py`: exemplo minimo executavel.
85
+
86
+ ## API principal
87
+
88
+ - `MTChartService.create_process(data)`: normaliza pecas, calcula quantidade total e previsao de saida.
89
+ - `MTChartService.evaluate_reading(process, value)`: classifica leitura como `OK`, `LOW`, `HIGH` ou `N/A`.
90
+ - `MTChartService.search_parts(term)`: consulta o catalogo local de pecas por nome ou PN.
91
+ - `clean_identifier(value)`: remove prefixos comuns como `PN:`, `P/N:`, `LOTE:` e `BATCH:`.
92
+
93
+ ## CLI de demonstracao
94
+
95
+ Depois de instalar localmente, rode:
96
+
97
+ ```powershell
98
+ mtchart-sdk-demo --value 188.7
99
+ ```
100
+
101
+ Ou sem instalar como script:
102
+
103
+ ```powershell
104
+ python -m mtchart_sdk.cli --catalog-db .tmp_demo.db --value 188.7
105
+ ```
106
+
107
+ O comando cria um processo ficticio, avalia a leitura e retorna um JSON com
108
+ status, previsao de saida e resultados do catalogo local.
109
+
110
+ ## Validacao local
111
+
112
+ Para validar uma copia local do SDK durante desenvolvimento:
113
+
114
+ ```powershell
115
+ python tools/validate_package.py
116
+ ```
117
+
118
+ O validador confere metadados, compila os modulos, roda testes e executa o
119
+ exemplo/CLI de demonstracao.
120
+
121
+ ## Status
122
+
123
+ Versao inicial. A API esta pronta para instalacao, testes locais e evolucao incremental.
@@ -0,0 +1,12 @@
1
+ mtchart_sdk/__init__.py,sha256=IJ8bMwv2YOQ6PmPSF3GH5ytZuf2ynCVcZf471KlJ7q4,677
2
+ mtchart_sdk/cli.py,sha256=Jq9QbhOSy4ItCc4Cw_mpMv6-tdBlqoChs71KdvvdBuM,3759
3
+ mtchart_sdk/models.py,sha256=f-BmGrFEfbOOHK3ueki1cjq4tvbyfv03D2yrX5gaJb4,1437
4
+ mtchart_sdk/rules.py,sha256=JgsVtwJ6OIqcGiwNVhuj_CcKfunfForPXY65ar2Yiro,3265
5
+ mtchart_sdk/service.py,sha256=GIB8Jan4UoVhl4hxXSU-HUVeXWwRk9DrPCoVlM-iRUE,1954
6
+ mtchart_sdk/storage.py,sha256=4K9iwyp7gk2CieRSS0O6iFShBabxqgiHiVKSg2c2VF8,3614
7
+ mtchart_sdk-0.1.0.dist-info/licenses/LICENSE.md,sha256=qiHPDS6FSlbg5G-Eoh7dFcOtXLOBvX9hXigb-El1LhE,667
8
+ mtchart_sdk-0.1.0.dist-info/METADATA,sha256=R6SiwpPqQD5mJfLJX2OSMcRI1-gek4IukCq3ogb2SXM,4110
9
+ mtchart_sdk-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
10
+ mtchart_sdk-0.1.0.dist-info/entry_points.txt,sha256=g2AdcwosARJ0uoEVK4gwINHguvPstiD-IcYEL0FGXC4,58
11
+ mtchart_sdk-0.1.0.dist-info/top_level.txt,sha256=msH_FVGlPkDhfnxYswk6bdyN936yoMv7sjS6vSpnLm0,12
12
+ mtchart_sdk-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mtchart-sdk-demo = mtchart_sdk.cli:main
@@ -0,0 +1,15 @@
1
+ Proprietary Commercial License
2
+
3
+ Copyright (c) 2026 MTD Softwares.
4
+
5
+ This SDK is provided as a commercial/proprietary component derived from
6
+ MTChart Pro. Use, redistribution, sublicensing, resale, or incorporation into
7
+ third-party products requires written authorization from MTD Softwares.
8
+
9
+ Developers may use this local copy only for evaluation, internal testing, and
10
+ integration planning unless a separate commercial license grants broader
11
+ rights.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -0,0 +1 @@
1
+ mtchart_sdk