heurist-api 0.2.0__tar.gz → 0.2.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.

Potentially problematic release.


This version of heurist-api might be problematic. Click here for more details.

Files changed (131) hide show
  1. {heurist_api-0.2.0 → heurist_api-0.2.2}/PKG-INFO +1 -1
  2. {heurist_api-0.2.0 → heurist_api-0.2.2}/pyproject.toml +1 -1
  3. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/cli/load.py +26 -4
  4. heurist_api-0.2.2/src/heurist/cli/parse_log.py +27 -0
  5. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/log/__init__.py +1 -0
  6. heurist_api-0.2.2/src/heurist/log/constants.py +3 -0
  7. heurist_api-0.2.2/src/heurist/log/summary.py +35 -0
  8. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/validators/record_validator.py +2 -4
  9. {heurist_api-0.2.0 → heurist_api-0.2.2}/uv.lock +1 -1
  10. heurist_api-0.2.0/src/heurist/cli/parse_log.py +0 -22
  11. {heurist_api-0.2.0 → heurist_api-0.2.2}/.github/workflows/pypi-release.yml +0 -0
  12. {heurist_api-0.2.0 → heurist_api-0.2.2}/.github/workflows/python-package.yml +0 -0
  13. {heurist_api-0.2.0 → heurist_api-0.2.2}/.gitignore +0 -0
  14. {heurist_api-0.2.0 → heurist_api-0.2.2}/.pre-commit-config.yaml +0 -0
  15. {heurist_api-0.2.0 → heurist_api-0.2.2}/LICENSE +0 -0
  16. {heurist_api-0.2.0 → heurist_api-0.2.2}/README.md +0 -0
  17. {heurist_api-0.2.0 → heurist_api-0.2.2}/demos/pandas_dataframe.ipynb +0 -0
  18. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/assets/coverage-badge.svg +0 -0
  19. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/assets/erc-logo.png +0 -0
  20. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/assets/heurist-admin-panel-users.png +0 -0
  21. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/assets/logo-transparent-1.png +0 -0
  22. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/assets/logo-transparent.png +0 -0
  23. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/assets/logo.png +0 -0
  24. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/assets/tests-badge.svg +0 -0
  25. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/development/code_of_conduct.md +0 -0
  26. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/development/contributing.md +0 -0
  27. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/development/coverage.md +0 -0
  28. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/development/heuristdb/temporal.md +0 -0
  29. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/development/publishing.md +0 -0
  30. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/index.md +0 -0
  31. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/legal.md +0 -0
  32. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/usage/download/date_validation.md +0 -0
  33. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/usage/download/export_csv.md +0 -0
  34. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/usage/download/group_types.md +0 -0
  35. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/usage/download/index.md +0 -0
  36. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/usage/download/logs.md +0 -0
  37. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/usage/download/user_filter.md +0 -0
  38. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/usage/index.md +0 -0
  39. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/usage/module.md +0 -0
  40. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/usage/records.md +0 -0
  41. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/usage/rstudio.md +0 -0
  42. {heurist_api-0.2.0 → heurist_api-0.2.2}/docs/usage/schema.md +0 -0
  43. {heurist_api-0.2.0 → heurist_api-0.2.2}/mkdocs.yml +0 -0
  44. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/__init__.py +0 -0
  45. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/api/__init__.py +0 -0
  46. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/api/client.py +0 -0
  47. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/api/connection.py +0 -0
  48. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/api/constants.py +0 -0
  49. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/api/credentials.py +0 -0
  50. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/api/exceptions.py +0 -0
  51. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/api/url_builder.py +0 -0
  52. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/api/utils.py +0 -0
  53. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/cli/__init__.py +0 -0
  54. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/cli/__main__.py +0 -0
  55. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/cli/records.py +0 -0
  56. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/cli/schema.py +0 -0
  57. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/database/__init__.py +0 -0
  58. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/database/basedb.py +0 -0
  59. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/database/database.py +0 -0
  60. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/log/iterator.py +0 -0
  61. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/log/model.py +1 -1
  62. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/__init__.py +0 -0
  63. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/dynamic/__init__.py +0 -0
  64. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/dynamic/annotation.py +0 -0
  65. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/dynamic/create_model.py +0 -0
  66. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/dynamic/date.py +0 -0
  67. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/dynamic/type.py +0 -0
  68. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/DetailTypes.py +0 -0
  69. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/RecStructure.py +0 -0
  70. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/RecTypeGroups.py +0 -0
  71. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/RecTypes.py +0 -0
  72. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/Terms.py +0 -0
  73. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/__init__.py +0 -0
  74. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/dty.py +0 -0
  75. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/hml_structure.py +0 -0
  76. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/rst.py +0 -0
  77. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/rtg.py +0 -0
  78. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/rty.py +0 -0
  79. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/trm.py +0 -0
  80. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/models/structural/utils.py +0 -0
  81. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/schema/__init__.py +0 -0
  82. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/schema/models.py +0 -0
  83. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/schema/rel_to_dict.py +0 -0
  84. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/sql/__init__.py +0 -0
  85. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/sql/joinRecordTypeIDNameByGroupType.sql +0 -0
  86. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/sql/joinRecordTypeMetadata.sql +0 -0
  87. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/sql/selectRecordTypeSchema.sql +0 -0
  88. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/sql/sql_safety.py +0 -0
  89. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/utils/constants.py +0 -0
  90. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/utils/rel_to_dict_array.py +0 -0
  91. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/validators/__init__.py +0 -0
  92. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/validators/detail_validator.py +0 -0
  93. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/validators/exceptions.py +0 -0
  94. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/validators/parse_heurist_date.py +0 -0
  95. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/workflows/__init__.py +0 -0
  96. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/heurist/workflows/etl.py +0 -0
  97. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/__init__.py +0 -0
  98. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/blocktext/__init__.py +0 -0
  99. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/blocktext/single.py +0 -0
  100. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/date/__init__.py +0 -0
  101. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/date/compound_repeated.py +0 -0
  102. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/date/compound_single.py +0 -0
  103. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/date/simple_single.py +0 -0
  104. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/date/timestamp_repeated.py +0 -0
  105. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/enum/__init__.py +0 -0
  106. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/enum/repeated.py +0 -0
  107. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/enum/single.py +0 -0
  108. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/file/__init__.py +0 -0
  109. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/file/single.py +0 -0
  110. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/float/__init__.py +0 -0
  111. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/float/single.py +0 -0
  112. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/freetext/__init__.py +0 -0
  113. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/freetext/single.py +0 -0
  114. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/geo/__init__.py +0 -0
  115. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/geo/single.py +0 -0
  116. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/resource/__init__.py +0 -0
  117. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/resource/repeated.py +0 -0
  118. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/mock_data/resource/single.py +0 -0
  119. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/scripts/gen_badges.sh +0 -0
  120. {heurist_api-0.2.0 → heurist_api-0.2.2}/src/scripts/gen_ref_pages.py +0 -0
  121. {heurist_api-0.2.0 → heurist_api-0.2.2}/tests/e2e/download_test.py +0 -0
  122. {heurist_api-0.2.0 → heurist_api-0.2.2}/tests/e2e/schema_test.py +0 -0
  123. {heurist_api-0.2.0 → heurist_api-0.2.2}/tests/integration/api/client_test.py +0 -0
  124. {heurist_api-0.2.0 → heurist_api-0.2.2}/tests/integration/api/connection_test.py +0 -0
  125. {heurist_api-0.2.0 → heurist_api-0.2.2}/tests/unit/database/database_test.py +0 -0
  126. {heurist_api-0.2.0 → heurist_api-0.2.2}/tests/unit/database/modeling_test.py +0 -0
  127. {heurist_api-0.2.0 → heurist_api-0.2.2}/tests/unit/database/skeleton_test.py +0 -0
  128. {heurist_api-0.2.0 → heurist_api-0.2.2}/tests/unit/log_test.py +0 -0
  129. {heurist_api-0.2.0 → heurist_api-0.2.2}/tests/unit/schema/get_db_schema_test.py +0 -0
  130. {heurist_api-0.2.0 → heurist_api-0.2.2}/tests/unit/validators/detail_validation_test.py +0 -0
  131. {heurist_api-0.2.0 → heurist_api-0.2.2}/tests/unit/validators/repeated_enum_test.py +0 -0
@@ -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.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "heurist-api"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  description = "API wrapper and CLI for Heurist database."
5
5
  keywords = [ "duckdb", "etl" ]
6
6
  dynamic = [ "readme" ]
@@ -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)
@@ -0,0 +1,27 @@
1
+ import csv
2
+ from pathlib import Path
3
+
4
+ import click
5
+ from heurist.log import LogDetail, yield_log_blocks
6
+ from heurist.log.constants import VALIDATION_LOG
7
+
8
+ log_detail_fieldnames = list(LogDetail.__annotations__.keys())
9
+
10
+
11
+ @click.command()
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:
19
+ writer = csv.DictWriter(of, fieldnames=log_detail_fieldnames)
20
+ writer.writeheader()
21
+ lines = f.readlines()
22
+ for block in yield_log_blocks(lines):
23
+ writer.writerow(block.__dict__)
24
+
25
+
26
+ if __name__ == "__main__":
27
+ cli()
@@ -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")
@@ -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
 
@@ -421,7 +421,7 @@ wheels = [
421
421
 
422
422
  [[package]]
423
423
  name = "heurist-api"
424
- version = "0.1.4"
424
+ version = "0.2.2"
425
425
  source = { editable = "." }
426
426
  dependencies = [
427
427
  { name = "click" },
@@ -1,22 +0,0 @@
1
- import click
2
- import csv
3
- from heurist.log import yield_log_blocks, LogDetail
4
-
5
-
6
- log_detail_fieldnames = list(LogDetail.__annotations__.keys())
7
-
8
-
9
- @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:
14
- writer = csv.DictWriter(of, fieldnames=log_detail_fieldnames)
15
- writer.writeheader()
16
- lines = f.readlines()
17
- for block in yield_log_blocks(lines):
18
- writer.writerow(block.__dict__)
19
-
20
-
21
- if __name__ == "__main__":
22
- cli()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -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