1- import hashlib
21import logging
3-
42import pandas as pd
5- from preprocessing . core import Preprocessor
6- from preprocessing . loader import BibLoader , TxtLoader
7- from preprocessing . models import DocumentRecord , PreprocessedDocument
3+
4+ from pathlib import Path
5+ from typing import List
86from scystream .sdk .core import entrypoint
97from scystream .sdk .env .settings import (
108 EnvSettings ,
11- FileSettings ,
129 InputSettings ,
1310 OutputSettings ,
14- PostgresSettings ,
11+ DatabaseSettings ,
12+ FileSettings ,
1513)
1614from scystream .sdk .file_handling .s3_manager import S3Operations
17- from sqlalchemy import create_engine
18- from sqlalchemy .sql import quoted_name
15+ from scystream .sdk .database_handling .database_manager import (
16+ PandasDatabaseOperations ,
17+ )
18+
19+ from preprocessing .core import Preprocessor
20+ from preprocessing .loader import TxtLoader , BibLoader
21+ from preprocessing .models import DocumentRecord , PreprocessedDocument
1922
2023logging .basicConfig (
2124 level = logging .INFO ,
2427logger = logging .getLogger (__name__ )
2528
2629
27- def _normalize_table_name (table_name : str ) -> str :
28- max_length = 63
29- if len (table_name ) <= max_length :
30- return table_name
31- digest = hashlib .sha1 (table_name .encode ("utf-8" )).hexdigest ()[:10 ]
32- prefix_length = max_length - len (digest ) - 1
33- return f"{ table_name [:prefix_length ]} _{ digest } "
34-
35-
36- def _resolve_db_table (settings : PostgresSettings ) -> str :
37- normalized_name = _normalize_table_name (settings .DB_TABLE )
38- settings .DB_TABLE = normalized_name
39- return normalized_name
30+ class NormalizedDocsOutput (DatabaseSettings , OutputSettings ):
31+ __identifier__ = "normalized_docs"
4032
4133
42- class NormalizedDocsOutput (PostgresSettings , OutputSettings ):
43- __identifier__ = "normalized_docs"
34+ class NormalizedTXTOutput (FileSettings , OutputSettings ):
35+ __identifier__ = "normalized_overwritten_file_output"
36+ FILE_EXT : str = "txt"
4437
4538
4639class TXTFileInput (FileSettings , InputSettings ):
@@ -55,6 +48,11 @@ class BIBFileInput(FileSettings, InputSettings):
5548 SELECTED_ATTRIBUTE : str = "Abstract"
5649
5750
51+ class NormalizedBIBOutput (FileSettings , OutputSettings ):
52+ __identifier__ = "normalized_overwritten_file_output"
53+ FILE_EXT : str = "bib"
54+
55+
5856class PreprocessTXT (EnvSettings ):
5957 LANGUAGE : str = "en"
6058 FILTER_STOPWORDS : bool = True
@@ -67,6 +65,7 @@ class PreprocessTXT(EnvSettings):
6765
6866 txt_input : TXTFileInput
6967 normalized_docs_output : NormalizedDocsOutput
68+ normalized_overwritten_file_output : NormalizedTXTOutput
7069
7170
7271class PreprocessBIB (EnvSettings ):
@@ -81,44 +80,37 @@ class PreprocessBIB(EnvSettings):
8180
8281 bib_input : BIBFileInput
8382 normalized_docs_output : NormalizedDocsOutput
83+ normalized_overwritten_file_output : NormalizedBIBOutput
8484
8585
8686def _write_preprocessed_docs_to_postgres (
8787 preprocessed_ouput : list [PreprocessedDocument ],
88- settings : PostgresSettings ,
88+ settings : DatabaseSettings ,
8989):
90- resolved_table_name = _resolve_db_table (settings )
9190 df = pd .DataFrame (
92- [
93- {
94- "doc_id" : d .doc_id ,
95- "tokens" : d .tokens ,
96- }
97- for d in preprocessed_ouput
98- ],
91+ [{"doc_id" : d .doc_id , "tokens" : d .tokens } for d in preprocessed_ouput ]
9992 )
10093
10194 logger .info (
10295 "Writing %s processed documents to DB table '%s'…" ,
10396 len (df ),
104- resolved_table_name ,
97+ settings . DB_TABLE ,
10598 )
106- engine = create_engine (
107- f"postgresql+psycopg2://{ settings .PG_USER } :{ settings .PG_PASS } "
108- f"@{ settings .PG_HOST } :{ int (settings .PG_PORT )} /" ,
109- )
110-
111- table_name = quoted_name (resolved_table_name , quote = True )
112- df .to_sql (table_name , engine , if_exists = "replace" , index = False )
99+ db = PandasDatabaseOperations (settings .DB_DSN , settings .DB_SCHEMA )
100+ db .write (table = settings .DB_TABLE , data = df )
113101
114102 logger .info (
115103 "Successfully stored normalized documents into '%s'." ,
116- resolved_table_name ,
104+ settings . DB_TABLE ,
117105 )
118106
119107
120- def _preprocess_and_store (documents : list [DocumentRecord ], settings ):
121- """Shared preprocessing logic for TXT and BIB."""
108+ def _preprocess_and_store (
109+ documents : List [DocumentRecord ],
110+ overwrite_callback ,
111+ settings ,
112+ ) -> List [PreprocessedDocument ]:
113+
122114 logger .info (f"Starting preprocessing with { len (documents )} documents" )
123115
124116 pre = Preprocessor (
@@ -134,30 +126,49 @@ def _preprocess_and_store(documents: list[DocumentRecord], settings):
134126 result = pre .generate_normalized_output ()
135127
136128 _write_preprocessed_docs_to_postgres (
137- result ,
138- settings .normalized_docs_output ,
129+ result , settings .normalized_docs_output
130+ )
131+
132+ # Overwrite file using injected behavior
133+ export_path = Path (
134+ f"output.{ settings .normalized_overwritten_file_output .FILE_EXT } "
135+ )
136+ overwrite_callback (result , export_path )
137+
138+ S3Operations .upload (
139+ settings .normalized_overwritten_file_output , export_path
139140 )
140141
141142 logger .info ("Preprocessing completed successfully." )
143+ return result
142144
143145
144146@entrypoint (PreprocessTXT )
145147def preprocess_txt_file (settings ):
146- logger .info ("Downloading TXT input from S3 ..." )
148+ logger .info ("Downloading TXT file ..." )
147149 S3Operations .download (settings .txt_input , settings .TXT_DOWNLOAD_PATH )
148150
149- texts = TxtLoader .load (settings .TXT_DOWNLOAD_PATH )
151+ documents = TxtLoader .load (settings .TXT_DOWNLOAD_PATH )
150152
151- _preprocess_and_store (texts , settings )
153+ _preprocess_and_store (
154+ documents = documents ,
155+ overwrite_callback = TxtLoader .overwrite_with_results ,
156+ settings = settings ,
157+ )
152158
153159
154160@entrypoint (PreprocessBIB )
155161def preprocess_bib_file (settings ):
156- logger .info ("Downloading BIB input from S3 ..." )
162+ logger .info ("Downloading BIB file ..." )
157163 S3Operations .download (settings .bib_input , settings .BIB_DOWNLOAD_PATH )
158164
159- texts = BibLoader . load (
160- settings .BIB_DOWNLOAD_PATH ,
165+ loader = BibLoader (
166+ file_path = settings .BIB_DOWNLOAD_PATH ,
161167 attribute = settings .bib_input .SELECTED_ATTRIBUTE ,
162168 )
163- _preprocess_and_store (texts , settings )
169+
170+ _preprocess_and_store (
171+ documents = loader .document_records ,
172+ overwrite_callback = loader .overwrite_with_results ,
173+ settings = settings ,
174+ )
0 commit comments