heurist-api 0.2.0__py3-none-any.whl → 0.2.2__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 heurist-api might be problematic. Click here for more details.

heurist/cli/load.py CHANGED
@@ -7,8 +7,14 @@ from pathlib import Path
7
7
  import duckdb
8
8
  from heurist.api.connection import HeuristAPIConnection
9
9
  from heurist.api.credentials import CredentialHandler
10
+ from heurist.log import log_summary
11
+ from heurist.log.constants import VALIDATION_LOG
10
12
  from heurist.utils.constants import DEFAULT_RECORD_GROUPS
11
13
  from heurist.workflows import extract_transform_load
14
+ from rich.columns import Columns
15
+ from rich.console import Console, Group
16
+ from rich.padding import Padding
17
+ from rich.panel import Panel
12
18
 
13
19
 
14
20
  def load_command(
@@ -37,10 +43,14 @@ def load_command(
37
43
  )
38
44
 
39
45
  # Show the results of the created DuckDB database
40
- with duckdb.connect(duckdb_database_connection_path) as new_conn:
41
- tables = new_conn.sql("show tables;")
42
- print("\nCreated the following tables")
43
- print(tables)
46
+ with duckdb.connect(duckdb_database_connection_path, read_only=True) as new_conn:
47
+ tables = [t[0] for t in new_conn.sql("show tables;").fetchall()]
48
+ if VALIDATION_LOG.is_file():
49
+ with open(VALIDATION_LOG) as f:
50
+ log = f.readlines()
51
+ else:
52
+ log = []
53
+ show_summary_in_console(tables=tables, log_lines=log)
44
54
 
45
55
  # If writing to CSV files, write only tables of record types
46
56
  if outdir:
@@ -53,3 +63,15 @@ def load_command(
53
63
  continue
54
64
  fp = outdir.joinpath(f"{table_name}.csv")
55
65
  new_conn.table(table_name).sort("H-ID").write_csv(str(fp))
66
+
67
+
68
+ def show_summary_in_console(tables: list[str], log_lines: list):
69
+ console = Console()
70
+ t0 = Panel(
71
+ Columns(tables, equal=True, expand=True),
72
+ title="SQL Tables",
73
+ subtitle="Saved in DuckDB database file.",
74
+ )
75
+ t1, t2 = log_summary(lines=log_lines)
76
+ panel_group = Group(Padding(t0, 1), t1, Padding(t2, 1))
77
+ console.print(panel_group)
heurist/cli/parse_log.py CHANGED
@@ -1,16 +1,21 @@
1
- import click
2
1
  import csv
3
- from heurist.log import yield_log_blocks, LogDetail
2
+ from pathlib import Path
4
3
 
4
+ import click
5
+ from heurist.log import LogDetail, yield_log_blocks
6
+ from heurist.log.constants import VALIDATION_LOG
5
7
 
6
8
  log_detail_fieldnames = list(LogDetail.__annotations__.keys())
7
9
 
8
10
 
9
11
  @click.command()
10
- @click.argument("csvfile", type=click.Path())
11
- @click.option("-l", "--log-file", required=None, default="validation.log")
12
- def cli(csvfile, log_file):
13
- with open(log_file) as f, open(csvfile, "w") as of:
12
+ @click.option("-l", "--log-file", required=None, default=VALIDATION_LOG)
13
+ @click.option("-o", "--outfile", required=None, default="invalid_records.csv")
14
+ def cli(log_file, outfile):
15
+ logfile = Path(log_file)
16
+ if not logfile.is_file():
17
+ raise FileNotFoundError(log_file)
18
+ with open(logfile) as f, open(outfile, "w") as of:
14
19
  writer = csv.DictWriter(of, fieldnames=log_detail_fieldnames)
15
20
  writer.writeheader()
16
21
  lines = f.readlines()
heurist/log/__init__.py CHANGED
@@ -1,2 +1,3 @@
1
1
  from .iterator import yield_log_blocks as yield_log_blocks
2
2
  from .model import LogDetail as LogDetail
3
+ from .summary import log_summary as log_summary
@@ -0,0 +1,3 @@
1
+ from pathlib import Path
2
+
3
+ VALIDATION_LOG = Path.cwd().joinpath("validation.log")
heurist/log/model.py CHANGED
@@ -1,5 +1,5 @@
1
- from dataclasses import dataclass
2
1
  import re
2
+ from dataclasses import dataclass
3
3
 
4
4
 
5
5
  @dataclass
heurist/log/summary.py ADDED
@@ -0,0 +1,35 @@
1
+ from collections import Counter
2
+
3
+ from heurist.log import yield_log_blocks
4
+ from rich.table import Table
5
+
6
+
7
+ def log_summary(lines: list[str]) -> tuple[Table, Table]:
8
+ rectypes = []
9
+ recs = []
10
+ for block in yield_log_blocks(lines):
11
+ rectypes.append(block.recType)
12
+ recs.append(block.recID)
13
+
14
+ rectype_counter = Counter(rectypes)
15
+ rec_counter = Counter(recs)
16
+
17
+ rec_table = Table(
18
+ title="Most problematic records",
19
+ caption="Note: Invalid records are not saved in the DuckDB database.",
20
+ )
21
+ rec_table.add_column("Record ID", style="red")
22
+ rec_table.add_column("Number of problems")
23
+ for rec, count in rec_counter.most_common(10):
24
+ rec_table.add_row(str(rec), str(count))
25
+
26
+ type_table = Table(
27
+ title="Types of invalid records",
28
+ caption="Note: Invalid records are not saved in the DuckDB database.",
29
+ )
30
+ type_table.add_column("Record Type", style="red")
31
+ type_table.add_column("Number of records")
32
+ for rec, count in rectype_counter.items():
33
+ type_table.add_row(str(rec), str(count))
34
+
35
+ return type_table, rec_table
@@ -1,16 +1,14 @@
1
1
  import logging
2
2
  import os
3
- from pathlib import Path
4
3
 
4
+ from heurist.log.constants import VALIDATION_LOG
5
5
  from heurist.models.dynamic.annotation import PydanticField
6
6
  from heurist.models.dynamic.type import FieldType
7
7
  from heurist.validators.detail_validator import DetailValidator
8
8
  from heurist.validators.exceptions import RepeatedValueInSingularDetailType
9
9
  from pydantic import BaseModel
10
10
 
11
- VALIDATION_LOG = Path.cwd().joinpath("validation.log")
12
-
13
- handlers = [logging.FileHandler(filename=VALIDATION_LOG, mode="w", delay=True)]
11
+ handlers = [logging.FileHandler(filename=VALIDATION_LOG, mode="w")]
14
12
  if os.getenv("HEURIST_STREAM_LOG") == "True":
15
13
  handlers.append(logging.StreamHandler())
16
14
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: heurist-api
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Dynamic: Description
5
5
  Dynamic: Description-Content-Type
6
6
  Summary: API wrapper and CLI for Heurist database.
@@ -9,16 +9,18 @@ heurist/api/url_builder.py,sha256=mT1hgZ-T38EPyHCSLfjFecbZVLsiPi18jemDuuMj21I,49
9
9
  heurist/api/utils.py,sha256=DT-BrdF7O2lmFSduRYOecx302dAlLWQTYgr2V9JoDYI,643
10
10
  heurist/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  heurist/cli/__main__.py,sha256=QG2gJG7zD3YIDRqbIp2MzTqPxqGLZ77RHCRYZ58SSjg,5975
12
- heurist/cli/load.py,sha256=kU8nTSJMl6ynz6FguhE_xdqJwQFijjsRerQGRtWil5s,1903
13
- heurist/cli/parse_log.py,sha256=9KjstOOjJsAiB6fTIQxxiNKpRxLg-2DB4qbKvScDhIc,623
12
+ heurist/cli/load.py,sha256=iiQ11EauKV93Z3YuGyspeOK9XQIVf5SqRzQ9b6V8KZQ,2685
13
+ heurist/cli/parse_log.py,sha256=cZU9mpLbx5p-bdCwbII27T-ugTpecTgCFiBoYJip5f4,828
14
14
  heurist/cli/records.py,sha256=yKK3XIZrU1szo6X-HmGjZpD0IKk3a3rd3Kkyrg5AYGE,1345
15
15
  heurist/cli/schema.py,sha256=Dg8NcSdI7Xb6r-dkUC_razXlZNtxSG0x7awsr1m8Mcw,2766
16
16
  heurist/database/__init__.py,sha256=JvQCGCi84AXUSIPCu4cTOqT_yZGDLmZFAUdsHDLbpKI,79
17
17
  heurist/database/basedb.py,sha256=0MKfQOKTBDCc6qcl8BGl5OIpSA7SYgmfcKXCBVWBPes,4200
18
18
  heurist/database/database.py,sha256=rJPhGA4158eoIwe13QsSGZ8929dkRxMTesRRlMrn1tI,4057
19
- heurist/log/__init__.py,sha256=9zYSx-jKp7GBnlS8qMWYqah3FnhqcTrebVVcn79ghFM,101
19
+ heurist/log/__init__.py,sha256=ubZl-2yMlvUYJwJtnk6C8AjmnU-9mbp96aHL1NSzbSg,149
20
+ heurist/log/constants.py,sha256=8TsR_BxYL_TzZSQWwKAO8oWqBGZ0g3e-XNls5XWymDs,81
20
21
  heurist/log/iterator.py,sha256=nmpW3QQfwToADD4zffAm5iFyIUMFT56LRORdThYRoqE,519
21
- heurist/log/model.py,sha256=U04rKbKva8dk6gTtEJdbYw-li0JVUjLYm8I8gyoWxuM,1085
22
+ heurist/log/model.py,sha256=rOey1V6Vd_ehm8FTXxfi7Q4A4Mjq0V9ITl_GlNdB0y0,1085
23
+ heurist/log/summary.py,sha256=n-skKRiFSPd3DieZMveJLCP96plVdgjW9wgBR0H_2BI,1113
22
24
  heurist/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
25
  heurist/models/dynamic/__init__.py,sha256=dFUNGMugaOAkec6uhDxkUVrmGkR5dr1fTd8X_TprRyU,77
24
26
  heurist/models/dynamic/annotation.py,sha256=FOkldKT5u2XWBk7DxXbrgRf8X_G3N5FEfr-rOTLq-Eg,4749
@@ -52,7 +54,7 @@ heurist/validators/__init__.py,sha256=Im5z_Yg2VdKSZRPUOPSF5AFZ8AWgnyBZNKhy1o69lC
52
54
  heurist/validators/detail_validator.py,sha256=NVItrZ4Ysmgqab-B24hIeimGqpiaiqFiono5qwW20ko,4070
53
55
  heurist/validators/exceptions.py,sha256=tgoMn6R2CExT6mFg2qe4vRxP2D61cNdgEqc7YUQCFSE,1108
54
56
  heurist/validators/parse_heurist_date.py,sha256=S-NzuLZJwDrxRJkAd-fXpOlENlkc8HXKRILWCODmtIU,2161
55
- heurist/validators/record_validator.py,sha256=bzSurq0aLN9LLWcAYSE3X63hT00OZUIqyaNCLTgtE08,6297
57
+ heurist/validators/record_validator.py,sha256=2mPfX_57F3MsgVVxpJm6Na2JCGhEicYD2bN_X6fn2L0,6253
56
58
  heurist/workflows/__init__.py,sha256=aYN0UE_7rD9h0h74DMXkUTIDrxA0WcsWLEXWK123Gzc,81
57
59
  heurist/workflows/etl.py,sha256=IA97B1NOg_2btT_pynY64RYvbL4JraAy6wgIKJlNljM,2286
58
60
  mock_data/__init__.py,sha256=TGe3NjGTXVRQbakVGEWbDDzIkFQ72fTZhTcAoIH3DGQ,488
@@ -77,8 +79,8 @@ mock_data/geo/single.py,sha256=gbk_gOLfVlJuU3MhjY2Lu14bs9-FbZmNtevpiw9jArk,79867
77
79
  mock_data/resource/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
80
  mock_data/resource/repeated.py,sha256=Nf3nIL596pLVbKo20sQm5UITwBzqf-IHFzE_m2UCLbw,788
79
81
  mock_data/resource/single.py,sha256=SXVri1MM8UaJw7GejMEJ6seNEnMksdw_WKiOxQOdVFs,411
80
- heurist_api-0.2.0.dist-info/METADATA,sha256=yen3I0sbV3Z81AXdBCsxlGAO0QWJ9m68eHelXCvkMrg,25177
81
- heurist_api-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
82
- heurist_api-0.2.0.dist-info/entry_points.txt,sha256=37KBvqofapLaKDPFrcYxv_rfUM9H08Mbe6mxNdd_Xno,93
83
- heurist_api-0.2.0.dist-info/licenses/LICENSE,sha256=I-54yLrknPCOovDISUXGa5h-vkUgiB-1Gz2tT7Q9B8I,20137
84
- heurist_api-0.2.0.dist-info/RECORD,,
82
+ heurist_api-0.2.2.dist-info/METADATA,sha256=uhv1HQ4n5iYL8Jp9dNrUMHfHH-_60u0Y9uciPrqqXIc,25177
83
+ heurist_api-0.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
84
+ heurist_api-0.2.2.dist-info/entry_points.txt,sha256=37KBvqofapLaKDPFrcYxv_rfUM9H08Mbe6mxNdd_Xno,93
85
+ heurist_api-0.2.2.dist-info/licenses/LICENSE,sha256=I-54yLrknPCOovDISUXGa5h-vkUgiB-1Gz2tT7Q9B8I,20137
86
+ heurist_api-0.2.2.dist-info/RECORD,,