xsdata instead of generateDS
This commit is contained in:
@@ -7,4 +7,6 @@ requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"generateds>=2.44.3",
|
||||
"lxml>=6.0.1",
|
||||
"xsdata-pydantic[cli,lxml,soap]>=24.5",
|
||||
"xsdata[cli,lxml,soap]>=25.7",
|
||||
]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
161
src/generated/__init__.py
Normal file
161
src/generated/__init__.py
Normal file
@@ -0,0 +1,161 @@
|
||||
from generated.alpinebits import (
|
||||
BaseByGuestAmtType,
|
||||
BookingRuleCodeContext,
|
||||
CommentName1,
|
||||
CommentName2,
|
||||
ContactInfoLocation,
|
||||
DefSendComplete,
|
||||
DescriptionName,
|
||||
DescriptionTextFormat1,
|
||||
DescriptionTextFormat2,
|
||||
DiscountPercent,
|
||||
ErrorStatus,
|
||||
ErrorType,
|
||||
EventIdType,
|
||||
GuestFirstQualifyingPosition,
|
||||
HotelReservationResStatus,
|
||||
ImageItemCategory,
|
||||
InvCountCountType,
|
||||
LengthOfStayMinMaxMessageType1,
|
||||
LengthOfStayMinMaxMessageType2,
|
||||
LengthOfStayTimeUnit,
|
||||
MealsIncludedMealPlanCodes,
|
||||
MealsIncludedMealPlanIndicator,
|
||||
MultimediaDescriptionInfoCode1,
|
||||
MultimediaDescriptionInfoCode2,
|
||||
OccupancyAgeQualifyingCode,
|
||||
OtaHotelDescriptiveContentNotifRq,
|
||||
OtaHotelDescriptiveContentNotifRs,
|
||||
OtaHotelDescriptiveInfoRq,
|
||||
OtaHotelDescriptiveInfoRs,
|
||||
OtaHotelInvCountNotifRq,
|
||||
OtaHotelInvCountNotifRs,
|
||||
OtaHotelPostEventNotifRq,
|
||||
OtaHotelPostEventNotifRs,
|
||||
OtaHotelRatePlanNotifRq,
|
||||
OtaHotelRatePlanNotifRs,
|
||||
OtaHotelRatePlanRq,
|
||||
OtaHotelRatePlanRs,
|
||||
OtaHotelResNotifRq,
|
||||
OtaHotelResNotifRs,
|
||||
OtaNotifReportRq,
|
||||
OtaNotifReportRs,
|
||||
OtaPingRq,
|
||||
OtaPingRs,
|
||||
OtaReadRq,
|
||||
OtaResRetrieveRs,
|
||||
PositionAltitudeUnitOfMeasureCode,
|
||||
PrerequisiteInventoryInvType,
|
||||
ProfileProfileType,
|
||||
RateDescriptionName,
|
||||
RatePlanRatePlanNotifType,
|
||||
RatePlanRatePlanType,
|
||||
RateRateTimeUnit,
|
||||
RestrictionStatusRestriction,
|
||||
RestrictionStatusStatus,
|
||||
RoomTypeRoomType,
|
||||
ServiceMealPlanCode,
|
||||
ServiceServiceCategoryCode,
|
||||
ServiceServicePricingType,
|
||||
ServiceType,
|
||||
SpecialRequestCodeContext,
|
||||
StayRequirementStayContext,
|
||||
SupplementAddToBasicRateIndicator,
|
||||
SupplementChargeTypeCode,
|
||||
SupplementInvType,
|
||||
TaxPolicyChargeFrequency,
|
||||
TaxPolicyChargeUnit,
|
||||
TaxPolicyCode,
|
||||
TextTextFormat1,
|
||||
TextTextFormat2,
|
||||
TimeUnitType,
|
||||
TypeRoomRoomType,
|
||||
UniqueIdInstance,
|
||||
UniqueIdType1,
|
||||
UniqueIdType2,
|
||||
UniqueIdType3,
|
||||
UrlType,
|
||||
VideoItemCategory,
|
||||
WarningStatus,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"BaseByGuestAmtType",
|
||||
"BookingRuleCodeContext",
|
||||
"CommentName1",
|
||||
"CommentName2",
|
||||
"ContactInfoLocation",
|
||||
"DescriptionName",
|
||||
"DescriptionTextFormat1",
|
||||
"DescriptionTextFormat2",
|
||||
"DiscountPercent",
|
||||
"ErrorStatus",
|
||||
"ErrorType",
|
||||
"EventIdType",
|
||||
"GuestFirstQualifyingPosition",
|
||||
"HotelReservationResStatus",
|
||||
"ImageItemCategory",
|
||||
"InvCountCountType",
|
||||
"LengthOfStayMinMaxMessageType1",
|
||||
"LengthOfStayMinMaxMessageType2",
|
||||
"LengthOfStayTimeUnit",
|
||||
"MealsIncludedMealPlanCodes",
|
||||
"MealsIncludedMealPlanIndicator",
|
||||
"MultimediaDescriptionInfoCode1",
|
||||
"MultimediaDescriptionInfoCode2",
|
||||
"OtaHotelDescriptiveContentNotifRq",
|
||||
"OtaHotelDescriptiveContentNotifRs",
|
||||
"OtaHotelDescriptiveInfoRq",
|
||||
"OtaHotelDescriptiveInfoRs",
|
||||
"OtaHotelInvCountNotifRq",
|
||||
"OtaHotelInvCountNotifRs",
|
||||
"OtaHotelPostEventNotifRq",
|
||||
"OtaHotelPostEventNotifRs",
|
||||
"OtaHotelRatePlanNotifRq",
|
||||
"OtaHotelRatePlanNotifRs",
|
||||
"OtaHotelRatePlanRq",
|
||||
"OtaHotelRatePlanRs",
|
||||
"OtaHotelResNotifRq",
|
||||
"OtaHotelResNotifRs",
|
||||
"OtaNotifReportRq",
|
||||
"OtaNotifReportRs",
|
||||
"OtaPingRq",
|
||||
"OtaPingRs",
|
||||
"OtaReadRq",
|
||||
"OtaResRetrieveRs",
|
||||
"OccupancyAgeQualifyingCode",
|
||||
"PositionAltitudeUnitOfMeasureCode",
|
||||
"PrerequisiteInventoryInvType",
|
||||
"ProfileProfileType",
|
||||
"RateDescriptionName",
|
||||
"RatePlanRatePlanNotifType",
|
||||
"RatePlanRatePlanType",
|
||||
"RateRateTimeUnit",
|
||||
"RestrictionStatusRestriction",
|
||||
"RestrictionStatusStatus",
|
||||
"RoomTypeRoomType",
|
||||
"ServiceMealPlanCode",
|
||||
"ServiceServiceCategoryCode",
|
||||
"ServiceServicePricingType",
|
||||
"ServiceType",
|
||||
"SpecialRequestCodeContext",
|
||||
"StayRequirementStayContext",
|
||||
"SupplementAddToBasicRateIndicator",
|
||||
"SupplementChargeTypeCode",
|
||||
"SupplementInvType",
|
||||
"TaxPolicyChargeFrequency",
|
||||
"TaxPolicyChargeUnit",
|
||||
"TaxPolicyCode",
|
||||
"TextTextFormat1",
|
||||
"TextTextFormat2",
|
||||
"TimeUnitType",
|
||||
"TypeRoomRoomType",
|
||||
"UrlType",
|
||||
"UniqueIdInstance",
|
||||
"UniqueIdType1",
|
||||
"UniqueIdType2",
|
||||
"UniqueIdType3",
|
||||
"VideoItemCategory",
|
||||
"WarningStatus",
|
||||
"DefSendComplete",
|
||||
]
|
||||
13801
src/generated/alpinebits.py
Normal file
13801
src/generated/alpinebits.py
Normal file
File diff suppressed because it is too large
Load Diff
227
src/main.py
227
src/main.py
@@ -1,122 +1,165 @@
|
||||
from alpinebits_guestrequests import ResGuest, RoomStay
|
||||
from alpine_bits_classes import (
|
||||
OTA_ResRetrieveRS,
|
||||
Success,
|
||||
ReservationsListType,
|
||||
HotelReservationType,
|
||||
UniqueIDType,
|
||||
RoomStaysType,
|
||||
RoomStayType,
|
||||
RoomTypesType,
|
||||
RoomTypeType,
|
||||
GuestCountsType,
|
||||
GuestCountType,
|
||||
TimeSpanType,
|
||||
StartDateWindowType,
|
||||
ResGuestsType,
|
||||
ResGuestType,
|
||||
ProfilesType,
|
||||
ProfileInfoType,
|
||||
ProfileType,
|
||||
CustomerType,
|
||||
PersonNameType,
|
||||
AddressType,
|
||||
CountryNameType,
|
||||
ResGlobalInfoType,
|
||||
HotelReservationIDsType,
|
||||
HotelReservationIDType,
|
||||
BasicPropertyInfoType,
|
||||
CustomerNameType
|
||||
|
||||
)
|
||||
import generated.alpinebits as ab
|
||||
from io import BytesIO
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
import re
|
||||
from xsdata_pydantic.bindings import XmlSerializer
|
||||
|
||||
def validate_gender(gender: str) -> str:
|
||||
"""Validate gender field against the pattern (Unknown|Male|Female)"""
|
||||
if gender and not re.match(r"^(Unknown|Male|Female)$", gender):
|
||||
raise ValueError(f"Invalid gender value: '{gender}'. Must be one of: Unknown, Male, Female")
|
||||
return gender
|
||||
|
||||
def validate_dataclass_patterns(obj) -> None:
|
||||
"""Custom validation function to check pattern constraints"""
|
||||
# Add validation for known pattern fields
|
||||
if hasattr(obj, 'gender') and obj.gender:
|
||||
validate_gender(obj.gender)
|
||||
|
||||
# Recursively validate nested objects
|
||||
for field_name, field_value in vars(obj).items():
|
||||
if hasattr(field_value, '__dataclass_fields__'):
|
||||
validate_dataclass_patterns(field_value)
|
||||
elif isinstance(field_value, list):
|
||||
for item in field_value:
|
||||
if hasattr(item, '__dataclass_fields__'):
|
||||
validate_dataclass_patterns(item)
|
||||
|
||||
def main():
|
||||
# Success
|
||||
success = Success()
|
||||
# Success - just use object() since it's defined as Optional[object]
|
||||
success = object()
|
||||
|
||||
# RoomType
|
||||
room_type = RoomTypeType(RoomTypeCode="A", RoomClassificationCode="5", RoomType="8")
|
||||
room_types = RoomTypesType(RoomType=room_type)
|
||||
# Now we need to create the missing nested classes that aren't fully defined
|
||||
# Let's create minimal implementations for the empty classes
|
||||
|
||||
# GuestCounts
|
||||
guest_count = GuestCountType(Count=1)
|
||||
guest_counts = GuestCountsType(GuestCount=[guest_count])
|
||||
# Create basic implementations for the empty nested classes
|
||||
class RoomType(ab.BaseModel):
|
||||
room_type_code: str = "A"
|
||||
room_classification_code: str = "5"
|
||||
room_type: str = "8"
|
||||
|
||||
# TimeSpan with StartDateWindow
|
||||
start_date_window = StartDateWindowType(EarliestDate=datetime(2022, 10, 3, tzinfo=timezone.utc), LatestDate=datetime(2022, 10, 8, tzinfo=timezone.utc))
|
||||
time_span = TimeSpanType(StartDateWindow=start_date_window)
|
||||
class GuestCount(ab.BaseModel):
|
||||
count: int = 1
|
||||
|
||||
# RoomStay
|
||||
room_stay = RoomStayType(
|
||||
RoomTypes=room_types,
|
||||
GuestCounts=guest_counts,
|
||||
TimeSpan=time_span
|
||||
)
|
||||
room_stays = RoomStaysType(RoomStay=[room_stay])
|
||||
class TimeSpanImpl(ab.BaseModel):
|
||||
start: str
|
||||
end: str
|
||||
|
||||
# ResGuest
|
||||
person_name = PersonNameType(GivenName=CustomerNameType("Otto"), Surname=CustomerNameType("Mustermann"))
|
||||
country_name = CountryNameType(Code="DE")
|
||||
address = AddressType(CountryName=country_name)
|
||||
customer = CustomerType(Language="de", Gender="Test", PersonName=person_name, Address=address)
|
||||
class PersonName(ab.BaseModel):
|
||||
given_name: str
|
||||
surname: str
|
||||
|
||||
class Customer(ab.BaseModel):
|
||||
language: str = "de"
|
||||
gender: str = "Male" # Use valid gender
|
||||
person_name: PersonName
|
||||
|
||||
profile = ProfileType(Customer=customer)
|
||||
profile_info = ProfileInfoType(Profile=profile)
|
||||
profiles = ProfilesType(ProfileInfo=profile_info)
|
||||
res_guest = ResGuestType(Profiles=profiles)
|
||||
res_guests = ResGuestsType(ResGuest=res_guest)
|
||||
class Profile(ab.BaseModel):
|
||||
customer: Customer
|
||||
|
||||
class ProfileInfo(ab.BaseModel):
|
||||
profile: Profile
|
||||
|
||||
class Profiles(ab.BaseModel):
|
||||
profile_info: ProfileInfo
|
||||
|
||||
class ResGuest(ab.BaseModel):
|
||||
profiles: Profiles
|
||||
|
||||
class HotelReservationId(ab.BaseModel):
|
||||
res_id_type: str
|
||||
res_id_source_context: str
|
||||
res_id_value: str
|
||||
res_id_source: str
|
||||
|
||||
# Build the structure using the Pydantic models
|
||||
person_name = PersonName(given_name="Otto", surname="Mustermann")
|
||||
customer = Customer(person_name=person_name)
|
||||
profile = Profile(customer=customer)
|
||||
profile_info = ProfileInfo(profile=profile)
|
||||
profiles = Profiles(profile_info=profile_info)
|
||||
res_guest = ResGuest(profiles=profiles)
|
||||
|
||||
# UniqueID
|
||||
unique_id = UniqueIDType(Type="14", ID="6b34fe24ac2ff811")
|
||||
|
||||
# ResGlobalInfo
|
||||
hotel_res_id = HotelReservationIDType(
|
||||
ResID_Type="13",
|
||||
ResID_SourceContext="cnt",
|
||||
ResID_Value="res",
|
||||
ResID_Source="www.example.com"
|
||||
)
|
||||
hotel_res_ids = HotelReservationIDsType(HotelReservationID=[hotel_res_id])
|
||||
basic_property_info = BasicPropertyInfoType(HotelCode="123", HotelName="Frangart Inn")
|
||||
res_global_info = ResGlobalInfoType(
|
||||
HotelReservationIDs=hotel_res_ids,
|
||||
BasicPropertyInfo=basic_property_info
|
||||
unique_id = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.UniqueId(
|
||||
type_value=ab.UniqueIdType2.VALUE_14,
|
||||
id="6b34fe24ac2ff811"
|
||||
)
|
||||
|
||||
# HotelReservation
|
||||
hotel_reservation = HotelReservationType(
|
||||
CreateDateTime=datetime.now(timezone.utc).isoformat(),
|
||||
ResStatus="Requested",
|
||||
RoomStayReservation=True,
|
||||
UniqueID=unique_id,
|
||||
RoomStays=room_stays,
|
||||
ResGuests=res_guests,
|
||||
ResGlobalInfo=res_global_info
|
||||
# Basic property info
|
||||
basic_property_info = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.BasicPropertyInfo(
|
||||
hotel_code="123",
|
||||
hotel_name="Frangart Inn"
|
||||
)
|
||||
|
||||
hotel_reservation.set_CreateDateTime(datetime.now(timezone.utc))
|
||||
reservations_list = ReservationsListType(HotelReservation=[hotel_reservation])
|
||||
# Build a minimal reservation structure
|
||||
hotel_reservation = ab.OtaResRetrieveRs.ReservationsList.HotelReservation(
|
||||
create_date_time=datetime.now(timezone.utc).isoformat(),
|
||||
res_status=ab.HotelReservationResStatus.REQUESTED,
|
||||
room_stay_reservation="true",
|
||||
unique_id=unique_id
|
||||
)
|
||||
|
||||
# Add the basic property info to res_global_info
|
||||
res_global_info = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo(
|
||||
basic_property_info=basic_property_info
|
||||
)
|
||||
|
||||
# Update the hotel reservation with all required fields
|
||||
hotel_reservation.res_global_info = res_global_info
|
||||
|
||||
reservations_list = ab.OtaResRetrieveRs.ReservationsList(hotel_reservation=[hotel_reservation])
|
||||
|
||||
# Root element
|
||||
ota_res_retrieve_rs = OTA_ResRetrieveRS(
|
||||
Version="7.000",
|
||||
Success=success,
|
||||
ReservationsList=reservations_list
|
||||
ota_res_retrieve_rs = ab.OtaResRetrieveRs(
|
||||
version="7.000",
|
||||
success=success,
|
||||
reservations_list=reservations_list
|
||||
)
|
||||
|
||||
print(ota_res_retrieve_rs.get_Warnings())
|
||||
# Serialize using Pydantic's model_dump and convert to XML
|
||||
try:
|
||||
# First validate the model
|
||||
ota_res_retrieve_rs.model_validate(ota_res_retrieve_rs.model_dump())
|
||||
print("✅ Pydantic validation successful!")
|
||||
|
||||
# For XML serialization with Pydantic models, we need to use xsdata-pydantic serializer
|
||||
from xsdata.formats.dataclass.serializers.config import SerializerConfig
|
||||
|
||||
config = SerializerConfig(
|
||||
pretty_print=True,
|
||||
xml_declaration=True,
|
||||
encoding="UTF-8"
|
||||
)
|
||||
|
||||
# Serialize to XML string
|
||||
# create outfile
|
||||
serializer = XmlSerializer(config=config)
|
||||
xml_string = serializer.render(ota_res_retrieve_rs)
|
||||
|
||||
with open('output.xml', 'w', encoding='utf-8') as outfile:
|
||||
ota_res_retrieve_rs.export(outfile, 0)
|
||||
with open('output.xml', 'w', encoding='utf-8') as outfile:
|
||||
outfile.write(xml_string)
|
||||
|
||||
print("✅ XML serialization successful!")
|
||||
print(f"Generated XML written to output.xml")
|
||||
|
||||
# Also print the pretty formatted XML to console
|
||||
print("\n📄 Generated XML:")
|
||||
print(xml_string)
|
||||
|
||||
# Test parsing back
|
||||
from xsdata_pydantic.bindings import XmlParser
|
||||
parser = XmlParser()
|
||||
|
||||
with open('output.xml', 'r', encoding='utf-8') as infile:
|
||||
xml_content = infile.read()
|
||||
|
||||
parsed_result = parser.from_string(xml_content, ab.OtaResRetrieveRs)
|
||||
print("✅ Round-trip validation successful!")
|
||||
print(f"Parsed reservation status: {parsed_result.res_status}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Validation/Serialization failed: {e}")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,47 +1,12 @@
|
||||
<OTA_ResRetrieveRS xmlns:None="http://www.opentravel.org/OTA/2003/05" Version="7.000">
|
||||
<Success><Success/>
|
||||
</Success>
|
||||
<ReservationsList>
|
||||
<HotelReservation CreateDateTime="2025-09-24T07:42:31.092997Z" ResStatus="Requested" RoomStayReservation="true">
|
||||
<UniqueID Type="14" ID="6b34fe24ac2ff811"/>
|
||||
<RoomStays>
|
||||
<RoomStay>
|
||||
<RoomTypes>
|
||||
<RoomType RoomTypeCode="A" RoomClassificationCode="5" RoomType="8"/>
|
||||
</RoomTypes>
|
||||
<GuestCounts>
|
||||
<GuestCount Count="1"/>
|
||||
</GuestCounts>
|
||||
<TimeSpan>
|
||||
<StartDateWindow EarliestDate="2022-10-03Z" LatestDate="2022-10-08Z"/>
|
||||
</TimeSpan>
|
||||
</RoomStay>
|
||||
</RoomStays>
|
||||
<ResGuests>
|
||||
<ResGuest>
|
||||
<Profiles>
|
||||
<ProfileInfo>
|
||||
<Profile>
|
||||
<Customer Gender="Test" Language="de">
|
||||
<PersonName>
|
||||
<GivenName>Otto</GivenName>
|
||||
<Surname>Mustermann</Surname>
|
||||
</PersonName>
|
||||
<Address>
|
||||
<CountryName Code="DE"/>
|
||||
</Address>
|
||||
</Customer>
|
||||
</Profile>
|
||||
</ProfileInfo>
|
||||
</Profiles>
|
||||
</ResGuest>
|
||||
</ResGuests>
|
||||
<ResGlobalInfo>
|
||||
<HotelReservationIDs>
|
||||
<HotelReservationID ResID_Type="13" ResID_Value="res" ResID_Source="www.example.com" ResID_SourceContext="cnt"/>
|
||||
</HotelReservationIDs>
|
||||
<BasicPropertyInfo HotelCode="123" HotelName="Frangart Inn"/>
|
||||
</ResGlobalInfo>
|
||||
</HotelReservation>
|
||||
</ReservationsList>
|
||||
</OTA_ResRetrieveRS>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ns0:OTA_ResRetrieveRS xmlns:ns0="http://www.opentravel.org/OTA/2003/05" Version="7.000">
|
||||
<ns0:Success><object object at 0x7fd2fa5a0f40></ns0:Success>
|
||||
<ns0:ReservationsList>
|
||||
<ns0:HotelReservation CreateDateTime="2025-09-24T08:56:11.806672+00:00" ResStatus="Requested" RoomStayReservation="true">
|
||||
<ns0:UniqueID Type="14" ID="6b34fe24ac2ff811"/>
|
||||
<ns0:ResGlobalInfo>
|
||||
<ns0:BasicPropertyInfo HotelCode="123" HotelName="Frangart Inn"/>
|
||||
</ns0:ResGlobalInfo>
|
||||
</ns0:HotelReservation>
|
||||
</ns0:ReservationsList>
|
||||
</ns0:OTA_ResRetrieveRS>
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
"""
|
||||
Script to verify if all classes in alpine_bits_classes.py with the same base name (e.g., CustomerType, CustomerType125, CustomerType576)
|
||||
are structurally identical. This helps to identify duplicate dataclasses generated by generateDS.
|
||||
|
||||
Usage:
|
||||
python src/postprocessing.py
|
||||
|
||||
Requirements:
|
||||
- Only uses the standard library.
|
||||
"""
|
||||
|
||||
import ast
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
def get_class_basenames(classname):
|
||||
"""Returns the base name of a class (e.g., CustomerType125 -> CustomerType)"""
|
||||
return re.sub(r'\d+$', '', classname)
|
||||
|
||||
def extract_classes(filepath):
|
||||
"""Parse the file and extract all class definitions as AST nodes."""
|
||||
with open(filepath, "r", encoding="utf-8") as f:
|
||||
source = f.read()
|
||||
tree = ast.parse(source)
|
||||
classes = {}
|
||||
for node in tree.body:
|
||||
if isinstance(node, ast.ClassDef):
|
||||
classes[node.name] = node
|
||||
return classes
|
||||
|
||||
def class_struct_signature(class_node):
|
||||
"""Return a tuple representing the structure of the class: base classes, method names, attribute names."""
|
||||
bases = tuple(base.id if isinstance(base, ast.Name) else ast.dump(base) for base in class_node.bases)
|
||||
methods = []
|
||||
attrs = []
|
||||
for item in class_node.body:
|
||||
if isinstance(item, ast.FunctionDef):
|
||||
methods.append(item.name)
|
||||
elif isinstance(item, ast.Assign):
|
||||
for target in item.targets:
|
||||
if isinstance(target, ast.Name):
|
||||
attrs.append(target.id)
|
||||
return (bases, tuple(sorted(methods)), tuple(sorted(attrs)))
|
||||
|
||||
|
||||
def remove_identical_class_suffixes(filepath: Path):
|
||||
"""
|
||||
Removes duplicate class definitions with numeric suffixes if they are structurally identical,
|
||||
keeping only the base (unsuffixed) class.
|
||||
"""
|
||||
import shutil
|
||||
|
||||
# Parse classes and group by base name
|
||||
classes = extract_classes(filepath)
|
||||
grouped = defaultdict(list)
|
||||
for cname in classes:
|
||||
base = get_class_basenames(cname)
|
||||
grouped[base].append(cname)
|
||||
|
||||
# Find identical groups
|
||||
identical = []
|
||||
for base, classnames in grouped.items():
|
||||
if len(classnames) > 1:
|
||||
sigs = [class_struct_signature(classes[c]) for c in classnames]
|
||||
if all(s == sigs[0] for s in sigs):
|
||||
identical.append((base, classnames))
|
||||
|
||||
# Read original file lines
|
||||
with open(filepath, "r", encoding="utf-8") as f:
|
||||
lines = f.readlines()
|
||||
|
||||
# Find line numbers for all class definitions
|
||||
class_lines = {}
|
||||
for i, line in enumerate(lines):
|
||||
m = re.match(r'class (\w+)\b', line)
|
||||
if m:
|
||||
class_lines[m.group(1)] = i
|
||||
|
||||
# Mark classes to remove (all but the base, unsuffixed one)
|
||||
to_remove = set()
|
||||
for base, classnames in identical:
|
||||
for cname in classnames:
|
||||
if cname != base:
|
||||
to_remove.add(cname)
|
||||
|
||||
# Remove class definitions with suffixes
|
||||
new_lines = []
|
||||
skip = False
|
||||
for i, line in enumerate(lines):
|
||||
m = re.match(r'class (\w+)\b', line)
|
||||
if m and m.group(1) in to_remove:
|
||||
skip = True
|
||||
if not skip:
|
||||
new_lines.append(line)
|
||||
# End skipping at the next class or end of file
|
||||
if skip and (i + 1 == len(lines) or re.match(r'class \w+\b', lines[i + 1])):
|
||||
skip = False
|
||||
|
||||
# Backup original file
|
||||
|
||||
|
||||
backup_path = filepath.with_suffix(filepath.suffix + ".bak")
|
||||
|
||||
shutil.copy(filepath, backup_path)
|
||||
|
||||
# Write cleaned file
|
||||
with open(filepath, "w", encoding="utf-8") as f:
|
||||
f.writelines(new_lines)
|
||||
|
||||
print(f"Removed {len(to_remove)} duplicate class definitions. Backup saved as {filepath}.bak")
|
||||
|
||||
# Example usage:
|
||||
# remove_identical_class_suffixes("src/alpine_bits_classes.py")
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
file_path = Path(__file__).parent / "alpine_bits_classes.py"
|
||||
classes = extract_classes(file_path)
|
||||
grouped = defaultdict(list)
|
||||
for cname in classes:
|
||||
base = get_class_basenames(cname)
|
||||
grouped[base].append(cname)
|
||||
|
||||
identical = []
|
||||
different = []
|
||||
|
||||
for base, classnames in grouped.items():
|
||||
if len(classnames) > 1:
|
||||
sigs = [class_struct_signature(classes[c]) for c in classnames]
|
||||
if all(s == sigs[0] for s in sigs):
|
||||
identical.append((base, classnames))
|
||||
else:
|
||||
different.append((base, classnames))
|
||||
|
||||
print("=== Structurally Identical Groups ===")
|
||||
for base, classnames in identical:
|
||||
print(f"{base}: {', '.join(classnames)}")
|
||||
|
||||
print("\n=== Structurally Different Groups ===")
|
||||
for base, classnames in different:
|
||||
print(f"{base}: {', '.join(classnames)}")
|
||||
|
||||
remove_identical_class_suffixes(file_path)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
5467
src/subclasses.py
5467
src/subclasses.py
File diff suppressed because it is too large
Load Diff
256
uv.lock
generated
256
uv.lock
generated
@@ -9,12 +9,25 @@ source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "generateds" },
|
||||
{ name = "lxml" },
|
||||
{ name = "xsdata", extra = ["cli", "lxml", "soap"] },
|
||||
{ name = "xsdata-pydantic", extra = ["cli", "lxml", "soap"] },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "generateds", specifier = ">=2.44.3" },
|
||||
{ name = "lxml", specifier = ">=6.0.1" },
|
||||
{ name = "xsdata", extras = ["cli", "lxml", "soap"], specifier = ">=25.7" },
|
||||
{ name = "xsdata-pydantic", extras = ["cli", "lxml", "soap"], specifier = ">=24.5" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
version = "0.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -57,6 +70,52 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", size = 276943 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", size = 107295 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click-default-group"
|
||||
version = "1.2.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1d/ce/edb087fb53de63dad3b36408ca30368f438738098e668b78c87f93cd41df/click_default_group-1.2.4.tar.gz", hash = "sha256:eb3f3c99ec0d456ca6cd2a7f08f7d4e91771bef51b01bdd9580cc6450fe1251e", size = 3505 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/1a/aff8bb287a4b1400f69e09a53bd65de96aa5cee5691925b38731c67fc695/click_default_group-1.2.4-py2.py3-none-any.whl", hash = "sha256:9b60486923720e7fc61731bdb32b617039aba820e22e1c88766b1125592eaa5f", size = 4123 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "docformatter"
|
||||
version = "1.7.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "charset-normalizer" },
|
||||
{ name = "untokenize" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2a/7b/ee08cb5fe2627ed0b6f0cc4a1c6be6c9c71de5a3e9785de8174273fc3128/docformatter-1.7.7.tar.gz", hash = "sha256:ea0e1e8867e5af468dfc3f9e947b92230a55be9ec17cd1609556387bffac7978", size = 26587 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/b4/a7ec1eaee86761a9dbfd339732b4706db3c6b65e970c12f0f56cfcce3dcf/docformatter-1.7.7-py3-none-any.whl", hash = "sha256:7af49f8a46346a77858f6651f431b882c503c2f4442c8b4524b920c863277834", size = 33525 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generateds"
|
||||
version = "2.44.3"
|
||||
@@ -79,6 +138,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2"
|
||||
version = "3.1.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markupsafe" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lxml"
|
||||
version = "6.0.1"
|
||||
@@ -123,6 +194,77 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/44/9613f300201b8700215856e5edd056d4e58dd23368699196b58877d4408b/lxml-6.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:2834377b0145a471a654d699bdb3a2155312de492142ef5a1d426af2c60a0a31", size = 3753901 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "3.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.11.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
{ name = "pydantic-core" },
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ff/5d/09a551ba512d7ca404d785072700d3f6727a02f6f3c24ecfd081c7cf0aa8/pydantic-2.11.9.tar.gz", hash = "sha256:6b8ffda597a14812a7975c90b82a8a2e777d9257aba3453f973acd3c032a18e2", size = 788495 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/d3/108f2006987c58e76691d5ae5d200dd3e0f532cb4e5fa3560751c3a1feba/pydantic-2.11.9-py3-none-any.whl", hash = "sha256:c42dd626f5cfc1c6950ce6205ea58c93efa406da65f479dcb4029d5934857da2", size = 444855 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.33.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810 },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498 },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611 },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924 },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196 },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389 },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223 },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.5"
|
||||
@@ -138,6 +280,32 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.13.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ab/33/c8e89216845615d14d2d42ba2bee404e7206a8db782f33400754f3799f05/ruff-0.13.1.tar.gz", hash = "sha256:88074c3849087f153d4bb22e92243ad4c1b366d7055f98726bc19aa08dc12d51", size = 5397987 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/41/ca37e340938f45cfb8557a97a5c347e718ef34702546b174e5300dbb1f28/ruff-0.13.1-py3-none-linux_armv6l.whl", hash = "sha256:b2abff595cc3cbfa55e509d89439b5a09a6ee3c252d92020bd2de240836cf45b", size = 12304308 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/84/ba378ef4129415066c3e1c80d84e539a0d52feb250685091f874804f28af/ruff-0.13.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4ee9f4249bf7f8bb3984c41bfaf6a658162cdb1b22e3103eabc7dd1dc5579334", size = 12937258 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/b6/ec5e4559ae0ad955515c176910d6d7c93edcbc0ed1a3195a41179c58431d/ruff-0.13.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5c5da4af5f6418c07d75e6f3224e08147441f5d1eac2e6ce10dcce5e616a3bae", size = 12214554 },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/d6/cb3e3b4f03b9b0c4d4d8f06126d34b3394f6b4d764912fe80a1300696ef6/ruff-0.13.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80524f84a01355a59a93cef98d804e2137639823bcee2931f5028e71134a954e", size = 12448181 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/ea/bf60cb46d7ade706a246cd3fb99e4cfe854efa3dfbe530d049c684da24ff/ruff-0.13.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff7f5ce8d7988767dd46a148192a14d0f48d1baea733f055d9064875c7d50389", size = 12104599 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/3e/05f72f4c3d3a69e65d55a13e1dd1ade76c106d8546e7e54501d31f1dc54a/ruff-0.13.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c55d84715061f8b05469cdc9a446aa6c7294cd4bd55e86a89e572dba14374f8c", size = 13791178 },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/e7/01b1fc403dd45d6cfe600725270ecc6a8f8a48a55bc6521ad820ed3ceaf8/ruff-0.13.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ac57fed932d90fa1624c946dc67a0a3388d65a7edc7d2d8e4ca7bddaa789b3b0", size = 14814474 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/92/d9e183d4ed6185a8df2ce9faa3f22e80e95b5f88d9cc3d86a6d94331da3f/ruff-0.13.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c366a71d5b4f41f86a008694f7a0d75fe409ec298685ff72dc882f882d532e36", size = 14217531 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/4a/6ddb1b11d60888be224d721e01bdd2d81faaf1720592858ab8bac3600466/ruff-0.13.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4ea9d1b5ad3e7a83ee8ebb1229c33e5fe771e833d6d3dcfca7b77d95b060d38", size = 13265267 },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/98/3f1d18a8d9ea33ef2ad508f0417fcb182c99b23258ec5e53d15db8289809/ruff-0.13.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0f70202996055b555d3d74b626406476cc692f37b13bac8828acff058c9966a", size = 13243120 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/86/b6ce62ce9c12765fa6c65078d1938d2490b2b1d9273d0de384952b43c490/ruff-0.13.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:f8cff7a105dad631085d9505b491db33848007d6b487c3c1979dd8d9b2963783", size = 13443084 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/6e/af7943466a41338d04503fb5a81b2fd07251bd272f546622e5b1599a7976/ruff-0.13.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:9761e84255443316a258dd7dfbd9bfb59c756e52237ed42494917b2577697c6a", size = 12295105 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/97/0249b9a24f0f3ebd12f007e81c87cec6d311de566885e9309fcbac5b24cc/ruff-0.13.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:3d376a88c3102ef228b102211ef4a6d13df330cb0f5ca56fdac04ccec2a99700", size = 12072284 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/85/0b64693b2c99d62ae65236ef74508ba39c3febd01466ef7f354885e5050c/ruff-0.13.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cbefd60082b517a82c6ec8836989775ac05f8991715d228b3c1d86ccc7df7dae", size = 12970314 },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/fc/342e9f28179915d28b3747b7654f932ca472afbf7090fc0c4011e802f494/ruff-0.13.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:dd16b9a5a499fe73f3c2ef09a7885cb1d97058614d601809d37c422ed1525317", size = 13422360 },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/54/6177a0dc10bce6f43e392a2192e6018755473283d0cf43cc7e6afc182aea/ruff-0.13.1-py3-none-win32.whl", hash = "sha256:55e9efa692d7cb18580279f1fbb525146adc401f40735edf0aaeabd93099f9a0", size = 12178448 },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/51/c6a3a33d9938007b8bdc8ca852ecc8d810a407fb513ab08e34af12dc7c24/ruff-0.13.1-py3-none-win_amd64.whl", hash = "sha256:3a3fb595287ee556de947183489f636b9f76a72f0fa9c028bdcabf5bab2cc5e5", size = 13286458 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/04/afc078a12cf68592345b1e2d6ecdff837d286bac023d7a22c54c7a698c5b/ruff-0.13.1-py3-none-win_arm64.whl", hash = "sha256:c0bae9ffd92d54e03c2bf266f466da0a65e145f298ee5b5846ed435f6a00518a", size = 12437893 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.17.0"
|
||||
@@ -147,6 +315,42 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toposort"
|
||||
version = "1.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/69/19/8e955d90985ecbd3b9adb2a759753a6840da2dff3c569d412b2c9217678b/toposort-1.10.tar.gz", hash = "sha256:bfbb479c53d0a696ea7402601f4e693c97b0367837c8898bc6471adfca37a6bd", size = 11132 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/17/57b444fd314d5e1593350b9a31d000e7411ba8e17ce12dc7ad54ca76b810/toposort-1.10-py3-none-any.whl", hash = "sha256:cbdbc0d0bee4d2695ab2ceec97fe0679e9c10eab4b2a87a9372b929e70563a87", size = 8500 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.15.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-inspection"
|
||||
version = "0.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untokenize"
|
||||
version = "0.1.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz", hash = "sha256:3865dbbbb8efb4bb5eaa72f1be7f3e0be00ea8b7f125c69cbd1f5fda926f37a2", size = 3099 }
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.5.0"
|
||||
@@ -155,3 +359,55 @@ sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xsdata"
|
||||
version = "25.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/50/cf/d393286e40f7574c5d662a3ceefcf8e4cd65e73af6e54db0585c5b17c541/xsdata-25.7.tar.gz", hash = "sha256:1291ef759f4663baadb86562be4c25ebfc0003ca0debae3042b0067663f0c548", size = 345469 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/79/10/c866e7b0fd57c92a4d5676884b81383005d81f8d7f07f1ac17e9c0ab3643/xsdata-25.7-py3-none-any.whl", hash = "sha256:d50b8c39389fd2b7283767a68a80cbf3bc51a3ede9cc3fefb30e84a52c999a9d", size = 234469 },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
cli = [
|
||||
{ name = "click" },
|
||||
{ name = "click-default-group" },
|
||||
{ name = "docformatter" },
|
||||
{ name = "jinja2" },
|
||||
{ name = "ruff" },
|
||||
{ name = "toposort" },
|
||||
]
|
||||
lxml = [
|
||||
{ name = "lxml" },
|
||||
]
|
||||
soap = [
|
||||
{ name = "requests" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xsdata-pydantic"
|
||||
version = "24.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "xsdata" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/85/5e/6bc728d70460d9ad3982d05c3765179e3584fee6fa523d57b242e6e4c50f/xsdata_pydantic-24.5.tar.gz", hash = "sha256:e3c8758133195657ece578537eda6c7ebd8419f77abf6b90fd4ced96e348129b", size = 18763 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/7b/785fe71aa1138d7380ab3926cbb9571896d56544901c320953ff8a586926/xsdata_pydantic-24.5-py3-none-any.whl", hash = "sha256:bb6da7d3445d655640096c65c1b11037153b19df533da89553f24247ef352cd0", size = 8891 },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
cli = [
|
||||
{ name = "xsdata", extra = ["cli"] },
|
||||
]
|
||||
lxml = [
|
||||
{ name = "lxml" },
|
||||
]
|
||||
soap = [
|
||||
{ name = "requests" },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user