Initial commit - Selenium automation framework

This commit is contained in:
2026-09-08 09:24:02 +05:30
commit e84b7e9950
76 changed files with 7484 additions and 0 deletions
@@ -0,0 +1,167 @@
from pathlib import Path
import re
import zipfile
from xml.etree import ElementTree as ET
MAIN_NS = {"a": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
REL_NS = {"r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships"}
PACKAGE_REL_NS = {"pr": "http://schemas.openxmlformats.org/package/2006/relationships"}
def load_single_bid_market_matrix(excel_path, trading_market, sheet_name="Sheet1", excel_layout=None):
excel_file = Path(excel_path)
if not excel_file.exists():
raise FileNotFoundError(f"Excel input file not found: {excel_file}")
layout = excel_layout or {}
with zipfile.ZipFile(excel_file) as workbook_zip:
shared_strings = _load_shared_strings(workbook_zip)
sheet_xml_path = _resolve_sheet_xml_path(workbook_zip, sheet_name)
sheet_root = ET.fromstring(workbook_zip.read(sheet_xml_path))
cell_map = _load_cell_map(sheet_root, shared_strings)
start_column = layout.get("column_start", "B")
market_price_rows = layout.get("market_price_rows", {})
common_data_start_row = int(layout.get("common_data_start_row", 6))
price_row = int(market_price_rows.get(trading_market, 2))
_, start_col = _split_cell_reference(f"{start_column}1")
max_row, max_col = _max_used_extent(cell_map, price_row, start_col)
matrix = []
for row_index in [price_row, *range(common_data_start_row, max_row + 1)]:
row_values = []
for col_index in range(start_col, max_col + 1):
row_values.append(cell_map.get((row_index, col_index), ""))
matrix.append(row_values)
matrix = _trim_trailing_empty_rows_and_columns(matrix)
if not matrix or not matrix[0]:
raise ValueError(f"No bidding data found in {excel_file} for market {trading_market}.")
tsv = "\n".join("\t".join(value for value in row) for row in matrix)
return {
"matrix": matrix,
"tsv": tsv,
"row_count": len(matrix),
"column_count": len(matrix[0]),
"first_value": matrix[0][0],
}
def _load_shared_strings(workbook_zip):
try:
root = ET.fromstring(workbook_zip.read("xl/sharedStrings.xml"))
except KeyError:
return []
values = []
for item in root.findall("a:si", MAIN_NS):
text_parts = [node.text or "" for node in item.findall(".//a:t", MAIN_NS)]
values.append("".join(text_parts))
return values
def _resolve_sheet_xml_path(workbook_zip, sheet_name):
workbook_root = ET.fromstring(workbook_zip.read("xl/workbook.xml"))
relationships_root = ET.fromstring(workbook_zip.read("xl/_rels/workbook.xml.rels"))
relationship_map = {
rel.attrib["Id"]: rel.attrib["Target"]
for rel in relationships_root.findall("pr:Relationship", PACKAGE_REL_NS)
}
for sheet in workbook_root.findall("a:sheets/a:sheet", {**MAIN_NS, **REL_NS}):
if sheet.attrib.get("name") != sheet_name:
continue
relationship_id = sheet.attrib.get(f"{{{REL_NS['r']}}}id")
target = relationship_map[relationship_id]
target = target.lstrip("/")
if not target.startswith("xl/"):
target = f"xl/{target}"
return target
raise KeyError(f"Sheet '{sheet_name}' not found in workbook.")
def _load_cell_map(sheet_root, shared_strings):
cell_map = {}
for row in sheet_root.findall(".//a:sheetData/a:row", MAIN_NS):
for cell in row.findall("a:c", MAIN_NS):
reference = cell.attrib.get("r", "")
row_index, col_index = _split_cell_reference(reference)
cell_map[(row_index, col_index)] = _cell_value(cell, shared_strings)
return cell_map
def _cell_value(cell, shared_strings):
cell_type = cell.attrib.get("t")
if cell_type == "inlineStr":
text_nodes = cell.findall(".//a:t", MAIN_NS)
return "".join(node.text or "" for node in text_nodes)
value_node = cell.find("a:v", MAIN_NS)
if value_node is None or value_node.text is None:
return ""
raw_value = value_node.text
if cell_type == "s":
return shared_strings[int(raw_value)]
return raw_value
def _split_cell_reference(reference):
match = re.match(r"([A-Z]+)(\d+)", reference)
if not match:
raise ValueError(f"Unsupported cell reference: {reference}")
column_letters, row_number = match.groups()
return int(row_number), _column_letters_to_number(column_letters)
def _column_letters_to_number(column_letters):
result = 0
for character in column_letters:
result = result * 26 + (ord(character) - ord("A") + 1)
return result
def _max_used_extent(cell_map, start_row, start_col):
used_rows = [row for row, col in cell_map if row >= start_row and col >= start_col and cell_map[(row, col)] != ""]
used_cols = [col for row, col in cell_map if row >= start_row and col >= start_col and cell_map[(row, col)] != ""]
if not used_rows or not used_cols:
raise ValueError("No populated cells were found in the requested data area.")
return max(used_rows), max(used_cols)
def _trim_trailing_empty_rows_and_columns(matrix):
while matrix and all(value == "" for value in matrix[-1]):
matrix.pop()
if not matrix:
return matrix
while matrix and matrix[0]:
if any(row[-1] != "" for row in matrix):
break
for row in matrix:
row.pop()
return matrix