Skip to content

Commit 911655f

Browse files
committed
rsj_CRLF_to_LF
only converted the files with actual changes from CRLF to LF NOTE: github shows Warning: This diff contains a change from 'LF' to 'CRLF' -- ignore
1 parent 7926535 commit 911655f

6 files changed

Lines changed: 534 additions & 10 deletions

File tree

src/pds_doi_service/core/db/transaction_on_disk.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ def get_transaction_key(node_id, doi, transaction_time):
7575

7676
prefix, suffix = doi.split("/", maxsplit=1)
7777

78-
return os.path.join(transaction_dir, node_id, prefix, suffix, transaction_time.isoformat())
78+
# 20250720: modify so transaction_time returns a string as YYYY-MM-DDThh:mm:ss.microseconds
79+
# return os.path.join(transaction_dir, node_id, prefix, suffix, transaction_time.isoformat())
80+
return os.path.join(transaction_dir, node_id, prefix, suffix, transaction_time.strftime("%Y-%m-%dT%H-%M-%S.%f"))
7981

8082
@staticmethod
8183
def output_label_for_transaction(transaction_record):
@@ -165,7 +167,7 @@ def write(self, transaction_dir, input_ref=None, output_content=None, output_con
165167
r = requests.get(input_ref, allow_redirects=True)
166168

167169
with open(full_input_name, "wb") as outfile:
168-
outfile.write(r.content)
170+
outfile.write(r.content, encoding="utf-8")
169171

170172
r.close()
171173

src/pds_doi_service/core/entities/doi.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,17 @@ class Doi:
117117
identifiers: list[dict] = field(default_factory=list)
118118
related_identifiers: list[dict] = field(default_factory=list)
119119
authors: Optional[list[dict]] = field(default_factory=list) # type: ignore
120+
# 20250501 -- add list_authors
121+
# -- optional because older XML labels did not implement this field
122+
list_authors: Optional[list[dict]] = field(default_factory=list) # type: ignore
120123
keywords: set[str] = field(default_factory=get_global_keywords)
121124
editors: Optional[list[dict]] = field(default_factory=list) # type: ignore
125+
# 20250501 -- add list_editors
126+
# -- add contributors and list_contributors as they didn't exist in the DOI structure
127+
# -- optional because older XML labels did not implement this field
128+
list_editors: Optional[list[dict]] = field(default_factory=list) # type: ignore
129+
contributors: Optional[list[dict]] = field(default_factory=list) # type: ignore
130+
list_contributors: Optional[list[dict]] = field(default_factory=list) # type: ignore
122131
description: Optional[str] = None
123132
id: Optional[str] = None
124133
doi: Optional[str] = None

src/pds_doi_service/core/input/input_util.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ def __init__(self, valid_extensions=None):
9191
# function pointers
9292
self._parser_map = {
9393
".xml": self.parse_xml_file,
94+
# 20250527; add .lblx to be parsed as xml
95+
".lblx": self.parse_xml_file,
9496
".xls": self.parse_xls_file,
9597
".xlsx": self.parse_xls_file,
9698
".csv": self.parse_csv_file,
@@ -100,6 +102,25 @@ def __init__(self, valid_extensions=None):
100102
if not all([extension in self._parser_map for extension in self._valid_extensions]):
101103
raise ValueError("One or more the provided extensions are not supported by the DOIInputUtil class.")
102104

105+
# 20250501: Detect UTF-16/UTF-8-BOM; decode
106+
def detect_and_decode_utf(Self, data: bytes) -> str:
107+
# Detect and decode UTF-16 (with BOM)
108+
if data.startswith(b"\xff\xfe") or data.startswith(b"\xfe\xff"):
109+
logger.info(f": Detected UTF-16 BOM.")
110+
return data.decode("utf-16")
111+
112+
try:
113+
# Try decoding as UTF-8 with BOM (utf-8-sig handles BOM automatically)
114+
logger.info(f": Trying to detect UTF-8 with BOM (utf-8-sig).")
115+
decoded_data = data.decode("utf-8-sig")
116+
except UnicodeDecodeError:
117+
# Fallback
118+
logger.info(f":Could not decode as UTF-8-sig. Using fallback UTF-8 with replacement.")
119+
decoded_data = data.decode("utf-8", errors="replace")
120+
121+
dos_line_endings = decoded_data.replace("\r\n", "\n").replace("\r", "\n").replace("\n", "\r\n")
122+
return dos_line_endings
123+
103124
def parse_xml_file(self, xml_path):
104125
"""
105126
Parses DOIs from a file with an .xml extension. The file is expected
@@ -473,12 +494,16 @@ def parse_json_file(self, json_path):
473494
validator = DOIServiceFactory.get_validator_service()
474495

475496
# First read the contents of the file
476-
with open(json_path, "r") as infile:
497+
# 20250501: read as binary to avoid encoding issues
498+
with open(json_path, "rb") as infile:
477499
# It's been observed that input files transferred from Windows-based
478500
# machines can append a UTF-8-BOM hex sequence, which breaks
479501
# JSON parsing later on. So we perform an encode-decode here to
480502
# ensure this sequence is stripped before continuing.
481-
json_contents = infile.read().encode().decode("utf-8-sig")
503+
# 20250501: modify code to call routine to detect and decode UTF-16/UTF-8-BOM
504+
# json_contents = infile.read().encode().decode("utf-8-sig")
505+
json_contents = infile.read()
506+
json_contents = self.detect_and_decode_utf(json_contents)
482507

483508
# Validate and parse the provide JSON label based on the service provider
484509
# configured within the INI. If there's a mismatch, the validation step
@@ -593,7 +618,7 @@ def _read_from_remote(self, input_url):
593618
raise InputFormatException(f"Could not read remote file {input_url}, reason: {str(http_err)}")
594619

595620
with tempfile.NamedTemporaryFile(suffix=basename(parsed_url.path)) as temp_file:
596-
temp_file.write(response.content)
621+
temp_file.write(response.content, encoding="utf-8")
597622
temp_file.seek(0)
598623

599624
dois = self._read_from_path(temp_file.name)

0 commit comments

Comments
 (0)