diff --git a/edk2toollib/acpi/dmar_parser.py b/edk2toollib/acpi/dmar_parser.py index b5342d634..761464396 100644 --- a/edk2toollib/acpi/dmar_parser.py +++ b/edk2toollib/acpi/dmar_parser.py @@ -12,6 +12,7 @@ import struct import sys import xml.etree.ElementTree as ET +from typing import Optional DMARParserVersion = '1.01' @@ -26,7 +27,7 @@ class DMARTable(object): ANDDHeaderLength = 8 DeviceScopeHeaderLength = 6 - def __init__(self, data): + def __init__(self, data: bytes) -> None: """Inits the object.""" self.dmar_table = self.AcpiTableHeader(data) self.data = data[DMARTable.DMARHeaderLength:] @@ -58,7 +59,7 @@ def __init__(self, data): self.xml = self.toXml() - def toXml(self): + def toXml(self) -> ET.Element: """Converts the object to an xml representation.""" root = ET.Element('DMAR Table') root.append(self.dmar_table.toXml()) @@ -67,7 +68,7 @@ def toXml(self): return root - def __str__(self): + def __str__(self) -> str: """String representation of the object.""" retval = str(self.dmar_table) @@ -76,15 +77,15 @@ def __str__(self): return retval - def DMARBitEnabled(self): + def DMARBitEnabled(self) -> bool: """Returns the status of the DMAR Bit.""" return bool(self.dmar_table.DMARBit) - def ANDDCount(self): + def ANDDCount(self) -> int: """Returns the amount of ANDD in the DMAR table.""" return self.dmar_table.ANDDCount - def CheckRMRRCount(self, goldenxml=None): + def CheckRMRRCount(self, goldenxml: Optional[ET.Element]=None) -> bool: """Verifies all RMRR paths are in the golden XML.""" goldenignores = set() @@ -108,7 +109,7 @@ class AcpiTableHeader(object): STRUCT_FORMAT = '=4sIBB6s8sI4sIBB' size = struct.calcsize(STRUCT_FORMAT) - def __init__(self, header_byte_array): + def __init__(self, header_byte_array: bytes) -> None: """Inits the object.""" (self.Signature, self.Length, @@ -127,7 +128,7 @@ def __init__(self, header_byte_array): self.RMRRlist = list() self.SubStructs = list() - def __str__(self): + def __str__(self) -> str: """String representation of the object.""" return """\n ACPI Table Header ------------------------------------------------------------------ @@ -145,7 +146,7 @@ def __str__(self): self.OEMID, self.OEMTableID, self.OEMRevision, self.CreatorID, self.CreatorRevision, self.HostAddressWidth, self.Flags) - def toXml(self): + def toXml(self) -> ET.Element: """Converts the object to an xml representation.""" xml_repr = ET.Element('AcpiTableHeader') xml_repr.set('Signature', '%s' % self.Signature) @@ -165,12 +166,12 @@ class RemappingStructHeader(object): """Generic remapping struct header.""" STRUCT_FORMAT = '=HH' - def __init__(self, header_byte_array): + def __init__(self, header_byte_array: bytes) -> None: """Inits the object.""" (self.Type, self.Length) = struct.unpack_from(DMARTable.RemappingStructHeader.STRUCT_FORMAT, header_byte_array) - def __str__(self): + def __str__(self) -> str: """String representation of the object.""" return """\n Remapping Struct Header ------------------------------------------------------------------ @@ -182,7 +183,7 @@ class DRHDStruct(RemappingStructHeader): """Object representing the DRHD struct.""" STRUCT_FORMAT = '=HHBBHQ' # spell-checker: disable-line - def __init__(self, header_byte_array, length): + def __init__(self, header_byte_array: bytes, length: int) -> None: """Inits the object.""" (self.Type, self.Length, @@ -201,7 +202,7 @@ def __init__(self, header_byte_array, length): bytes_left -= device_scope.Length self.DeviceScope.append(device_scope) - def toXml(self): + def toXml(self) -> ET.Element: """Converts the object to an xml representation.""" xml_repr = ET.Element('DRHD') xml_repr.set('Type', '0x%X' % self.Type) @@ -222,7 +223,7 @@ def toXml(self): return xml_repr - def __str__(self): + def __str__(self) -> str: """String representation of the object.""" retstring = """\n DRHD ------------------------------------------------------------------ @@ -243,7 +244,7 @@ class RMRRStruct(RemappingStructHeader): """Object representing the RMRR struct.""" STRUCT_FORMAT = '=HHHHQQ' # spell-checker: disable-line - def __init__(self, header_byte_array, length): + def __init__(self, header_byte_array: bytes, length: int) -> None: """Inits the object.""" (self.Type, self.Length, @@ -263,7 +264,7 @@ def __init__(self, header_byte_array, length): bytes_left -= device_scope.Length self.DeviceScope.append(device_scope) - def getPath(self): + def getPath(self) -> str: """Generates and returns the path.""" retString = "" for index, item in enumerate(self.DeviceScope): @@ -272,7 +273,7 @@ def getPath(self): retString += ", " return retString - def toXml(self): + def toXml(self) -> ET.Element: """Converts the object to an xml representation.""" xml_repr = ET.Element('RMRR') xml_repr.set('Type', '0x%X' % self.Type) @@ -293,7 +294,7 @@ def toXml(self): return xml_repr - def __str__(self): + def __str__(self) -> str: """String representation of the object.""" retstring = """\n RMRR ------------------------------------------------------------------ @@ -315,7 +316,7 @@ class ATSRStruct(RemappingStructHeader): """Object representing the ANDD struct.""" STRUCT_FORMAT = '=HHBBH' # spell-checker: disable-line - def __init__(self, header_byte_array, length): + def __init__(self, header_byte_array: bytes, length: int) -> None: """Inits the object.""" (self.Type, self.Length, @@ -333,7 +334,7 @@ def __init__(self, header_byte_array, length): bytes_left -= device_scope.Length self.DeviceScope.append(device_scope) - def toXml(self): + def toXml(self) -> ET.Element: """Converts the object to an xml representation.""" xml_repr = ET.Element('ASTR') xml_repr.set('Type', '0x%X' % self.Type) @@ -353,7 +354,7 @@ def toXml(self): return xml_repr - def __str__(self): + def __str__(self) -> str: """String representation of the object.""" retstring = """\n ASTR ------------------------------------------------------------------ @@ -373,7 +374,7 @@ class RHSAStruct(RemappingStructHeader): """Object representing the RHSA struct.""" STRUCT_FORMAT = '=HHIQI' # spell-checker: disable-line - def __init__(self, header_byte_array, length): + def __init__(self, header_byte_array: bytes, length: int) -> None: """Inits the object.""" (self.Type, self.Length, @@ -381,7 +382,7 @@ def __init__(self, header_byte_array, length): self.RegisterBaseAddress, self.ProximityDomain) = struct.unpack_from(DMARTable.RHSAStruct.STRUCT_FORMAT, header_byte_array) - def toXml(self): + def toXml(self) -> ET.Element: """Converts the object to an xml representation.""" xml_repr = ET.Element('RHSA') xml_repr.set('Type', '0x%X' % self.Type) @@ -392,7 +393,7 @@ def toXml(self): return xml_repr - def __str__(self): + def __str__(self) -> str: """String representation of the object.""" return """\n RHSA ------------------------------------------------------------------ @@ -407,7 +408,7 @@ class ANDDStruct(RemappingStructHeader): """Object representing the ANDD struct.""" header_format = '=HH' - def __init__(self, header_byte_array, length): + def __init__(self, header_byte_array: bytes, length: int) -> None: """Inits the object.""" self.STRUCT_FORMAT = '=B' (self.Type, @@ -425,7 +426,7 @@ def __init__(self, header_byte_array, length): (self.ACPIDeviceNumber, self.ACPIObjectName) = struct.unpack_from(self.STRUCT_FORMAT, header_byte_array) - def toXml(self): + def toXml(self) -> ET.Element: """Converts the object to an xml representation.""" xml_repr = ET.Element('ANDD') xml_repr.set('Type', '0x%X' % self.Type) @@ -436,7 +437,7 @@ def toXml(self): return xml_repr - def __str__(self): + def __str__(self) -> str: """String representation of the object.""" return """\n ANDD ------------------------------------------------------------------ @@ -451,7 +452,7 @@ class DeviceScopeStruct(object): """Object representing a Device Scope.""" STRUCT_FORMAT = '=BBHBB' # spell-checker: disable-line - def __init__(self, header_byte_array): + def __init__(self, header_byte_array: bytes) -> None: """Inits a DeviceScopeStruct.""" (self.Type, self.Length, @@ -484,7 +485,7 @@ def __init__(self, header_byte_array): offset += 2 number_path_entries -= 1 - def getPath(self): + def getPath(self) -> str: """Returns the path.""" retstring = "%02d" % self.StartBusNumber + ":" @@ -495,7 +496,7 @@ def getPath(self): return retstring - def __str__(self): + def __str__(self) -> str: """String representation.""" retstring = """\n\t\t %s \t\t-------------------------------------------------- diff --git a/edk2toollib/acpi/ivrs_parser.py b/edk2toollib/acpi/ivrs_parser.py index da80842f3..671a0e280 100644 --- a/edk2toollib/acpi/ivrs_parser.py +++ b/edk2toollib/acpi/ivrs_parser.py @@ -11,6 +11,7 @@ import sys import xml.etree.ElementTree as ET from enum import IntEnum +from typing import Optional IVRSParserVersion = '1.00' # spell-checker:ignore IVMD, IOMMUEFR @@ -18,7 +19,7 @@ class IVRS_TABLE(object): """Object representing a IVRS Table.""" - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.acpi_header = None self.SubStructs = list() @@ -27,7 +28,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, data): + def Decode(self, data: bytes) -> None: """Loads data into the object from the header_byte_array.""" self.acpi_header = IVRS_TABLE.ACPI_TABLE_HEADER(data[:IVRS_TABLE.ACPI_TABLE_HEADER.struct_format_size]) @@ -70,7 +71,7 @@ def Decode(self, data): raise Exception("IVRS length does not add up. Parsed len: %d, reported len: %d" % (t_length, self.acpi_header.Length)) - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -86,7 +87,7 @@ def Encode(self): bytes_str += ivxd.Encode() return bytes_str - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" root = ET.Element('IVRSTable') root.append(self.acpi_header.ToXmlElementTree()) @@ -95,7 +96,7 @@ def ToXmlElementTree(self): return root - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" self.acpi_header.DumpInfo() @@ -103,11 +104,11 @@ def DumpInfo(self): sub.DumpInfo() @staticmethod - def validateChecksum8(data): + def validateChecksum8(data: bytes) -> bool: """Validate the Checksum.""" return sum(data) & 0xFF - def updateACPISum(self): + def updateACPISum(self) -> None: """Update the ACPI Checksum.""" temp_sum = 0 # Clear the checksum before calculating sum @@ -116,13 +117,13 @@ def updateACPISum(self): temp_sum = sum(temp_str) self.acpi_header.Checksum = (0x100 - (temp_sum & 0xFF)) & 0xFF - def addIVHDEntry(self, ivhd): + def addIVHDEntry(self, ivhd: 'IVRS_TABLE.IVHD_STRUCT') -> None: """Append entry to the list, update length and checksum.""" self.acpi_header.Length += len(ivhd.Encode()) self.SubStructs.append(ivhd) self.updateACPISum() - def addIVMDEntry(self, ivmd): + def addIVMDEntry(self, ivmd: 'IVRS_TABLE.IVMD_STRUCT') -> None: """Append entry to the list, update length and checksum.""" self.acpi_header.Length += len(ivmd.Encode()) # IVMD has to follow the corresponding IVHD, thus the list records all entries to maintain order @@ -130,7 +131,7 @@ def addIVMDEntry(self, ivmd): self.IVMD_list.append(ivmd) self.updateACPISum() - def IVRSBitEnabled(self): + def IVRSBitEnabled(self) -> bool: """Returns the IVRSBit Value.""" return bool(self.acpi_header.IVRSBit) @@ -139,7 +140,7 @@ class ACPI_TABLE_HEADER(object): struct_format = '=4sIBB6s8sI4sIIQ' struct_format_size = struct.calcsize(struct_format) - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Signature = None self.Length = 0 @@ -158,7 +159,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Signature, self.Length, @@ -176,7 +177,7 @@ def Decode(self, header_byte_array): if (self.IVinfo & 0x1E) == 0: sys.exit(-1) - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -195,7 +196,7 @@ def Encode(self): self.IVinfo, self.Reserved) - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print(' ACPI Table Header') print('------------------------------------------------------------------') @@ -210,7 +211,7 @@ def DumpInfo(self): print('Creator Revision : 0x{CreatorRevision:08X}'.format(CreatorRevision=self.CreatorRevision)) print('IVinfo : 0x{IVinfo:08X}'.format(IVinfo=self.IVinfo)) - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_repr = ET.Element('AcpiTableHeader') xml_repr.set('Signature', '%s' % self.Signature) @@ -230,7 +231,7 @@ class REMAPPING_STRUCT_HEADER(object): struct_format = '=B' struct_format_size = struct.calcsize(struct_format) - def __init__(self, header_byte_array): + def __init__(self, header_byte_array: bytes) -> None: """Inits an empty object.""" (self.Type, ) = struct.unpack(IVRS_TABLE.REMAPPING_STRUCT_HEADER.struct_format, header_byte_array[:IVRS_TABLE.REMAPPING_STRUCT_HEADER.struct_format_size]) @@ -249,7 +250,7 @@ class IVHD_TYPE(IntEnum): TYPE_11H = 0x11 TYPE_40H = 0x40 - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = None self.Flags = None @@ -268,7 +269,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.Flags, @@ -308,7 +309,7 @@ def Decode(self, header_byte_array): raise Exception("IVHD length does not add up. Parsed len: %d, reported len: %d" % (self.Length, t_Length)) - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -334,12 +335,12 @@ def Encode(self): return byte_str - def addDTEEntry(self, dte): + def addDTEEntry(self, dte: 'IVRS_TABLE.DEVICE_TABLE_ENTRY') -> None: """Append raw data, update length. checksum will be left untouched.""" self.Length += len(dte.Encode()) self.DeviceTableEntries.append(dte) - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_repr = ET.Element('IVHD') xml_repr.set('Type', '0x%X' % self.Type) @@ -362,7 +363,7 @@ def ToXmlElementTree(self): return xml_repr - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print("\t IVHD") print("\t----------------------------------------------------------------") @@ -391,7 +392,7 @@ class IVMD_TYPE(IntEnum): TYPE_21H = 0x21 # Specified peripheral TYPE_22H = 0x22 # Peripheral range - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = None self.Flags = None @@ -405,7 +406,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.Flags, @@ -419,7 +420,7 @@ def Decode(self, header_byte_array): if (self.Length != len(header_byte_array)): raise Exception("Bad IVMD entry size %d, expecting %d" % (self.Length, len(header_byte_array))) - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -435,7 +436,7 @@ def Encode(self): self.IVMDStartAddress, self.IVMDMemoryBlockLength) - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_repr = ET.Element('IVMD') @@ -453,7 +454,7 @@ def ToXmlElementTree(self): return xml_repr - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print("\t IVMD") print("\t----------------------------------------------------------------") @@ -491,7 +492,7 @@ class DTE_TYPE(IntEnum): ACPI = 240 @staticmethod - def Factory(data): + def Factory(data: bytes) -> Optional['IVRS_TABLE.DEVICE_TABLE_ENTRY_SPECIAL']: """Factory method to generate a specific table entry type.""" if (data is None): raise Exception("Invalid File stream") @@ -524,7 +525,7 @@ def Factory(data): class DEVICE_TABLE_ENTRY_RESERVED(object): """Object representing a Device Table Entry RESERVED.""" - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = 0 self.DeviceID = 0 @@ -534,7 +535,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.DeviceID, @@ -547,7 +548,7 @@ def Decode(self, header_byte_array): self.TypeString = "Reserved" self.Length = IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format_size - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -558,7 +559,7 @@ def Encode(self): self.DeviceID, self.DTESetting) - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_item = ET.Element(self.TypeString.replace(" ", "")) xml_item.set('DeviceID', '0x%X' % (self.DeviceID)) @@ -566,7 +567,7 @@ def ToXmlElementTree(self): xml_item.set('Type', '0x%X' % self.Type) return xml_item - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print('\t\t {TypeString:s}'.format(TypeString=self.TypeString)) print('\t\t--------------------------------------------------') @@ -576,7 +577,7 @@ def DumpInfo(self): class DEVICE_TABLE_ENTRY_ALL(object): """Object representing a Device Table Entry ALL.""" - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = 0 self.DeviceID = 0 @@ -586,7 +587,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.DeviceID, @@ -600,7 +601,7 @@ def Decode(self, header_byte_array): self.TypeString = "All" self.Length = IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format_size - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -611,7 +612,7 @@ def Encode(self): self.DeviceID, self.DTESetting) - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_item = ET.Element(self.TypeString.replace(" ", "")) xml_item.set('Type', '0x%X' % self.Type) @@ -619,7 +620,7 @@ def ToXmlElementTree(self): xml_item.set('DTESetting', '0x%X' % (self.DTESetting)) return xml_item - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print('\t\t {TypeString:s}'.format(TypeString=self.TypeString)) print('\t\t--------------------------------------------------') @@ -629,7 +630,7 @@ def DumpInfo(self): class DEVICE_TABLE_ENTRY_SELECT(object): """Object representing a Device Table Entry SELECT.""" - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = 0 self.DeviceID = 0 @@ -639,7 +640,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.DeviceID, @@ -653,7 +654,7 @@ def Decode(self, header_byte_array): self.TypeString = "Reserved" self.Length = IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format_size - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -664,7 +665,7 @@ def Encode(self): self.DeviceID, self.DTESetting) - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_item = ET.Element(self.TypeString.replace(" ", "")) xml_item.set('Type', '0x%X' % self.Type) @@ -672,7 +673,7 @@ def ToXmlElementTree(self): xml_item.set('DTESetting', '0x%X' % (self.DTESetting)) return xml_item - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print('\t\t {TypeString:s}'.format(TypeString=self.TypeString)) print('\t\t--------------------------------------------------') @@ -682,7 +683,7 @@ def DumpInfo(self): class DEVICE_TABLE_ENTRY_RANGE_START(object): """Object representing a Device Table Entry RANGE_START.""" - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = 0 self.DeviceID = 0 @@ -692,7 +693,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.DeviceID, @@ -714,7 +715,7 @@ def Decode(self, header_byte_array): sys.exit(-1) self.Length += IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format_size - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -730,7 +731,7 @@ def Encode(self): 0) return byte_str - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_item = ET.Element(self.TypeString.replace(" ", "")) xml_item.set('Type', '0x%X' % self.Type) @@ -739,7 +740,7 @@ def ToXmlElementTree(self): xml_item.set('DTESetting', '0x%X' % (self.DTESetting)) return xml_item - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print('\t\t {TypeString:s}'.format(TypeString=self.TypeString)) print('\t\t--------------------------------------------------') @@ -750,7 +751,7 @@ def DumpInfo(self): class DEVICE_TABLE_ENTRY_ALIAS_SELECT(object): """Object representing a Device Table Entry ALIAS_SELECT.""" - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = 0 self.DeviceID = 0 @@ -761,7 +762,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.DeviceID, @@ -780,7 +781,7 @@ def Decode(self, header_byte_array): struct.unpack(IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format, header_byte_array[IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format_size:self.Length]) - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -793,7 +794,7 @@ def Encode(self): byte_str += struct.pack(IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format, 0, self.SourceDeviceID, 0) return byte_str - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_item = ET.Element(self.TypeString.replace(" ", "")) xml_item.set('Type', '0x%X' % self.Type) @@ -802,7 +803,7 @@ def ToXmlElementTree(self): xml_item.set('SourceDeviceID', '0x%X' % (self.SourceDeviceID)) return xml_item - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print('\t\t {TypeString:s}'.format(TypeString=self.TypeString)) print('\t\t--------------------------------------------------') @@ -813,7 +814,7 @@ def DumpInfo(self): class DEVICE_TABLE_ENTRY_ALIAS_RANGE_START(object): """Object representing a Device Table Range Start.""" - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = 0 self.DeviceID = 0 @@ -825,7 +826,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.DeviceID, @@ -852,7 +853,7 @@ def Decode(self, header_byte_array): sys.exit(-1) self.Length += IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format_size - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -869,7 +870,7 @@ def Encode(self): 0) return byte_str - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_item = ET.Element(self.TypeString.replace(" ", "")) xml_item.set('Type', '0x%X' % self.Type) @@ -879,7 +880,7 @@ def ToXmlElementTree(self): xml_item.set('SourceDeviceID', '0x%X' % (self.SourceDeviceID)) return xml_item - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print('\t\t {TypeString:s}'.format(TypeString=self.TypeString)) print('\t\t--------------------------------------------------') @@ -891,7 +892,7 @@ def DumpInfo(self): class DEVICE_TABLE_ENTRY_EX_SELECT(object): """Object representing a Device Table Entry EX_SELECT.""" - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = 0 self.DeviceID = 0 @@ -902,7 +903,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.DeviceID, @@ -920,7 +921,7 @@ def Decode(self, header_byte_array): (self.ExtendedDTESetting,) = \ struct.unpack("=I", header_byte_array[IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format_size:self.Length]) - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -934,7 +935,7 @@ def Encode(self): byte_str += struct.pack("=I", self.ExtendedDTESetting) return byte_str - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_item = ET.Element(self.TypeString.replace(" ", "")) xml_item.set('Type', '0x%X' % self.Type) @@ -946,7 +947,7 @@ def ToXmlElementTree(self): xml_item.set('ExtendedDTESetting', 'ATS allowed') return xml_item - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print('\t\t {TypeString:s}'.format(TypeString=self.TypeString)) print('\t\t--------------------------------------------------') @@ -961,7 +962,7 @@ def DumpInfo(self): class DEVICE_TABLE_ENTRY_EX_RANGE_START(object): """Object representing a Device Table Entry EX_RANGE_START.""" - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = 0 self.DeviceID = 0 @@ -971,7 +972,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.DeviceID, @@ -997,7 +998,7 @@ def Decode(self, header_byte_array): sys.exit(-1) self.Length += IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format_size - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -1012,7 +1013,7 @@ def Encode(self): byte_str += struct.pack(IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format, 4, self.EndDeviceID, 0) return byte_str - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_item = ET.Element(self.TypeString.replace(" ", "")) xml_item.set('Type', '0x%X' % self.Type) @@ -1025,7 +1026,7 @@ def ToXmlElementTree(self): xml_item.set('ExtendedDTESetting', 'ATS allowed') return xml_item - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print('\t\t {TypeString:s}'.format(TypeString=self.TypeString)) print('\t\t--------------------------------------------------') @@ -1041,7 +1042,7 @@ def DumpInfo(self): class DEVICE_TABLE_ENTRY_SPECIAL(object): """Object representing a Device Table Entry Special.""" - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = 0 self.DeviceID = 0 @@ -1052,7 +1053,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.DeviceID, @@ -1071,7 +1072,7 @@ def Decode(self, header_byte_array): struct.unpack(IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format, header_byte_array[IVRS_TABLE.DEVICE_TABLE_ENTRY.struct_format_size:self.Length]) - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -1088,7 +1089,7 @@ def Encode(self): self.Variety) return byte_str - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_item = ET.Element(self.TypeString.replace(" ", "")) xml_item.set('Type', '0x%X' % self.Type) @@ -1105,7 +1106,7 @@ def ToXmlElementTree(self): xml_item.set('Variety', 'Reserved %X' % (self.Variety)) return xml_item - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print('\t\t {TypeString:s}'.format(TypeString=self.TypeString)) print('\t\t--------------------------------------------------') @@ -1125,7 +1126,7 @@ def DumpInfo(self): class DEVICE_TABLE_ENTRY_ACPI(object): """Object representing a Device Table Entry ACPI.""" - def __init__(self, data=None): + def __init__(self, data: Optional[bytes]=None) -> None: """Inits an empty object.""" self.Type = 0 self.DeviceID = 0 @@ -1136,7 +1137,7 @@ def __init__(self, data=None): if data is not None: self.Decode(data) - def Decode(self, header_byte_array): + def Decode(self, header_byte_array: bytes) -> None: """Loads data into the object from the header_byte_array.""" (self.Type, self.DeviceID, @@ -1163,7 +1164,7 @@ def Decode(self, header_byte_array): struct.unpack("=%ss" % self.UIDLength, header_byte_array[IVRS_TABLE.DEVICE_TABLE_ENTRY.dte_var_len:self.Length]) - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -1185,7 +1186,7 @@ def Encode(self): byte_str += struct.pack("=%ss" % self.UIDLength, self.UID) return byte_str - def ToXmlElementTree(self): + def ToXmlElementTree(self) -> ET.Element: """Transforms the object into an xml item and returns it.""" xml_item = ET.Element(self.TypeString.replace(" ", "")) xml_item.set('Type', '0x%X' % self.Type) @@ -1207,7 +1208,7 @@ def ToXmlElementTree(self): sys.exit(-1) return xml_item - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints internal information to the console.""" print('\t\t {TypeString:s}'.format(TypeString=self.TypeString)) print('\t\t--------------------------------------------------') diff --git a/edk2toollib/gitignore_parser.py b/edk2toollib/gitignore_parser.py index 27e677f00..30922d965 100644 --- a/edk2toollib/gitignore_parser.py +++ b/edk2toollib/gitignore_parser.py @@ -7,6 +7,7 @@ import re from os.path import abspath, dirname from pathlib import Path +from typing import Callable, Optional """Original file is from https://github.com/mherrmann/gitignore_parser/blob/master/gitignore_parser.py @@ -39,7 +40,7 @@ """ -def handle_negation(file_path, rules): +def handle_negation(file_path: str, rules: list) -> bool: """Allows `matched` value override if negation is true. Otherwise `matched` cannot be overwritten with an exception. @@ -55,7 +56,7 @@ def handle_negation(file_path, rules): return matched -def parse_gitignore_file(full_path, base_dir=None): +def parse_gitignore_file(full_path: str, base_dir: Optional[str]=None) -> Callable: """Parse a gitignore file.""" if base_dir is None: base_dir = dirname(full_path) @@ -64,7 +65,7 @@ def parse_gitignore_file(full_path, base_dir=None): return parse_gitignore_lines(lines, full_path, base_dir) -def parse_gitignore_lines(lines: list, full_path: str, base_dir: str): +def parse_gitignore_lines(lines: list, full_path: str, base_dir: str) -> Callable: """Parse a list of lines matching gitignore syntax.""" counter = 0 rules = [] @@ -78,7 +79,7 @@ def parse_gitignore_lines(lines: list, full_path: str, base_dir: str): return lambda file_path: handle_negation(file_path, rules) -def rule_from_pattern(pattern, base_path=None, source=None): +def rule_from_pattern(pattern: str, base_path: Optional[str]=None, source: Optional[str]=None) ->'IgnoreRule': """Generates an IgnoreRule object from a pattern. Take a .gitignore match pattern, such as "*.py[cod]" or "**/*.bak", @@ -164,15 +165,15 @@ def rule_from_pattern(pattern, base_path=None, source=None): class IgnoreRule(collections.namedtuple('IgnoreRule_', IGNORE_RULE_FIELDS)): """Class representing a single rule parsed from a .ignore file.""" - def __str__(self): + def __str__(self) -> str: """String representation (user friendly) of the rule.""" return self.pattern - def __repr__(self): + def __repr__(self) -> str: """String representation (developer friendly) of the rule.""" return ''.join(['IgnoreRule(\'', self.pattern, '\')']) - def match(self, abs_path): + def match(self, abs_path: str) -> bool: """Returns True or False if the path matches the rule.""" matched = False if self.base_path: @@ -188,7 +189,7 @@ def match(self, abs_path): # Frustratingly, python's fnmatch doesn't provide the FNM_PATHNAME # option that .gitignore's behavior depends on. -def fnmatch_pathname_to_regex(pattern): +def fnmatch_pathname_to_regex(pattern: str) -> str: """Implements fnmatch style-behavior, as though with FNM_PATHNAME flagged. WARNING: the path seperator will not match shell-style '*' and '.' wildcards. diff --git a/edk2toollib/log/ansi_handler.py b/edk2toollib/log/ansi_handler.py index 76f88fc78..25f3596f0 100644 --- a/edk2toollib/log/ansi_handler.py +++ b/edk2toollib/log/ansi_handler.py @@ -12,6 +12,7 @@ """ import logging import re +from typing import IO, Callable, Optional from edk2toollib.utility_functions import GetHostInfo @@ -25,11 +26,11 @@ # if we run into an exception (ie on unix or linux) windll = None - def SetConsoleTextAttribute(): + def SetConsoleTextAttribute() -> None: """Create blank lambda for when on unix / linux.""" None - def winapi_test(): + def winapi_test() -> None: """Create blank lambda for when on unix / linux.""" None @@ -51,7 +52,7 @@ class CONSOLE_SCREEN_BUFFER_INFO(Structure): ("dwMaximumWindowSize", COORD), ] - def __str__(self): + def __str__(self) -> str: """String representation of the console screen buffer.""" return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( self.dwSize.Y, self.dwSize.X, @@ -82,21 +83,21 @@ class Win32Console(object): STDERR = -12 @staticmethod - def _winapi_test(handle): + def _winapi_test(handle: Callable) -> bool: csbi = CONSOLE_SCREEN_BUFFER_INFO() success = Win32Console._GetConsoleScreenBufferInfo( handle, byref(csbi)) return bool(success) @staticmethod - def winapi_test(): + def winapi_test() -> Callable: """Returns the winapi_test.""" return any(Win32Console._winapi_test(h) for h in (Win32Console._GetStdHandle(Win32Console.STDOUT), Win32Console._GetStdHandle(Win32Console.STDERR))) @staticmethod - def GetConsoleScreenBufferInfo(stream_id=STDOUT): + def GetConsoleScreenBufferInfo(stream_id: int=STDOUT) -> CONSOLE_SCREEN_BUFFER_INFO: """Returns the console screen buffer info object.""" handle = Win32Console._GetStdHandle(stream_id) csbi = CONSOLE_SCREEN_BUFFER_INFO() @@ -105,7 +106,7 @@ def GetConsoleScreenBufferInfo(stream_id=STDOUT): return csbi @staticmethod - def SetConsoleTextAttribute(stream_id, attrs): + def SetConsoleTextAttribute(stream_id: int, attrs: int) -> bool: """Sets the console text attribute.""" handle = Win32Console._GetStdHandle(stream_id) return Win32Console._SetConsoleTextAttribute(handle, attrs) @@ -166,7 +167,7 @@ class AnsiColor(object): BG_LIGHTWHITE_EX = 107 @classmethod - def __contains__(self, item): + def __contains__(self: 'AnsiColor', item: str) -> bool: """Verifies we contain the color.""" if type(item) is str and hasattr(self, item): return True @@ -195,12 +196,12 @@ class ColoredFormatter(logging.Formatter): "SECTION": AnsiColor.CYAN } - def __init__(self, msg="", use_azure=False): + def __init__(self, msg: str="", use_azure: bool=False) -> None: """Inits the formatter.""" logging.Formatter.__init__(self, msg) self.use_azure = use_azure - def format(self, record): + def format(self, record: logging.LogRecord) -> str: """Formats the given record and returns it.""" levelname = record.levelname org_message = record.msg @@ -227,7 +228,7 @@ def format(self, record): return result -def get_ansi_string(color=AnsiColor.RESET): +def get_ansi_string(color: AnsiColor=AnsiColor.RESET) -> str: """Returns the string formatted ANSI command for the specific color.""" CSI = '\033[' colors = AnsiColor() @@ -241,7 +242,7 @@ class ColoredStreamHandler(logging.StreamHandler): # Control Sequence Introducer ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') - def __init__(self, stream=None, strip=None, convert=None): + def __init__(self, stream: Optional[IO]=None, strip: Optional[str]=None, convert: Optional[str]=None) -> None: """Inits a Colored Stream Handler.""" logging.StreamHandler.__init__(self, stream) self.on_windows = GetHostInfo().os == "Windows" @@ -276,7 +277,7 @@ def __init__(self, stream=None, strip=None, convert=None): self._default_back = self._back self._default_style = self._style - def handle(self, record): + def handle(self, record: logging.LogRecord) -> bool: """Conditionally emit the specified logging record. Emission depends on filters which may have been added to the handler. @@ -293,7 +294,7 @@ def handle(self, record): self.release() return rv - def get_win32_calls(self): + def get_win32_calls(self) -> dict: """Returns a dict for converting ANSI Colors to Windows Colors.""" if self.convert: return { @@ -334,7 +335,7 @@ def get_win32_calls(self): } return dict() - def set_foreground(self, fore=None, light=False, on_stderr=False): + def set_foreground(self, fore: Optional[int]=None, light: bool=False, on_stderr: bool=False) -> None: """Does the win32 call to set the foreground.""" if fore is None: fore = self._default_fore @@ -346,7 +347,7 @@ def set_foreground(self, fore=None, light=False, on_stderr=False): self._light &= ~WinColor.BRIGHT self.set_console(on_stderr=on_stderr) - def set_background(self, back=None, light=False, on_stderr=False): + def set_background(self, back: Optional[int]=None, light: bool=False, on_stderr: bool=False) -> None: """Does the win32 call to see the background.""" if back is None: back = self._default_back @@ -358,7 +359,7 @@ def set_background(self, back=None, light=False, on_stderr=False): self._light &= ~WinColor.BRIGHT_BACKGROUND self.set_console(on_stderr=on_stderr) - def set_console(self, attrs=None, on_stderr=False): + def set_console(self, attrs: Optional[int]=None, on_stderr: bool=False) -> None: """Does the win32 call to set the console text attribute.""" if attrs is None: attrs = self.get_attrs() @@ -367,24 +368,24 @@ def set_console(self, attrs=None, on_stderr=False): handle = Win32Console.STDERR Win32Console.SetConsoleTextAttribute(handle, attrs) - def get_attrs(self): + def get_attrs(self) -> int: """Gets the current settings for the style and colors selected.""" return self._fore + self._back * 16 + (self._style | self._light) - def set_attrs(self, value): + def set_attrs(self, value: int) -> None: """Sets the attributes for the style and colors selected.""" self._fore = value & 7 self._back = (value >> 4) & 7 self._style = value & (WinColor.BRIGHT | WinColor.BRIGHT_BACKGROUND) - def write(self, text): + def write(self, text: str) -> None: """Writes to stream, stripping ANSI if specified.""" if self.strip or self.convert: self.write_and_convert(text) else: self.write_plain_text(text) - def write_and_convert(self, text): + def write_and_convert(self, text: str) -> None: """Write the given text to the strip stripping and converting ANSI.""" cursor = 0 for match in self.ANSI_CSI_RE.finditer(text): @@ -396,7 +397,7 @@ def write_and_convert(self, text): self.write_plain_text(text, cursor, len(text)) - def write_plain_text(self, text, start=None, end=None): + def write_plain_text(self, text: str, start: Optional[int]=None, end: Optional[int]=None) -> None: """Writes plain text to our stream.""" if start is None: self.stream.write(text) @@ -404,13 +405,13 @@ def write_plain_text(self, text, start=None, end=None): self.stream.write(text[start:end]) self.flush() - def convert_ansi(self, paramstring, command): + def convert_ansi(self, paramstring: str, command: str) -> None: """Converts an ANSI command to a win32 command.""" if self.convert: params = self.extract_params(command, paramstring) self.call_win32(command, params) - def extract_params(self, command, paramstring): + def extract_params(self, command: str, paramstring: str) -> tuple: """Extracts the parameters in the ANSI command.""" params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) if len(params) == 0: @@ -418,7 +419,7 @@ def extract_params(self, command, paramstring): return params - def call_win32(self, command, params): + def call_win32(self, command: str, params: list) -> None: """Calls the win32 apis set_foreground and set_background.""" if command == 'm': for param in params: @@ -429,7 +430,7 @@ def call_win32(self, command, params): kwargs = dict() func(*args, **kwargs) - def emit(self, record): + def emit(self, record: logging.LogRecord) -> None: """Logging.handler method we are overriding to emit a record.""" try: if record is None: diff --git a/edk2toollib/log/file_handler.py b/edk2toollib/log/file_handler.py index cfb2b9e02..21204515d 100644 --- a/edk2toollib/log/file_handler.py +++ b/edk2toollib/log/file_handler.py @@ -11,11 +11,11 @@ class FileHandler(logging.FileHandler): """Object for handling basic logging output to files.""" - def __init__(self, filename, mode='w+'): + def __init__(self, filename: str, mode: str='w+') -> None: """Init a file handler for the specified file.""" logging.FileHandler.__init__(self, filename, mode=mode) - def handle(self, record): + def handle(self, record: logging.LogRecord) -> bool: """Conditionally emit the specified logging record. Emission depends on filters which may have been added to the handler. diff --git a/edk2toollib/log/junit_report_format.py b/edk2toollib/log/junit_report_format.py index 83a8a5f0d..67ba6efed 100644 --- a/edk2toollib/log/junit_report_format.py +++ b/edk2toollib/log/junit_report_format.py @@ -15,12 +15,13 @@ This does test report generation without being a test runner. """ import time +from typing import IO from xml.sax.saxutils import escape class JunitReportError(object): """Object representing a Test Error.""" - def __init__(self, type, msg): + def __init__(self, type: str, msg: str) -> None: """Init the type of error.""" self.Message = escape(msg.strip(), {'"': """}) self.Type = escape(type.strip(), {'"': """}) @@ -28,7 +29,7 @@ def __init__(self, type, msg): class JunitReportFailure(object): """Object representing a Test Failure.""" - def __init__(self, type, msg): + def __init__(self, type: str, msg: str) -> None: """Init the type of Failure.""" self.Message = escape(msg.strip(), {'"': """}) self.Type = escape(type.strip(), {'"': """}) @@ -42,7 +43,7 @@ class JunitReportTestCase(object): ERROR = 4 SUCCESS = 5 - def __init__(self, Name, ClassName): + def __init__(self, Name: str, ClassName: str) -> None: """Init a Test case with it's name and class name.""" self.Name = escape(Name.strip(), {'"': """}) self.ClassName = escape(ClassName.strip(), {'"': """}) @@ -56,7 +57,7 @@ def __init__(self, Name, ClassName): self.StdOut = "" self._StartTime = time.time() - def SetFailed(self, Msg, Type): + def SetFailed(self, Msg: str, Type: str) -> None: """Sets internal state if the test failed.""" if (self.Status != JunitReportTestCase.NEW): raise Exception("Can't Set to failed. State must be in NEW") @@ -64,7 +65,7 @@ def SetFailed(self, Msg, Type): self.Status = JunitReportTestCase.FAILED self.FailureMsg = JunitReportFailure(Type, Msg) - def SetError(self, Msg, Type): + def SetError(self, Msg: str, Type: str) -> None: """Set internal state if the test had an error.""" if (self.Status != JunitReportTestCase.NEW): raise Exception("Can't Set to error. State must be in NEW") @@ -72,29 +73,29 @@ def SetError(self, Msg, Type): self.Status = JunitReportTestCase.ERROR self.ErrorMsg = JunitReportError(Type, Msg) - def SetSuccess(self): + def SetSuccess(self) -> None: """Set internal state if the test passed.""" if (self.Status != JunitReportTestCase.NEW): raise Exception("Can't Set to success. State must be in NEW") self.Status = JunitReportTestCase.SUCCESS self.Time = time.time() - self._StartTime - def SetSkipped(self): + def SetSkipped(self) -> None: """Set internal state if the test was skipped.""" if (self.Status != JunitReportTestCase.NEW): raise Exception("Can't Set to skipped. State must be in NEW") self.Status = JunitReportTestCase.SKIPPED self.Time = time.time() - self._StartTime - def LogStdOut(self, msg): + def LogStdOut(self, msg: str) -> None: """Log to the standard out.""" self.StdOut += escape(msg.strip()) + "\n " - def LogStdError(self, msg): + def LogStdError(self, msg: str) -> None: """Log to the standard err.""" self.StdErr += escape(msg.strip()) + "\n " - def Output(self, outstream): + def Output(self, outstream: IO) -> None: """Write the test result to the outstream.""" outstream.write(''.format(self.ClassName, self.Name, self.Time)) if self.Status == JunitReportTestCase.SKIPPED: @@ -120,14 +121,14 @@ class JunitReportTestSuite(object): Create new suites by using the JunitTestReport Object """ - def __init__(self, Name, Package, Id): + def __init__(self, Name: str, Package: str, Id: id) -> None: """Initialize a new test suite.""" self.Name = escape(Name.strip(), {'"': """}) self.Package = escape(Package.strip(), {'"': """}) self.TestId = Id self.TestCases = [] - def create_new_testcase(self, name, classname): + def create_new_testcase(self, name: str, classname: str) -> JunitReportTestCase: """Create a new test case. Returns: @@ -138,7 +139,7 @@ def create_new_testcase(self, name, classname): tc._TestSuite = self return tc - def Output(self, outstream): + def Output(self, outstream: IO) -> None: """Output the test results to the stream.""" Errors = 0 Failures = 0 @@ -168,11 +169,11 @@ class JunitTestReport(object): Top level object test reporting. """ - def __init__(self): + def __init__(self) -> None: """Init an empty test report.""" self.TestSuites = [] - def create_new_testsuite(self, name, package): + def create_new_testsuite(self, name: str, package: str) -> JunitReportTestSuite: """Create a new test suite. Returns: @@ -183,7 +184,7 @@ def create_new_testsuite(self, name, package): self.TestSuites.append(ts) return ts - def Output(self, filepath): + def Output(self, filepath: str) -> None: """Write report to file.""" f = open(filepath, "w") f.write('') diff --git a/edk2toollib/log/string_handler.py b/edk2toollib/log/string_handler.py index 8191d1eda..af211e07e 100644 --- a/edk2toollib/log/string_handler.py +++ b/edk2toollib/log/string_handler.py @@ -8,18 +8,19 @@ """Module for handling basic logging by streaming into StringIO.""" import io import logging +from logging import LogRecord class StringStreamHandler(logging.StreamHandler): """Class for logging via StringIO.""" terminator = '\n' - def __init__(self): + def __init__(self) -> None: """Init a StringStreamHandler.""" logging.Handler.__init__(self) self.stream = io.StringIO() - def handle(self, record): + def handle(self, record: LogRecord) -> bool: """Conditionally emit the specified logging record. Emission depends on filters which may have been added to the handler. @@ -36,18 +37,18 @@ def handle(self, record): self.release() return rv - def readlines(self, hint=-1): + def readlines(self, hint: int=-1) -> list[str]: """Reads lines from stream and returns them.""" return self.stream.readlines(hint) - def seek_start(self): + def seek_start(self) -> None: """Seeks to a specific point in the stream.""" self.stream.seek(0, 0) - def seek_end(self): + def seek_end(self) -> None: """Seeks to the end of the stream.""" self.stream.seek(0, io.SEEK_END) - def seek(self, offset, whence): + def seek(self, offset: int, whence: int) -> int: """Seek to a specific point in the stream.""" return self.stream.seek(offset, whence) diff --git a/edk2toollib/tpm/tpm2_defs.py b/edk2toollib/tpm/tpm2_defs.py index fff8227a0..545c484e2 100644 --- a/edk2toollib/tpm/tpm2_defs.py +++ b/edk2toollib/tpm/tpm2_defs.py @@ -7,6 +7,8 @@ # SPDX-License-Identifier: BSD-2-Clause-Patent ## """This module contains utility classes to help interpret definitions from the Tpm20.h header file.""" +from typing import Optional + ## # INCLUDES CONTENTS FROM TianoCore Tpm20.h HEADER FILE!! # @@ -241,7 +243,7 @@ class CommandCode(object): Allows alternativing between command codes and command strings. """ @staticmethod - def get_code(cc_string): + def get_code(cc_string: str) -> Optional[int]: """Returns associated command code. Args: @@ -361,7 +363,7 @@ def get_code(cc_string): }.get(cc_string, None) @staticmethod - def get_string(cc_code): + def get_string(cc_code: int) -> Optional[str]: """Returns associated command string. Args: @@ -487,11 +489,11 @@ class ResponseCode(object): Allows alternativing between response codes and response strings. """ @staticmethod - def get_simple_string(rc_code): + def get_simple_string(rc_code: int) -> Optional[str]: """Returns associated response string. Args: - rc_code (int): response code + rc_code: response code Returns: (str): Associated response string (None): rc_code not found @@ -534,7 +536,7 @@ def get_simple_string(rc_code): }.get(rc_code, None) @staticmethod - def parse_code(rc_code): + def parse_code(rc_code: int) -> tuple: """Returns a Tuple representing the parsed response code.""" generic_errors = { 0x000: 'TPM_RC_INITIALIZE', diff --git a/edk2toollib/tpm/tpm2_policy_calc.py b/edk2toollib/tpm/tpm2_policy_calc.py index d3390f31c..e5b4df38b 100644 --- a/edk2toollib/tpm/tpm2_policy_calc.py +++ b/edk2toollib/tpm/tpm2_policy_calc.py @@ -9,6 +9,7 @@ import hashlib import struct +from typing import Optional, Union import edk2toollib.tpm.tpm2_defs as t2d @@ -29,7 +30,7 @@ class PolicyHasher(object): """An object used to hash TPM 2.0 policies with a specified hash.""" - def __init__(self, hash_type): + def __init__(self, hash_type: str) -> None: """Init the hasher with the specified hash. Args: @@ -47,11 +48,11 @@ def __init__(self, hash_type): 'sha384': 48 }[hash_type] - def get_size(self): + def get_size(self) -> int: """Returns the size of the hash.""" return self.hash_size - def hash(self, data): + def hash(self, data: str) -> bytes: """Hashes the data using the specified type.""" hash_obj = None if self.hash_type == 'sha256': @@ -77,7 +78,7 @@ def generate_digest(self, digest_type): # noqa class PolicyTreeOr(object): """Object representing an OR junction in a policy tree.""" - def __init__(self, components): + def __init__(self, components: Union['PolicyTreeAnd', 'PolicyTreeOr', 'PolicyTreeSolo']) -> None: """Inits the policy tree junction with a list of connected components. Args: @@ -93,11 +94,11 @@ def __init__(self, components): self.components = components - def get_type(self): + def get_type(self) -> str: """Returns the type of junction.""" return 'or' - def validate(self): + def validate(self) -> bool: """Validates all components have the correct attributes.""" result = True @@ -112,21 +113,21 @@ def validate(self): return result - def get_policy_buffer(self, hash_obj): + def get_policy_buffer(self, hash_obj: Union['PolicyTreeAnd', 'PolicyTreeOr', 'PolicyTreeSolo']) -> bytes: """Creates and returns a buffer representing the policy.""" concat_policy_buffer = b'\x00' * hash_obj.get_size() concat_policy_buffer += struct.pack(">L", t2d.TPM_CC_PolicyOR) concat_policy_buffer += b''.join([component.get_policy(hash_obj) for component in self.components]) return concat_policy_buffer - def get_policy(self, hash_obj): + def get_policy(self, hash_obj: Union['PolicyTreeAnd', 'PolicyTreeOr', 'PolicyTreeSolo']) -> int: """Returns a hashed policy buffer.""" return hash_obj.hash(self.get_policy_buffer(hash_obj)) class PolicyTreeAnd(object): """Object representing an AND junction in a policy tree.""" - def __init__(self, components): + def __init__(self, components: list[Union['PolicyTreeAnd', 'PolicyTreeOr', 'PolicyTreeSolo']]) -> None: """Inits the policy tree junction with a list of connected components.""" # ANDs must only be composed of primitives. For simplicity, I guess. # Honestly, this has spiralled out of control, but something is better than nothing. @@ -136,15 +137,16 @@ def __init__(self, components): self.components = components - def get_type(self): + def get_type(self) -> str: """Returns the type of junction.""" return 'and' - def validate(self): # noqa + def validate(self) -> bool: + """Validate.""" # Not sure why don't validate here instead of in the init? return True - def get_policy(self, hash_obj): + def get_policy(self, hash_obj: Union['PolicyTreeAnd', 'PolicyTreeOr', 'PolicyTreeSolo']) -> bytes: """Returns a hashed policy buffer.""" current_digest = b'\x00' * hash_obj.get_size() for component in self.components: @@ -155,26 +157,27 @@ def get_policy(self, hash_obj): class PolicyTreeSolo(object): """This object should only be used to put a single policy claim under an OR.""" - def __init__(self, policy_obj): + def __init__(self, policy_obj: Union['PolicyTreeAnd', 'PolicyTreeOr', 'PolicyTreeSolo']) -> None: """Inits the policy tree junction.""" if not hasattr(policy_obj, 'get_buffer_for_digest'): raise ValueError("Supplied policy object is missing required functionality!") self.policy_obj = policy_obj - def get_type(self): + def get_type(self) -> str: """Returns the type of junction.""" return 'solo' - def validate(self): # noqa + def validate(self) -> bool: + """Validate.""" # Not sure why don't validate here instead of in the init? return True - def get_policy_buffer(self, hash_obj): + def get_policy_buffer(self, hash_obj: Union['PolicyTreeAnd', 'PolicyTreeOr', 'PolicyTreeSolo']) -> bytes: """Creates and returns a buffer representing the policy.""" return (b'\x00' * hash_obj.get_size()) + self.policy_obj.get_buffer_for_digest() - def get_policy(self, hash_obj): + def get_policy(self, hash_obj: Union['PolicyTreeAnd', 'PolicyTreeOr']) -> int: """Returns a hashed policy buffer.""" return hash_obj.hash(self.get_policy_buffer(hash_obj)) @@ -190,7 +193,7 @@ def get_policy(self, hash_obj): class PolicyLocality(object): """Policy Primitive to describe a single assertion to create complex assertions.""" - def __init__(self, localities): + def __init__(self, localities: list[int]) -> None: """Init with the requested localities.""" # Update the bitfield with the requested localities. if localities is not None: @@ -198,11 +201,11 @@ def __init__(self, localities): else: self.bitfield = 0b00000000 - def get_bitfield(self): + def get_bitfield(self) -> int: """Return the bitfield attribute.""" return self.bitfield - def calc_bitfield_from_list(self, localities): + def calc_bitfield_from_list(self, localities: list[int]) -> int: """Calculate the bitfield from a list of localities.""" bitfield = 0b00000000 @@ -230,7 +233,7 @@ def calc_bitfield_from_list(self, localities): return bitfield - def get_buffer_for_digest(self): + def get_buffer_for_digest(self) -> str: r"""Serializes the primitive. Returns: @@ -242,7 +245,7 @@ def get_buffer_for_digest(self): class PolicyCommandCode(object): """Policy Primitive to describe a Command code.""" - def __init__(self, command_code_string=None): + def __init__(self, command_code_string: Optional[str]=None) -> None: """Init with the requested command code string.""" # Check to make sure that a command_code can be found. str_command_code_string = str(command_code_string) @@ -251,11 +254,11 @@ def __init__(self, command_code_string=None): raise ValueError("Command code '%s' unknown!" % str_command_code_string) self.command_code_string = str_command_code_string - def get_code(self): + def get_code(self) -> str: """Returns the command_code_string attribute.""" return self.command_code_string - def get_buffer_for_digest(self): + def get_buffer_for_digest(self) -> str: r"""Serializes the primitive. Returns: diff --git a/edk2toollib/tpm/tpm2_simulator.py b/edk2toollib/tpm/tpm2_simulator.py index 80dc224a2..806a3fdb6 100644 --- a/edk2toollib/tpm/tpm2_simulator.py +++ b/edk2toollib/tpm/tpm2_simulator.py @@ -42,7 +42,7 @@ class TpmSimulator(object): """An object for interacting with the Tpm Simulator.""" - def __init__(self, host='localhost', port=2321): + def __init__(self, host: str='localhost', port: int=2321) -> None: """Initialize the simulator on the requested host (ip) and port.""" super(TpmSimulator, self).__init__() @@ -61,18 +61,18 @@ def __init__(self, host='localhost', port=2321): # Enable the NV space. self.platSock.send(struct.pack(">L", PLAT_COMMANDS['TPM_SIGNAL_NV_ON'])) - def send_raw_data(self, data): + def send_raw_data(self, data: str) -> None: """Send raw data to the TPM simulator.""" print("RAW -->: " + str(data).encode('hex')) self.tpmSock.send(data) - def read_raw_data(self, count): + def read_raw_data(self, count: int) -> bytes: """Read raw data from the TPM simulator.""" data = self.tpmSock.recv(count) print("RAW <--: " + str(data).encode('hex')) return data - def send_data(self, data): + def send_data(self, data: str) -> bytes: """Send data to the TPM simulator.""" # Send the "I'm about to send data" command. self.send_raw_data(struct.pack(">L", PLAT_COMMANDS['TPM_SEND_COMMAND'])) @@ -94,7 +94,7 @@ def send_data(self, data): return self.read_raw_data(result_size) - def startup(self, type): + def startup(self, type: str) -> bytes: """Initialize the connection to the TPM simulator.""" stream = t2s.Tpm2CommandStream(t2d.TPM_ST_NO_SESSIONS, 0x00, t2d.TPM_CC_Startup) stream.add_element(t2s.Tpm2StreamPrimitive(t2d.TPM_SU_Size, type)) diff --git a/edk2toollib/tpm/tpm2_stream.py b/edk2toollib/tpm/tpm2_stream.py index 134e105e9..34bc52fbb 100644 --- a/edk2toollib/tpm/tpm2_stream.py +++ b/edk2toollib/tpm/tpm2_stream.py @@ -12,11 +12,11 @@ class Tpm2StreamElement(object): """Tpm2 Stream Element.""" - def __init__(self): + def __init__(self) -> None: """Init an empty Tpm2StreamElement.""" self.pack_string = "" - def get_size(self): + def get_size(self) -> int: """The size of this structure when marshalled.""" return struct.calcsize(self.pack_string) @@ -25,15 +25,15 @@ class Tpm2StreamPrimitive(Tpm2StreamElement): """Tpm2 Stream Primitive. Attributes: - size (int): size of the primitive. 1, 2, 4, or 8 bytes - value (): Value of primitive + size: size of the primitive. 1, 2, 4, or 8 bytes + value: Value of primitive """ - def __init__(self, size, value): + def __init__(self, size: int, value: str) -> None: """Init a primitive value. Args: - size (int): 1, 2, 4, or 8 bytes - value (): Value to stream. + size: 1, 2, 4, or 8 bytes + value: Value to stream. """ super(Tpm2StreamPrimitive, self).__init__() @@ -48,7 +48,7 @@ def __init__(self, size, value): }[size] self.value = value - def marshal(self): + def marshal(self) -> bytes: r"""Serializes the Tpm2 primitive. Returns: @@ -61,11 +61,11 @@ class TPM2_COMMAND_HEADER(Tpm2StreamElement): """Tpm2 Command header. Attributes: - tag (): tag - code (): code - size(): size + tag + code + size """ - def __init__(self, tag, size, code): + def __init__(self, tag: str, size: str, code: str) -> None: """Init a Tpm2 command.""" super(TPM2_COMMAND_HEADER, self).__init__() self.tag = tag @@ -73,11 +73,11 @@ def __init__(self, tag, size, code): self.size = size self.pack_string = ">HLL" - def update_size(self, size): + def update_size(self, size: int) -> None: """Update size of the whole command.""" self.size = size - def marshal(self): + def marshal(self) -> str: r"""Serializes the Tpm2 command header. Returns: @@ -88,20 +88,20 @@ def marshal(self): class TPM2B(Tpm2StreamElement): """Tpm2 B.""" - def __init__(self, data): + def __init__(self, data: str) -> None: """Inits the object.""" super(TPM2B, self).__init__() self.data = data self.size = len(data) self.pack_string = ">H%ds" % self.size - def update_data(self, data): + def update_data(self, data: str) -> None: """Updates the data attribute.""" self.data = data self.size = len(data) self.pack_string = ">H%ds" % self.size - def marshal(self): + def marshal(self) -> str: r"""Serializes the Tpm2B object. Returns: @@ -112,7 +112,7 @@ def marshal(self): class Tpm2CommandStream(object): """Tpm2 Command Stream.""" - def __init__(self, tag, size, code): + def __init__(self, tag: str, size: int, code: str) -> None: """Inits a Tpm2 Command stream object.""" super(Tpm2CommandStream, self).__init__() self.header = TPM2_COMMAND_HEADER(tag, size, code) @@ -120,17 +120,17 @@ def __init__(self, tag, size, code): self.header.update_size(self.stream_size) self.stream_elements = [] - def get_size(self): + def get_size(self) -> int: """Returns the stream size.""" return self.stream_size - def add_element(self, element): + def add_element(self, element: 'Tpm2StreamElement') -> None: """Adds an element to the stream list.""" self.stream_elements.append(element) self.stream_size += element.get_size() self.header.update_size(self.stream_size) - def get_stream(self): + def get_stream(self) -> str: r"""Serializes the Header + elements. Returns: diff --git a/edk2toollib/uefi/authenticated_variables_structure_support.py b/edk2toollib/uefi/authenticated_variables_structure_support.py index a4ec28e81..7d2fbcaa2 100644 --- a/edk2toollib/uefi/authenticated_variables_structure_support.py +++ b/edk2toollib/uefi/authenticated_variables_structure_support.py @@ -19,7 +19,7 @@ import uuid from abc import ABC, abstractmethod from operator import attrgetter -from typing import BinaryIO, List +from typing import IO, Any, BinaryIO, List, Optional, Tuple, Union from warnings import warn from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey @@ -44,7 +44,7 @@ class CommonUefiStructure(ABC): """This structure contains the methods common across all UEFI Structures.""" - def __init__(self): + def __init__(self) -> None: """Inits the object.""" @abstractmethod @@ -73,7 +73,7 @@ def encode(self) -> bytes: """ @abstractmethod - def print(self, outfs=sys.stdout) -> None: + def print(self, outfs: IO=sys.stdout) -> None: """Prints the object to the console.""" @@ -84,18 +84,18 @@ class EfiSignatureDataEfiCertX509(CommonUefiStructure): def __init__(self, decodefs: BinaryIO = None, - decodesize=0, + decodesize: int=0, createfs: BinaryIO = None, cert: bytes = None, - sigowner: uuid.UUID = None): + sigowner: uuid.UUID = None) -> None: """Inits the object. Args: - decodefs (BinaryIO): a filestream object of binary content that is the structure encoded - decodesize (int):number of bytes to decode as the EFI_SIGNATURE_DATA object (guid + x509 data) - createfs (BinaryIO): a filestream object that is the DER encoded x509 cert - cert (bytes): the x509 certificate to initialize this object - sigowner (uuid.UUID): the uuid object of the signature owner guid + decodefs: a filestream object of binary content that is the structure encoded + decodesize:number of bytes to decode as the EFI_SIGNATURE_DATA object (guid + x509 data) + createfs: a filestream object that is the DER encoded x509 cert + cert: the x509 certificate to initialize this object + sigowner: the uuid object of the signature owner guid Raises: (ValueError): Invalid FileStream size @@ -147,16 +147,16 @@ def SignatureData(self, value: bytes) -> None: warn("SignatureData is deprecated. Use signature_data instead.", DeprecationWarning, 2) self.signature_data = value - def __lt__(self, other): + def __lt__(self, other: 'EfiSignatureDataEfiCertX509') -> bool: """Less-than comparison for sorting. Looks at signature_data only, not signature_owner.""" return self.signature_data < other.signature_data - def PopulateFromFileStream(self, fs: BinaryIO, decodesize): + def PopulateFromFileStream(self, fs: BinaryIO, decodesize: int) -> None: """Decodes an object from a filestream. Args: - fs (BinaryIO): filestream - decodesize (int): amount to decode. + fs: filestream + decodesize: amount to decode. Raises: (ValueError): Invalid filestream @@ -165,12 +165,12 @@ def PopulateFromFileStream(self, fs: BinaryIO, decodesize): warn("PopulateFromFileStream() is deprecated. Use decode() instead.", DeprecationWarning, 2) self.decode(fs, decodesize=decodesize) - def decode(self, fs: BinaryIO, decodesize): + def decode(self, fs: BinaryIO, decodesize: int) -> None: """Decodes an object from a filestream. Args: - fs (BinaryIO): filestream - decodesize (int): amount to decode. + fs: filestream + decodesize: amount to decode. Raises: (ValueError): Invalid filestream @@ -201,12 +201,12 @@ def decode(self, fs: BinaryIO, decodesize): EfiSignatureDataEfiCertX509.STATIC_STRUCT_SIZE self.signature_data = fs.read(self.signature_data_size) - def Print(self, compact: bool = False, outfs=sys.stdout): + def Print(self, compact: bool = False, outfs: IO=sys.stdout) -> None: """Prints to the console.""" warn("Print() is deprecated. Use print() instead.", DeprecationWarning, 2) self.print(compact=compact, outfs=outfs) - def print(self, compact: bool = False, outfs=sys.stdout): + def print(self, compact: bool = False, outfs: IO=sys.stdout) -> None: """Prints to the console.""" if not compact: outfs.write("EfiSignatureData - EfiSignatureDataEfiCertX509\n") @@ -232,11 +232,11 @@ def print(self, compact: bool = False, outfs=sys.stdout): outfs.write(s) outfs.write("\n") - def Write(self, fs): + def Write(self, fs: BinaryIO) -> None: """Write the object to the filestream. Args: - fs (BinaryIO): filestream + fs: filestream Raises: (ValueError): Invalid filestream @@ -245,11 +245,11 @@ def Write(self, fs): warn("Write() is deprecated. Use write() instead.", DeprecationWarning, 2) self.write(fs) - def write(self, fs): + def write(self, fs: BinaryIO) -> None: """Write the object to the filestream. Args: - fs (BinaryIO): filestream + fs: filestream Raises: (ValueError): Invalid filestream @@ -271,12 +271,12 @@ def encode(self) -> bytes: """Return bytes array produced by Write().""" return self.signature_owner.bytes_le + self.signature_data - def GetTotalSize(self): + def GetTotalSize(self) -> int: """Returns the total size of the object.""" warn("GetTotalSize() is deprecated. Use get_total_size() instead.", DeprecationWarning, 2) return self.get_total_size() - def get_total_size(self): + def get_total_size(self) -> int: """Returns the total size of the object.""" return EfiSignatureDataEfiCertX509.STATIC_STRUCT_SIZE + self.signature_data_size @@ -290,7 +290,7 @@ def __init__(self, decodefs: BinaryIO = None, createfs: BinaryIO = None, digest: bytes = None, - sigowner: uuid = None): + sigowner: uuid = None) -> None: """Inits the object. Args: @@ -343,12 +343,12 @@ def SignatureData(self, value: bytes) -> None: warn("SignatureData is deprecated. Use signature_data instead.", DeprecationWarning, 2) self.signature_data = value - def decode(self, fs, decodesize: int = -1): + def decode(self, fs: BinaryIO, decodesize: int = -1) -> None: """Decodes an object from a filestream. Args: - fs (BinaryIO): filestream - decodesize (int): size of the object to decode (UNUSED) + fs: filestream + decodesize: size of the object to decode (UNUSED) Raises: (Exception): Invalid filestream @@ -369,7 +369,7 @@ def decode(self, fs, decodesize: int = -1): self.signature_data = fs.read(hashlib.sha256().digest_size) - def PopulateFromFileStream(self, fs): + def PopulateFromFileStream(self, fs: BinaryIO) -> None: """Loads an object from a filestream. Args: @@ -381,7 +381,7 @@ def PopulateFromFileStream(self, fs): warn("PopulateFromFileStream() is deprecated. Use decode() instead.", DeprecationWarning, 2) self.decode(fs) - def print(self, compact: bool = False, outfs=sys.stdout): + def print(self, compact: bool = False, outfs: IO=sys.stdout) -> None: """Prints to the console.""" if not compact: outfs.write("EfiSignatureData - EfiSignatureDataEfiCertSha256\n") @@ -406,16 +406,16 @@ def print(self, compact: bool = False, outfs=sys.stdout): outfs.write(s) outfs.write("\n") - def Print(self, compact: bool = False, outfs=sys.stdout): + def Print(self, compact: bool = False, outfs: IO=sys.stdout) -> None: """Prints to the console.""" warn("Print() is deprecated. Use print() instead.", DeprecationWarning, 2) self.print(compact, outfs) - def write(self, fs): + def write(self, fs: BinaryIO) -> None: """Write the object to the filestream. Args: - fs (BinaryIO): filestream + fs: filestream Raises: (Exception): Invalid filestream @@ -429,11 +429,11 @@ def write(self, fs): fs.write(self.signature_owner.bytes_le) fs.write(self.signature_data) - def Write(self, fs): + def Write(self, fs: BinaryIO) -> None: """Write the object to the filestream. Args: - fs (BinaryIO): filestream + fs: filestream Raises: (Exception): Invalid filestream @@ -453,11 +453,11 @@ def GetBytes(self) -> bytes: warn("GetBytes() is deprecated. Use encode() instead.", DeprecationWarning, 2) return self.encode() - def get_total_size(self): + def get_total_size(self) -> int: """Returns the total size of the object.""" return EfiSignatureDataEfiCertSha256.STATIC_STRUCT_SIZE - def GetTotalSize(self): + def GetTotalSize(self) -> int: """Returns the total size of the object.""" warn("GetTotalSize() is deprecated. Use get_total_size() instead.", DeprecationWarning, 2) return self.get_total_size() @@ -486,15 +486,19 @@ class EfiSignatureDataFactory(object): # EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID("0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7") @staticmethod - def factory(fs: BinaryIO, type, size): + def factory( + fs: BinaryIO, + type: uuid.UUID, + size: int + )-> Union[EfiSignatureDataEfiCertSha256, EfiSignatureDataEfiCertX509]: """This method is a factory for creating the correct Efi Signature Data object from the filestream. Uses a Filestream of an existing auth payload. Args: - fs (BinaryIO): filestream to read - type (uuid.UUID): Guid of the type - size (int): decodesize for x509, struct size for Sha256 + fs: filestream to read + type: Guid of the type + size: decodesize for x509, struct size for Sha256 """ if (fs is None): raise Exception("Invalid File stream") @@ -512,39 +516,51 @@ def factory(fs: BinaryIO, type, size): raise Exception("Not Supported") @staticmethod - def Factory(fs: BinaryIO, type, size): + def Factory( + fs: BinaryIO, + type: uuid.UUID, + size: int + ) -> Union[EfiSignatureDataEfiCertSha256, EfiSignatureDataEfiCertX509]: """This method is a factory for creating the correct Efi Signature Data object from the filestream. Uses a Filestream of an existing auth payload. Args: - fs (BinaryIO): filestream to read - type (uuid.UUID): Guid of the type - size (int): decodesize for x509, struct size for Sha256 + fs: filestream to read + type: Guid of the type + size: decodesize for x509, struct size for Sha256 """ warn("Factory() is deprecated, use factory() instead", DeprecationWarning) return EfiSignatureDataFactory.factory(fs, type, size) @staticmethod - def Create(type, ContentFileStream, sigowner): + def Create( + type: uuid.UUID, + ContentFileStream: BinaryIO, + sigowner: uuid.UUID + ) -> Union[EfiSignatureDataEfiCertSha256, EfiSignatureDataEfiCertX509]: """Create a new EFI Sginature Data Object. Args: - type (uuid.UUID): Guid of the type - ContentFileStream (BinaryIO): filestream to read - sigowner (uuid.UUID): the uuid object of the signature owner guid + type: Guid of the type + ContentFileStream: filestream to read + sigowner: the uuid object of the signature owner guid """ warn("Create() is deprecated, use create() instead", DeprecationWarning, 2) return EfiSignatureDataFactory.create(type, ContentFileStream, sigowner) @staticmethod - def create(type, ContentFileStream, sigowner): + def create( + type: uuid.UUID, + ContentFileStream: BinaryIO, + sigowner: uuid.UUID + ) -> Union[EfiSignatureDataEfiCertSha256, EfiSignatureDataEfiCertX509]: """Create a new EFI Sginature Data Object. Args: - type (uuid.UUID): Guid of the type - ContentFileStream (BinaryIO): filestream to read - sigowner (uuid.UUID): the uuid object of the signature owner guid + type: Guid of the type + ContentFileStream: filestream to read + sigowner: the uuid object of the signature owner guid """ if (ContentFileStream is None): raise Exception("Invalid Content File Stream") @@ -561,7 +577,7 @@ class EfiSignatureList(CommonUefiStructure): """An object representing a EFI_SIGNATURE_LIST.""" STATIC_STRUCT_SIZE = 16 + 4 + 4 + 4 - def __init__(self, filestream: BinaryIO = None, typeguid: uuid.UUID = None): + def __init__(self, filestream: BinaryIO = None, typeguid: uuid.UUID = None) -> None: """Inits the object. Args: @@ -603,7 +619,7 @@ def SignatureData_List(self, value: list) -> None: warn("SignatureData_List is deprecated. Use signature_data_list instead.", DeprecationWarning, 2) self.signature_data_list = value - def decode(self, fs: BinaryIO): + def decode(self, fs: BinaryIO) -> None: """Decodes a filestream and generates the structure. Args: @@ -664,7 +680,7 @@ def decode(self, fs: BinaryIO): fs, self.signature_type, self.signature_size) self.signature_data_list.append(a) - def PopulateFromFileStream(self, fs: BinaryIO): + def PopulateFromFileStream(self, fs: BinaryIO) -> None: """Decodes a filestream and generates the structure. Args: @@ -679,12 +695,12 @@ def PopulateFromFileStream(self, fs: BinaryIO): warn("PopulateFromFileStream() is deprecated, use decode() instead.", DeprecationWarning, 2) self.decode(fs) - def Print(self, compact: bool = False, outfs=sys.stdout): + def Print(self, compact: bool = False, outfs: IO=sys.stdout) -> None: """Prints to the console.""" warn("Print() is deprecated, use print() instead().", DeprecationWarning, 2) self.print(compact=compact, outfs=outfs) - def print(self, compact: bool = False, outfs=sys.stdout): + def print(self, compact: bool = False, outfs: IO=sys.stdout) -> None: """Prints to the console.""" if not compact: outfs.write("EfiSignatureList\n") @@ -713,7 +729,7 @@ def print(self, compact: bool = False, outfs=sys.stdout): for a in self.signature_data_list: a.print(compact=compact, outfs=outfs) - def Write(self, fs): + def Write(self, fs: BinaryIO) -> None: """Serializes the object and writes it to a filestream. Raises: @@ -723,7 +739,7 @@ def Write(self, fs): warn("Write() is deprecated, use write() instead", DeprecationWarning, 2) self.write(fs) - def write(self, fs): + def write(self, fs: BinaryIO) -> None: """Serializes the object and writes it to a filestream. Raises: @@ -757,7 +773,7 @@ def encode(self) -> bytes: self.write(fs) return fs.getvalue() - def AddSignatureHeader(self, SigHeader, SigSize=0): + def AddSignatureHeader(self, SigHeader: bytes, SigSize: int=0) -> None: """Adds the Signature Header. Raises: @@ -784,7 +800,10 @@ def AddSignatureHeader(self, SigHeader, SigSize=0): self.signature_size = SigHeader.GetSizeOfSignatureDataEntry() self.signature_list_size += self.signature_header_size - def AddSignatureData(self, SigDataObject): + def AddSignatureData( + self, + SigDataObject: Tuple['EfiSignatureDataEfiCertX509', 'EfiSignatureDataEfiCertSha256'] + ) -> None: """Adds the Signature Data. Raises: @@ -803,7 +822,7 @@ def AddSignatureData(self, SigDataObject): self.signature_data_list.append(SigDataObject) self.signature_list_size += self.signature_size - def MergeSignatureList(self, esl): + def MergeSignatureList(self, esl: 'EfiSignatureList') -> None: """Add the EfiSignatureData entries within the supplied EfiSignatureList to the current object. No sorting or deduplication is performed, the EfiSignatureData elements are simply appended @@ -837,7 +856,7 @@ def MergeSignatureList(self, esl): self.signature_list_size += esl.signature_list_size - \ EfiSignatureList.STATIC_STRUCT_SIZE - def SortBySignatureDataValue(self, deduplicate: bool = True): + def SortBySignatureDataValue(self, deduplicate: bool = True) -> 'EfiSignatureList': """Sort self's signature_data_list by signature_data values (ignores SigOwner) & optionally deduplicate. When deduplicate is true, remove duplicate signature_data values from self and return them in an @@ -889,7 +908,7 @@ class EfiSignatureDatabase(CommonUefiStructure): Useful for parsing and building the contents of the Secure Boot variables """ - def __init__(self, filestream: BinaryIO = None, EslList: List[EfiSignatureList] = None): + def __init__(self, filestream: BinaryIO = None, EslList: List[EfiSignatureList] = None) -> None: """Inits an Efi Signature Database object. Args: @@ -902,7 +921,7 @@ def __init__(self, filestream: BinaryIO = None, EslList: List[EfiSignatureList] else: self.EslList = [] if EslList is None else EslList - def decode(self, fs: BinaryIO, decodesize: int = -1): + def decode(self, fs: BinaryIO, decodesize: int = -1) -> None: """Decodes a filestream and generates the structure. Args: @@ -924,7 +943,7 @@ def decode(self, fs: BinaryIO, decodesize: int = -1): Esl = EfiSignatureList(fs) self.EslList.append(Esl) - def PopulateFromFileStream(self, fs: BinaryIO): + def PopulateFromFileStream(self, fs: BinaryIO) -> None: """Decodes a filestream and generates the structure. Args: @@ -936,17 +955,17 @@ def PopulateFromFileStream(self, fs: BinaryIO): """ return self.decode(fs) - def print(self, compact: bool = False, outfs=sys.stdout): + def print(self, compact: bool = False, outfs: IO=sys.stdout) -> None: """Prints to the console.""" for Esl in self.EslList: Esl.print(compact=compact, outfs=outfs) - def Print(self, compact: bool = False, outfs=sys.stdout): + def Print(self, compact: bool = False, outfs: IO=sys.stdout) -> None: """Prints to the console.""" warn("Print() is deprecated, use print() instead.", DeprecationWarning, 2) self.print(compact=compact, outfs=outfs) - def Write(self, fs): + def Write(self, fs: BinaryIO) -> None: """Serializes the object and writes it to a filestream. Raises: @@ -955,7 +974,7 @@ def Write(self, fs): warn("Write() is deprecated, use write() instead.", DeprecationWarning, 2) self.write(fs) - def write(self, fs): + def write(self, fs: BinaryIO) -> None: """Serializes the object and writes it to a filestream. Raises: @@ -977,7 +996,7 @@ def encode(self) -> bytes: self.write(fs) return fs.getvalue() - def get_canonical_and_dupes(self): + def get_canonical_and_dupes(self) -> tuple['EfiSignatureDatabase', 'EfiSignatureDatabase']: """Compute and return a tuple containing both a canonicalized database & a database of duplicates. Returns: @@ -1037,7 +1056,7 @@ def get_canonical_and_dupes(self): return (canonicalDb, duplicatesDb) - def GetCanonicalAndDupes(self): + def GetCanonicalAndDupes(self) -> tuple['EfiSignatureDatabase', 'EfiSignatureDatabase']: """Compute and return a tuple containing both a canonicalized database & a database of duplicates. Returns: @@ -1053,22 +1072,22 @@ def GetCanonicalAndDupes(self): warn("GetCanonicalAndDupes() is deprecated. Use get_canonical_and_dupes() instead.", DeprecationWarning, 2) return self.get_canonical_and_dupes() - def get_canonical(self): + def get_canonical(self) -> 'EfiSignatureDatabase': """Return a canonicalized EfiSignatureDatabase, see GetCanonicalAndDupes() for more details.""" canonical, _ = self.get_canonical_and_dupes() return canonical - def GetCanonical(self): + def GetCanonical(self) -> 'EfiSignatureDatabase': """Return a canonicalized EfiSignatureDatabase, see GetCanonicalAndDupes() for more details.""" warn("GetCanonical() is deprecated. Use get_canonical() instead.", DeprecationWarning, 2) return self.get_canonical() - def get_duplicates(self): + def get_duplicates(self) -> 'EfiSignatureDatabase': """Return an EfiSignatureDatabase of duplicates, see GetCanonicalAndDupes() for more details.""" _, dupes = self.get_canonical_and_dupes() return dupes - def GetDuplicates(self): + def GetDuplicates(self) -> 'EfiSignatureDatabase': """Return an EfiSignatureDatabase of duplicates, see GetCanonicalAndDupes() for more details.""" warn("GetDuplicates() is deprecated. Use get_duplicates() instead.", DeprecationWarning, 2) return self.get_duplicates() @@ -1079,19 +1098,19 @@ class EfiTime(CommonUefiStructure): _StructFormat = ' None: """Inits an EFI_TIME object. Args: - time (:obj:`datetime`, optional): Inits object with specified date (if decodefs not set) - decodefs (:obj:`BinaryIO`, optional): Inits the object with this stream + time: Inits object with specified date (if decodefs not set) + decodefs: Inits the object with this stream """ if decodefs is None: self.time = time else: self.decode(decodefs) - def decode(self, fs): + def decode(self, fs: BinaryIO) -> datetime.datetime: """Decodes a filestream and generates the structure. Args: @@ -1133,7 +1152,7 @@ def decode(self, fs): return self.time - def PopulateFromFileStream(self, fs): + def PopulateFromFileStream(self, fs: BinaryIO) -> datetime.datetime: """Decodes a filestream and generates the structure. Args: @@ -1146,22 +1165,22 @@ def PopulateFromFileStream(self, fs): warn("PopulateFromFileStream() is deprecated, use decode() instead", DeprecationWarning, 2) return self.decode(fs) - def Print(self, outfs=sys.stdout): + def Print(self, outfs: IO=sys.stdout) -> None: """Prints to the console.""" warn("Print() is deprecated, use print() instead", DeprecationWarning, 2) return self.print(outfs) - def print(self, outfs=sys.stdout): + def print(self, outfs: IO=sys.stdout) -> None: """Prints to the console.""" outfs.write("\nEfiTime: %s\n" % datetime.datetime.strftime( self.time, "%A, %B %d, %Y %I:%M%p")) - def Encode(self): + def Encode(self) -> bytes: """Return's time as a packed EfiTime Structure.""" warn("Encode() is deprecated use encode() instead", DeprecationWarning, 2) return self.encode() - def encode(self): + def encode(self) -> bytes: """Get's time as packed EfiTime structure.""" return struct.pack( EfiTime._StructFormat, @@ -1178,7 +1197,7 @@ def encode(self): 0 # Pad2 ) - def write(self, fs): + def write(self, fs: IO) -> None: """Serializes the object and writes it to a filestream. Raises: @@ -1189,7 +1208,7 @@ def write(self, fs): fs.write(self.encode()) - def Write(self, fs): + def Write(self, fs: IO) -> None: """Serializes the object and writes it to a filestream. Raises: @@ -1198,7 +1217,7 @@ def Write(self, fs): warn("Write is deprecated(), use write() instead", DeprecationWarning, 2) self.write(fs) - def __str__(self): + def __str__(self) -> str: """String representation of EFI_TIME.""" return datetime.datetime.strftime(self.time, "%A, %B %d, %Y %I:%M%p") @@ -1206,12 +1225,12 @@ def __str__(self): class EfiVariableAuthentication2(CommonUefiStructure): """An object representing a EFI_VARIABLE_AUTHENTICATION_2.""" - def __init__(self, time=datetime.datetime.now(), decodefs=None): + def __init__(self, time: datetime.datetime=datetime.datetime.now(), decodefs: BinaryIO=None) -> None: """Inits an EFI_VARIABLE_AUTHENTICATION_2 object. Args: - time (:obj:`datetime`, optional): Inits object with specified date (if decodefs not set) - decodefs (:obj:`BinaryIO`, optional): Inits the object with this stream + time: Inits object with specified date (if decodefs not set) + decodefs: Inits the object with this stream """ if decodefs: self.decode(decodefs) @@ -1225,10 +1244,11 @@ def __init__(self, time=datetime.datetime.now(), decodefs=None): # Most variables do not have a sig list self.sig_list_payload = None - def encode(self): + def encode(self) -> bytes: """Encodes a new variable into a binary representation. - :return: buffer - binary representation of the variable + Returns: + (bytes): binary representation of the variable """ buffer = self.time.encode() + self.auth_info.encode() @@ -1237,13 +1257,14 @@ def encode(self): return buffer - def Encode(self, outfs=None): + def Encode(self, outfs: BinaryIO=None) -> bytes: """Encodes a new variable into a binary representation. Args: - outfs (BinaryIO): [default: None] write's to a file stream if provided + outfs: [default: None] write's to a file stream if provided - :return: buffer - binary representation of the variable + Returns: + (bytes): binary representation of the variable """ warn("Encode() is deprecated, use encode() instead", DeprecationWarning, 2) @@ -1253,11 +1274,11 @@ def Encode(self, outfs=None): return buffer - def decode(self, fs): + def decode(self, fs: BinaryIO) -> None: """Decodes a filestream and generates the structure. Args: - fs (BinaryIO): filestream to load from + fs: filestream to load from Raises: (Exception): Invalid filestream @@ -1271,11 +1292,11 @@ def decode(self, fs): self.set_payload(fs) - def PopulateFromFileStream(self, fs): + def PopulateFromFileStream(self, fs: BinaryIO) -> None: """Decodes a filestream and generates the structure. Args: - fs (BinaryIO): filestream to load from + fs: filestream to load from Raises: (ValueError): Invalid filestream @@ -1283,7 +1304,7 @@ def PopulateFromFileStream(self, fs): warn("PopulateFromFileStream() is deprecated, use decode() instead.", DeprecationWarning, 2) self.decode(fs) - def print(self, outfs=sys.stdout): + def print(self, outfs: IO=sys.stdout) -> None: """Prints to the console.""" outfs.write("EfiVariableAuthentication2\n") self.time.print(outfs) @@ -1300,16 +1321,16 @@ def print(self, outfs=sys.stdout): raise Exception("Invalid Payload Data Size vs Length of data") hexdump(sdl, outfs=outfs) - def Print(self, outfs=sys.stdout): + def Print(self, outfs: IO=sys.stdout) -> None: """Prints to the console.""" warn("Print() is deprecated, use print() instead.", DeprecationWarning, 2) self.print(outfs=outfs) - def write(self, fs) -> None: + def write(self, fs: BinaryIO) -> None: """Serializes the object and writes it to a filestream. Args: - fs (BinaryIO): filestream to write to + fs: filestream to write to Raises: (ValueError): Invalid filestream @@ -1322,22 +1343,22 @@ def write(self, fs) -> None: if self.payload is not None: fs.write(self.payload) - def Write(self, fs) -> None: + def Write(self, fs: BinaryIO) -> None: """Serializes the object and writes it to a filestream. Args: - fs (BinaryIO): filestream to write to + fs: filestream to write to Raises: (ValueError): Invalid filestream """ return self.write(fs) - def SetPayload(self, fs) -> None: + def SetPayload(self, fs: BinaryIO) -> None: """Decodes a filestream and generates the payload. Args: - fs (BinaryIO): filestream to load from + fs: filestream to load from Raises: (ValueError): Invalid filestream @@ -1345,11 +1366,11 @@ def SetPayload(self, fs) -> None: warn("SetPayload() is deprecated, use set_payload() instead.", DeprecationWarning, 2) self.set_payload(fs) - def set_payload(self, fs) -> None: + def set_payload(self, fs: BinaryIO) -> None: """Decodes a filestream and generates the payload. Args: - fs (BinaryIO): filestream to load from + fs: filestream to load from Raises: (ValueError): Invalid filestream @@ -1384,7 +1405,14 @@ def set_payload(self, fs) -> None: class EfiVariableAuthentication2Builder(object): """Builds EfiVariableAuthentication2 variables.""" - def __init__(self, name, guid, attributes, payload=None, efi_time=datetime.datetime.now()): + def __init__( + self, + name: str, + guid: str, + attributes: Union[int, str], + payload: Optional[Union[io.BytesIO, bytes]]=None, + efi_time: datetime.datetime=datetime.datetime.now() + ) -> None: """Builds a EfiVariableAuthentication2 structure. Args: @@ -1431,11 +1459,11 @@ def get_signature(self) -> bytes: """Returns the Signature of the digest (PKCS#7 ContentInfo or SignedData structure).""" return self.signature - def update_payload(self, payload) -> None: + def update_payload(self, payload: Union[io.ByteIO, bytes]) -> None: """Updates the authenticated variables payload and ultimately the digest. Args: - payload (io.ByteIO | bytes): byte array or byte file stream of variable data + payload: byte array or byte file stream of variable data Returns: None @@ -1459,8 +1487,12 @@ def update_payload(self, payload) -> None: self.authenticated_variable.set_payload(payload) - def sign(self, signing_certificate: Certificate, signing_private_key: RSAPrivateKey, - additional_certificates: List = [], **kwargs) -> None: + def sign( + self, signing_certificate: Certificate, + signing_private_key: RSAPrivateKey, + additional_certificates: List = [], + **kwargs: Any + ) -> None: """Signs an authenticated variable. Args: @@ -1502,7 +1534,7 @@ def sign(self, signing_certificate: Certificate, signing_private_key: RSAPrivate # Add the certificate for verification self.signature_builder = self.signature_builder.add_certificate(cert.certificate) - def finalize(self, omit_content_info=True) -> EfiVariableAuthentication2: + def finalize(self, omit_content_info: bool=True) -> EfiVariableAuthentication2: """Finalizes the signature and returns a EfiVariableAuthentication2. Args: @@ -1546,7 +1578,7 @@ def finalize(self, omit_content_info=True) -> EfiVariableAuthentication2: class EFiVariableAuthentication2(EfiVariableAuthentication2): """An object representing a EFI_VARIABLE_AUTHENTICATION_2. DEPRECATED.""" - def __init__(self, time=datetime.datetime.now(), decodefs=None): + def __init__(self, time: datetime.datetime=datetime.datetime.now(), decodefs: BinaryIO=None) -> None: """DEPRECATED. Use EfiVariableAuthentication2() instead. Initializes a EFiVariableAuthentication2.""" warn("EFiVariableAuthentication2() is deprecated, use EfiVariableAuthentication2() instead.", DeprecationWarning, 2) # noqa: E501 super().__init__(time, decodefs=decodefs) diff --git a/edk2toollib/uefi/bmp_object.py b/edk2toollib/uefi/bmp_object.py index c12e62497..67890c5e4 100644 --- a/edk2toollib/uefi/bmp_object.py +++ b/edk2toollib/uefi/bmp_object.py @@ -8,6 +8,7 @@ """Module for reading and parsing bitmap graphics files.""" import logging import struct +from typing import IO, Optional class BmpColorMap(object): @@ -29,7 +30,7 @@ class BmpColorMap(object): """ STATIC_SIZE = 4 - def __init__(self, filestream=None): + def __init__(self, filestream: Optional[IO]=None) -> None: """Inits an empty object or loads from an fs.""" if filestream is None: self.Blue = 0 @@ -39,7 +40,7 @@ def __init__(self, filestream=None): else: self.PopulateFromFileStream(filestream) - def PopulateFromFileStream(self, fs): + def PopulateFromFileStream(self, fs: IO) -> None: """Loads a bmp from a filestream. Args: @@ -66,7 +67,7 @@ def PopulateFromFileStream(self, fs): self.Red = struct.unpack("=B", fs.read(1))[0] self.Reserved = struct.unpack("=B", fs.read(1))[0] - def Print(self): + def Print(self) -> None: """Logs the object.""" logger = logging.get(__name__) logger.info("BMP Color Map") @@ -75,7 +76,7 @@ def Print(self): logger.info(" Red: 0x%X" % self.Red) logger.info(" Reserved: 0x%X" % self.Reserved) - def Write(self, fs): + def Write(self, fs: IO) -> None: """Writes the object to a fs.""" fs.write(struct.pack("=B", self.Blue)) fs.write(struct.pack("=B", self.Green)) @@ -110,7 +111,7 @@ class BmpObject(object): STATIC_FILE_HEADER_SIZE = 14 STATIC_IMAGE_HEADER_SIZE = 40 - def __init__(self, filestream=None): + def __init__(self, filestream: Optional[IO]=None) -> None: """Inits an empty object or loads from filestream.""" self.logger = logging.getLogger(__name__) if filestream is None: @@ -143,7 +144,7 @@ def __init__(self, filestream=None): self.ColorMapList = [] self.PopulateFromFileStream(filestream) - def ExpectedColorMapEntires(self): + def ExpectedColorMapEntires(self) -> int: """Returns expected entries depending on BitPerPixel.""" if (self.BitPerPixel == 1): return 2 @@ -154,7 +155,7 @@ def ExpectedColorMapEntires(self): else: return 0 - def PopulateFromFileStream(self, fs): + def PopulateFromFileStream(self, fs: IO) -> None: """Method to un-serialize from a filestream. Args: @@ -243,7 +244,7 @@ def PopulateFromFileStream(self, fs): raise Exception( "Extra Data at the end of BMP file - 0x%X bytes" % (end - fs.tell())) - def Print(self, PrintImageData=False, PrintColorMapData=False): + def Print(self, PrintImageData: bool=False, PrintColorMapData: bool=False) -> None: """Prints to logger. Args: @@ -297,11 +298,11 @@ def Print(self, PrintImageData=False, PrintColorMapData=False): self.logger.info("") self.logger.info("") - def Write(self, fs): + def Write(self, fs: IO) -> bytes: r"""Serializes the Bmp object. Returns: - (str): string representing packed data as bytes (i.e. b'\x01\x00\x03') + (bytes): string representing packed data as bytes (i.e. b'\x01\x00\x03') """ # Bmp File header fs.write(struct.pack("=c", self.CharB)) diff --git a/edk2toollib/uefi/edk2/build_objects/dsc.py b/edk2toollib/uefi/edk2/build_objects/dsc.py index bc8b73301..d7704ff86 100644 --- a/edk2toollib/uefi/edk2/build_objects/dsc.py +++ b/edk2toollib/uefi/edk2/build_objects/dsc.py @@ -8,19 +8,20 @@ """Data model for the EDK II DSC.""" # There will be some overlap between the objects for DSC files and FDF files import collections +from typing import Any, Optional DEFAULT_SECTION_TYPE = "COMMON" class dsc_set(set): """a DSC set object.""" - def __init__(self, allowed_classes=None): + def __init__(self, allowed_classes: list=None) -> None: """Initializes an empty set.""" if allowed_classes is None: allowed_classes = [] self._allowed_classes = set(allowed_classes) - def add(self, item): + def add(self, item: Any) -> None: # noqa: ANN401 """Adds the item to the set. Raises: @@ -37,7 +38,7 @@ def add(self, item): class dsc_dict(collections.OrderedDict): """A dictionary that allows specific classes as headers and sections.""" - def __init__(self, allowed_key_classes=None, allowed_value_classes=None): + def __init__(self, allowed_key_classes: Optional[str]=None, allowed_value_classes: Optional[Any]=None) -> None: """Initializes a dsc_dict.""" if allowed_key_classes is None: allowed_key_classes = [] @@ -46,7 +47,7 @@ def __init__(self, allowed_key_classes=None, allowed_value_classes=None): self._allowed_key_classes = set(allowed_key_classes) self._allowed_value_classes = set(allowed_value_classes) - def __missing__(self, key): + def __missing__(self, key: int) -> str: """Describes how to handle a missing key. Makes a new dsc_set if allowed. @@ -59,7 +60,7 @@ def __missing__(self, key): return self[key] raise KeyError(key) - def __setitem__(self, key, val): + def __setitem__(self, key: int, val: str) -> None: """Setting a key value pair in the Ordered Dictionary. Raises: @@ -87,7 +88,7 @@ def __setitem__(self, key, val): class dsc: """Class representing a DSC.""" - def __init__(self, file_path=None): + def __init__(self, file_path: Optional[str]=None) -> None: """Inits dsc type.""" # The EDK2 path to this particular DSC, if is is None it means it was created from a stream and has no file self.file_path = file_path @@ -109,7 +110,7 @@ def __init__(self, file_path=None): # NEXTVER: should we populate the default information into the DSC object? # FOR EXAMPLE: default_stores and skus - def __eq__(self, other): + def __eq__(self, other: 'dsc') -> bool: """Enables equality comparisons (a == b). Warning: @@ -145,19 +146,19 @@ class dsc_section_type: "DXE_SMM_DRIVER", "SMM_CORE", "UEFI_DRIVER", "UEFI_APPLICATION", "USER_DEFINED"] - def __init__(self, arch="common", module_type="common"): + def __init__(self, arch: str="common", module_type: str="common") -> None: """Inits dsc section type.""" self.arch = arch.upper().strip() self.module_type = module_type.upper().strip() if not dsc_section_type.IsValidModuleType(self.module_type): raise ValueError(f"{module_type} is not a proper module type for dsc section") - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" arch = "*" if (self.arch == "COMMON" or self.arch == "DEFAULT") else self.arch return hash((arch, self.module_type)) - def __eq__(self, other): + def __eq__(self, other: 'dsc_section_type') -> bool: """Enables equality comparisons (a == b).""" if type(other) is not dsc_section_type: return False @@ -165,13 +166,13 @@ def __eq__(self, other): arch2 = "*" if (other.arch == "COMMON" or other.arch == "DEFAULT") else other.arch return self.module_type == other.module_type or arch == arch2 - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" attributes = f".{self.arch}.{self.module_type}" return attributes @classmethod - def IsValidModuleType(cls, name): + def IsValidModuleType(cls: 'dsc_section_type', name: str) -> bool: """If the module type is valid or not.""" return name in cls.dsc_module_types @@ -192,7 +193,7 @@ class dsc_buildoption_section_type(dsc_section_type): BuildOptions ``` """ - def __init__(self, arch="common", codebase="common", module_type="common"): + def __init__(self, arch: str="common", codebase: str="common", module_type: str="common") -> None: """Inits dsc build option section type.""" super().__init__(arch, module_type) self.codebase = codebase.upper().strip() @@ -200,22 +201,22 @@ def __init__(self, arch="common", codebase="common", module_type="common"): raise ValueError(f"{codebase} is not a valid codebase type") @classmethod - def IsValidCodeBase(cls, codebase): + def IsValidCodeBase(cls: 'dsc_buildoption_section_type', codebase: str) -> bool: """Determines if codebase is valid. Args: - codebase (str): codebase + codebase: codebase Returns: (bool): True if COMMON, EDK, EDKII else false """ return codebase in ["COMMON", "EDK", "EDKII"] - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" return hash((super().__hash__(), self.codebase)) - def __eq__(self, other): + def __eq__(self, other: 'dsc_buildoption_section_type') -> bool: """Enables equality comparisons (a == b).""" if type(other) is not dsc_buildoption_section_type: return False @@ -223,7 +224,7 @@ def __eq__(self, other): return False return other.module_type == self.module_type - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" return f"{self.arch}.{self.codebase}.{self.module_type}" @@ -236,12 +237,12 @@ class dsc_pcd_section_type(): """This class is uses to define the PCD section type inside a component. Attributes: - pcdtype (str): pcd type - arch (:obj:`str`, optional): defaults to common - sku (:obj:`str`, optional): defaults to DEFAULT - store (:obj:`bool`, optional): if none, we don't have anything done + pcdtype: pcd type + arch: defaults to common + sku: defaults to DEFAULT + store: if none, we don't have anything done """ - def __init__(self, pcdtype, arch="common", sku="DEFAULT", store=None): + def __init__(self, pcdtype: str, arch: str="common", sku: str="DEFAULT", store: Optional[str]=None) -> None: """Inits the dsc_pcd_section object.""" # if store is none, then we don't have anything done self.arch = arch.upper().strip() @@ -253,16 +254,16 @@ def __init__(self, pcdtype, arch="common", sku="DEFAULT", store=None): raise ValueError(f"{pcdtype} does not allow for a store to be specified") self.sku = sku.upper() - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" return hash((self.arch, self.pcd_type)) - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" store = "" if self.default_store is None else f".{self.default_store}" return f"Pcds{self.pcd_type}.{self.arch}.{self.sku}{store}" - def __eq__(self, other): + def __eq__(self, other: 'dsc_pcd_section_type') -> bool: """Enables equality comparisons (a == b).""" if type(other) is not dsc_pcd_section_type: return False @@ -272,19 +273,19 @@ def __eq__(self, other): class dsc_pcd_component_type(dsc_pcd_section_type): """This class is uses to define the PCD type inside a component.""" - def __init__(self, pcdtype): + def __init__(self, pcdtype: str) -> None: """Inits the dsc_pcd_component object.""" super().__init__(pcdtype) - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" return f"Pcds{self.pcd_type}" - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" return hash(self.pcd_type) - def __eq__(self, other): + def __eq__(self, other: 'dsc_pcd_component_type') -> bool: """Enables equality comparisons (a == b).""" if type(other) is not dsc_pcd_component_type: return False @@ -295,26 +296,32 @@ class sku_id: """Contains the data for a sku. Args: - id (int): sku id number - name (:obj:`str`, optional): name of the sku - parent (:obj:`str`, optional): parent - source_info (:obj:`str`, optional): source info + id: sku id number + name: name of the sku + parent: parent + source_info: source info """ - def __init__(self, id=0, name="DEFAULT", parent="DEFAULT", source_info=None): + def __init__( + self, + id: int=0, + name: str="DEFAULT", + parent: str="DEFAULT", + source_info: Optional['source_info']=None + ) -> None: """Inits the sku_id object.""" self.id = id self.name = name self.parent = parent # the default parent is default self.source_info = source_info - def __eq__(self, other): + def __eq__(self, other: 'sku_id') -> bool: """Enables equality comparisons (a == b).""" if type(other) is not sku_id: return False return self.id == other.id or self.name == other.name - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" # we return zero because we want all the skus to hash to the same bucket # this won't be performant for large numbers of skus, which hopefully won't happen @@ -322,7 +329,7 @@ def __hash__(self): # since we want to make sure names and id's are unique return 0 - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" return f"{self.id}|{self.name}|{self.parent}" @@ -330,7 +337,7 @@ def __repr__(self): class component: """Contains the data for a component for the EDK build system to build.""" - def __init__(self, inf, source_info=None): + def __init__(self, inf: str, source_info: Optional['source_info']=None) -> None: """Inits the component object.""" self.library_classes = set() # a list of libraries that this component uses self.pcds = {} # a dictionary of PCD's that are keyed by dsc_pcd_component_type, they are sets @@ -339,17 +346,17 @@ def __init__(self, inf, source_info=None): self.inf = inf # the EDK2 relative path to the source INF self.source_info = source_info - def __eq__(self, other): + def __eq__(self, other: 'component') -> bool: """Enables equality comparisons (a == b).""" if (type(other) is not component): return False return self.inf == other.inf # NEXTVER: should this be case insensitive? - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" return hash(self.inf) - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" source = str(self.source_info) if source_info is not None else "" return f"{self.inf} @ {source}" @@ -359,13 +366,13 @@ class definition: """Contains the information on a definition. Args: - name (obj): definition name - value (obj): definition value - local (:obj:`bool`, optional): if the value is local or not - source_info (:obj:`bool`, optional): source info + name: definition name + value: definition value + local: if the value is local or not + source_info: source info """ - def __init__(self, name, value, local=False, source_info=None): + def __init__(self, name: str, value: str, local: bool=False, source_info: Optional['source_info']=None) -> None: """Inits the definition object. NOTE: Local means DEFINE is in front and is localized to that particular section @@ -375,7 +382,7 @@ def __init__(self, name, value, local=False, source_info=None): self.local = local self.source_info = source_info - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" string = "" if self.local: @@ -383,11 +390,11 @@ def __repr__(self): string += f"{self.name} = {self.value} @ {self.source_info}" return string - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" return hash(self.name) - def __eq__(self, other): + def __eq__(self, other: 'definition') -> bool: """Enables equality comparisons (a == b).""" if (type(other) is not definition): return False @@ -402,22 +409,22 @@ class library: source_info (:obj:`obj`, optional): source info """ - def __init__(self, inf: str, source_info=None): + def __init__(self, inf: str, source_info: Optional['source_info']=None) -> None: """Inits the Library object.""" self.inf = inf self.source_info = source_info - def __eq__(self, other): + def __eq__(self, other: 'library') -> bool: """Enables equality comparisons (a == b).""" if type(other) is not library: return False return self.inf == other.inf - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" return hash(self.inf) # NEXTVER how to figure out if they hash to the same spot? - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" return f"{self.inf} @ {self.source_info}" @@ -426,24 +433,24 @@ class library_class: """Contains the data for a specific EDK2 library class. Attributes: - libraryclass (str): the EDK2 library class - inf (str): the inf - source_info (:obj:`obj`, optional): source info + libraryclass: the EDK2 library class + inf): the inf + source_info: source info """ - def __init__(self, libraryclass: str, inf: str, source_info=None): + def __init__(self, libraryclass: str, inf: str, source_info: Optional['source_info']=None) -> None: """Inits the Library class object. Args: - libraryclass (str): the EDK2 library class - inf (str): the inf - source_info (:obj:`obj`, optional): source info + libraryclass: the EDK2 library class + inf: the inf + source_info: source info """ self.libraryclass = libraryclass self.inf = inf self.source_info = source_info - def __eq__(self, other): + def __eq__(self, other: 'library_class') -> bool: """Enables equality comparisons (a == b).""" if (type(other) is not library_class): return False @@ -452,7 +459,7 @@ def __eq__(self, other): return self.inf == other.inf return self.libraryclass.lower() == other.libraryclass.lower() - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" # if we're a null lib, we want the hash to be based on the inf path if (self.libraryclass.lower() == "null"): @@ -460,7 +467,7 @@ def __hash__(self): else: return hash(self.libraryclass) - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" return f"{self.libraryclass}|{self.inf} @ {self.source_info}" @@ -469,39 +476,39 @@ class pcd: """A PCD object. Attributes: - namespace (obj): namespace - name (obj): pcd name - value (obj): pcd value - source_info (:obj:`obj`, optional): source info + namespace: namespace + name: pcd name + value: pcd value + source_info: source info EXAMPLE: PcdTokenSpaceGuidCName.PcdCName|Value """ - def __init__(self, namespace, name, value, source_info=None): + def __init__(self, namespace: str, name: str, value: str, source_info: Optional['source_info']=None) -> None: """Inits a PCD object. Args: - namespace (obj): namespace - name (obj): pcd name - value (obj): pcd value - source_info (:obj:`obj`, optional): source info + namespace: namespace + name: pcd name + value: pcd value + source_info: source info """ self.namespace = namespace self.name = name self.value = value self.source_info = source_info - def __eq__(self, other): + def __eq__(self, other: 'pcd') -> bool: """Enables equality comparisons (a == b).""" if not issubclass(other.__class__, pcd): return False return self.namespace == other.namespace and self.name == other.name - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" return hash(f"{self.namespace}.{self.name}") - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" return f"{self.namespace}.{self.name} = {self.value} @ {self.source_info}" @@ -510,19 +517,27 @@ class pcd_typed(pcd): """A Typed PCD object. Attributes: - datum_type (obj): Data Type - max_size (obj): max size of the data type + datum_type: Data Type + max_size: max size of the data type EXAMPLE: PcdTokenSpaceGuidCName.PcdCName|Value[|DatumType[|MaximumDatumSize]] """ - def __init__(self, namespace, name, value, datum_type, max_size=0, source_info=None): + def __init__( + self, + namespace: str, + name: str, + value: str, + datum_type: str, + max_size: int=0, + source_info: Optional['source_info']=None + ) -> None: """Inits the Typed PCD Object.""" super().__init__(namespace, name, value, source_info) self.datum_type = datum_type self.max_size = int(max_size) - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" return f"{self.namespace}.{self.name} = {self.value} |{self.datum_type}|{self.max_size} @ {self.source_info}" @@ -534,18 +549,27 @@ class pcd_variable(pcd): """A Variable PCD object. Attributes: - var_name (obj): VariableName - var_guid (obj): VariableGuid - var_offset (obj): VariableOffset - default (:obj:`obj`, optional): default value - attribute (:obj:`obj`, optional): Optional attributes - source_info (:obj:`obj`, optional): source info + var_name: VariableName + var_guid: VariableGuid + var_offset: VariableOffset + default: default value + attribute: Optional attributes + source_info: source info EXAMPLE: PcdTokenSpaceGuidCName.PcdCName|VariableName|VariableGuid|VariableOffset[|HiiDefaultValue[|HiiAttribute]] """ - def __init__(self, namespace, name, var_name, var_guid, var_offset, - default=None, attributes=None, source_info=None): + def __init__( + self, + namespace: str, + name: str, + var_name: str, + var_guid: str, + var_offset: str, + default: Optional[str]=None, + attributes: Optional[str]=None, + source_info: Optional['source_info']=None + ) -> None: """Inits a pcd_variable object.""" super().__init__(namespace, name, "", source_info) if attributes is None: @@ -562,7 +586,7 @@ def __init__(self, namespace, name, var_name, var_guid, var_offset, raise ValueError(f"Invalid PcdHiiAttribute values: {attributes}") self.attributes = attributes - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" pcd_data = f"{self.var_guid}|{self.var_offset}|{self.default}|{self.attributes}" return f"{self.namespace}.{self.name} = {self.var_name} |{pcd_data} @ {self.source_info}" @@ -572,34 +596,44 @@ class build_option: """Build option object. Attributes: - tool_code (obj): One of the defined tool codes in the Conf/tools_def.txt file. - attribute (obj): for example flags, d_path, path - data (obj): the actual flags or path you want to set - target (obj): DEBUG, RELEASE, or other - tagname (obj): the tool chain tag - arch (obj): ARM, AARCH64, IA32, X64, etc - family (obj): Conf/tools_def.txt defines FAMILY as one of MSFT, INTEL or GCC. - replace (obj): whether or not this replaces the default from tools_def, if this is false, we append - source_info (obj): source_info object. + tool_code: One of the defined tool codes in the Conf/tools_def.txt file. + attribute: for example flags, d_path, path + data: the actual flags or path you want to set + target: DEBUG, RELEASE, or other + tagname: the tool chain tag + arch: ARM, AARCH64, IA32, X64, etc + family: Conf/tools_def.txt defines FAMILY as one of MSFT, INTEL or GCC. + replace: whether or not this replaces the default from tools_def, if this is false, we append + source_info: source_info object. NOTE: Contains the data for a build option EX: MSFT:*_*_*_CC_FLAGS = /D MDEPKG_NDEBUG """ # {FAMILY}:{TARGET}_{TAGNAME}_{ARCH}_{TOOLCODE}_{ATTRIBUTE} - def __init__(self, tool_code, attribute, data, target="*", tagname="*", - arch="*", family=None, replace=False, source_info=None): + def __init__( + self, + tool_code: str, + attribute: str, + data: str, + target: str="*", + tagname: str="*", + arch: str="*", + family: Optional[str]=None, + replace: bool=False, + source_info: 'source_info'=None + ) -> None: """Inits a build_option object. Args: - tool_code (obj): One of the defined tool codes in the Conf/tools_def.txt file. - attribute (obj): for example flags, d_path, path - data (obj): the actual flags or path you want to set - target (obj): DEBUG, RELEASE, or other - tagname (obj): the tool chain tag - arch (obj): ARM, AARCH64, IA32, X64, etc - family (obj): Conf/tools_def.txt defines FAMILY as one of MSFT, INTEL or GCC. - replace (obj): whether or not this replaces the default from tools_def, if this is false, we append - source_info (obj): source_info object. + tool_code: One of the defined tool codes in the Conf/tools_def.txt file. + attribute: for example flags, d_path, path + data: the actual flags or path you want to set + target: DEBUG, RELEASE, or other + tagname: the tool chain tag + arch: ARM, AARCH64, IA32, X64, etc + family: Conf/tools_def.txt defines FAMILY as one of MSFT, INTEL or GCC. + replace: whether or not this replaces the default from tools_def, if this is false, we append + source_info: source_info object. NOTE: attribute Attribute: The flags defined in this section are appended to flags defined in the tools_def.txt file @@ -619,7 +653,7 @@ def __init__(self, tool_code, attribute, data, target="*", tagname="*", self.data = data self.source_info = source_info - def __eq__(self, other): + def __eq__(self, other: 'build_option') -> bool: """Enables equality comparisons (a == b).""" if (type(other) is not build_option): return False @@ -637,11 +671,11 @@ def __eq__(self, other): return False return True - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" return hash(self.__repr__(False)) - def __repr__(self, include_data=True): + def __repr__(self, include_data: bool=True) -> str: """A string representation of the object.""" rep = "" if self.family is None else f"{self.family}:" rep += "_".join((self.target, self.tagname, self.arch, self.tool_code, self.attribute)) @@ -654,14 +688,14 @@ class default_store: """Object containing information on a default store. Attributes: - index (:obj:`int`, optional): index - value (:obj:`str`, optional): defaults to "Standard" - source_info (:obj:`str`, optional): defaults to None + index: index + value: defaults to "Standard" + source_info: defaults to None """ ''' contains the information on a default store. ''' ''' 0 | Standard # UEFI Standard default ''' - def __init__(self, index=0, value="Standard", source_info=None): + def __init__(self, index: int=0, value: str="Standard", source_info: Optional[str]=None) -> None: """Inits a default store object. NOTE: Local means DEFINE is in front and is localized to that particular section @@ -670,15 +704,15 @@ def __init__(self, index=0, value="Standard", source_info=None): self.value = value self.source_info = source_info - def __repr__(self): + def __repr__(self) -> str: """A string representation of the object.""" return f"{self.index} | {self.value}" - def __hash__(self): + def __hash__(self) -> int: """Returns the hash of an object for hashtables.""" return hash(self.index) - def __eq__(self, other): + def __eq__(self, other: 'default_store') -> bool: """Enables equality comparisons (a == b).""" if (type(other) is not default_store): return False @@ -692,12 +726,12 @@ class source_info: file (str): filename lineno (:obj:`int`, optional): line number """ - def __init__(self, file: str, lineno: int = None): + def __init__(self, file: str, lineno: int = None) -> None: """Inits a source_info object.""" self.file = file self.lineno = lineno - def __repr__(self): + def __repr__(self) -> str: """Returns a string representation of object.""" if self.lineno is None: return self.file diff --git a/edk2toollib/uefi/edk2/build_objects/dsc_translator.py b/edk2toollib/uefi/edk2/build_objects/dsc_translator.py index 9e18817a1..7c73af87e 100644 --- a/edk2toollib/uefi/edk2/build_objects/dsc_translator.py +++ b/edk2toollib/uefi/edk2/build_objects/dsc_translator.py @@ -24,7 +24,7 @@ class DscTranslator(): """A class used to translate DSCs.""" @classmethod - def dsc_to_file(cls, dsc_obj, filepath): + def dsc_to_file(cls: 'DscTranslator', dsc_obj: dsc, filepath: str) -> None: """Transforms the DSC object to a file.""" file_path = os.path.abspath(filepath) f = open(file_path, "w") @@ -34,7 +34,7 @@ def dsc_to_file(cls, dsc_obj, filepath): f.close() @classmethod - def _GetDscLinesFromDscObj(cls, obj, depth=0) -> list: + def _GetDscLinesFromDscObj(cls: 'DscTranslator', obj: dsc, depth: int=0) -> list: """Gets the DSC strings for an data model objects.""" lines = [] depth_pad = ''.ljust(depth) @@ -118,7 +118,7 @@ def _GetDscLinesFromDscObj(cls, obj, depth=0) -> list: return lines @classmethod - def _FormatComponent(cls, comp, depth=0): + def _FormatComponent(cls: 'DscTranslator', comp: dsc, depth: int=0) -> list[str]: has_subsection = len(comp.pcds) > 0 or len(comp.defines) > 0 or len( comp.build_options) > 0 or len(comp.library_classes) > 0 depth_pad = ''.ljust(depth) diff --git a/edk2toollib/uefi/edk2/fmp_payload_header.py b/edk2toollib/uefi/edk2/fmp_payload_header.py index 1694bda72..deb84062f 100644 --- a/edk2toollib/uefi/edk2/fmp_payload_header.py +++ b/edk2toollib/uefi/edk2/fmp_payload_header.py @@ -16,11 +16,11 @@ import struct -def _SIGNATURE_32(A, B, C, D): +def _SIGNATURE_32(A: str, B: str, C: str, D: str) -> bytes: return struct.unpack('=I', bytearray(A + B + C + D, 'ascii'))[0] -def _SIGNATURE_32_TO_STRING(Signature): +def _SIGNATURE_32_TO_STRING(Signature: int) -> bytes: return struct.pack(" None: """Inits an empty object.""" self.Signature = self._FMP_PAYLOAD_HEADER_SIGNATURE self.HeaderSize = self._StructSize @@ -49,11 +49,11 @@ def __init__(self): self.LowestSupportedVersion = 0x00000000 self.Payload = b'' - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the Header + payload. Returns: - (str): string representing packed data as bytes (i.e. b'\x01\x00\x03') + (bytes): string representing packed data as bytes (i.e. b'\x01\x00\x03') """ FmpPayloadHeader = struct.pack( self._StructFormat, @@ -64,7 +64,7 @@ def Encode(self): ) return FmpPayloadHeader + self.Payload - def Decode(self, Buffer): + def Decode(self, Buffer: bytes) -> bytes: """Loads data into the Object by parsing a buffer. Args: @@ -96,7 +96,7 @@ def Decode(self, Buffer): return self.Payload - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints payload header information.""" print('FMP_PAYLOAD_HEADER.Signature = {Signature:08X} ({SignatureString})' .format(Signature=self.Signature, SignatureString=_SIGNATURE_32_TO_STRING(self.Signature))) diff --git a/edk2toollib/uefi/edk2/ftw_working_block_format.py b/edk2toollib/uefi/edk2/ftw_working_block_format.py index a3318f1b9..6941870c6 100644 --- a/edk2toollib/uefi/edk2/ftw_working_block_format.py +++ b/edk2toollib/uefi/edk2/ftw_working_block_format.py @@ -9,6 +9,7 @@ import struct import sys import uuid +from typing import IO # # UEFI GUIDs @@ -32,7 +33,7 @@ class EfiFtwWorkingBlockHeader(object): UINT64 WriteQueueSize; } EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER; """ - def __init__(self): + def __init__(self) -> None: """Initializes an empty object.""" self.StructString = "=16sLBBBBQ" # spell-checker: disable-line self.Signature = None @@ -43,7 +44,7 @@ def __init__(self): self.Reserved3 = None self.WriteQueueSize = None - def load_from_file(self, file): + def load_from_file(self, file: IO) -> 'EfiFtwWorkingBlockHeader': """Loads an EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER from a file. Args: @@ -77,7 +78,7 @@ def load_from_file(self, file): return self - def serialize(self): + def serialize(self) -> bytes: r"""Serializes the EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER. Returns: @@ -103,7 +104,7 @@ class EfiFtwWriteHeader(object): UINT64 PrivateDataSize; } EFI_FAULT_TOLERANT_WRITE_HEADER; """ - def __init__(self): + def __init__(self) -> None: """Initializes an empty object.""" self.StructString = "=BBBB16sLQQ" self.StatusBits = None @@ -115,7 +116,7 @@ def __init__(self): self.NumberOfWrites = None self.PrivateDataSize = None - def load_from_file(self, file): + def load_from_file(self, file: IO) -> 'EfiFtwWriteHeader': """Loads an EFI_FAULT_TOLERANT_WRITE_HEADER from a file. Args: @@ -137,7 +138,7 @@ def load_from_file(self, file): return self - def serialize(self): + def serialize(self) -> bytes: r"""Serializes the EFI_FAULT_TOLERANT_WRITE_HEADER. Returns: @@ -164,7 +165,7 @@ class EfiFtwWriteRecord(object): INT64 RelativeOffset; } EFI_FAULT_TOLERANT_WRITE_RECORD; """ - def __init__(self): + def __init__(self) -> None: """Initializes an empty object.""" self.StructString = "=BBBBLQQQQ" # spell-checker: disable-line self.StatusBits = None @@ -177,7 +178,7 @@ def __init__(self): self.Length = None self.RelativeOffset = None - def load_from_file(self, file): + def load_from_file(self, file: IO) -> 'EfiFtwWriteRecord': """Loads an EFI_FAULT_TOLERANT_WRITE_RECORD from a file. Args: @@ -198,7 +199,7 @@ def load_from_file(self, file): return self - def serialize(self): + def serialize(self) -> bytes: r"""Serializes the EFI_FAULT_TOLERANT_WRITE_RECORD. Returns: diff --git a/edk2toollib/uefi/edk2/guid_list.py b/edk2toollib/uefi/edk2/guid_list.py index 470e7c2a4..5c3aa90fb 100644 --- a/edk2toollib/uefi/edk2/guid_list.py +++ b/edk2toollib/uefi/edk2/guid_list.py @@ -9,6 +9,7 @@ """Simple list of GuidListEntry objects parsed from edk2 specific files.""" import logging import os +from typing import IO from edk2toollib.gitignore_parser import parse_gitignore_lines from edk2toollib.uefi.edk2.parsers.dec_parser import DecParser @@ -23,7 +24,7 @@ class GuidListEntry(): guid (str): registry format guid in string format filepath (str): absolute path to file where this guid was found """ - def __init__(self, name: str, guid: str, filepath: str): + def __init__(self, name: str, guid: str, filepath: str) -> None: """Create GuidListEntry for later review and compare. Args: @@ -35,7 +36,7 @@ def __init__(self, name: str, guid: str, filepath: str): self.guid = guid self.absfilepath = filepath - def __str__(self): + def __str__(self) -> str: """String representation of the guid.""" return f"GUID: {self.guid} NAME: {self.name} FILE: {self.absfilepath}" @@ -91,12 +92,12 @@ def parse_guids_from_edk2_file(filename: str) -> list: return [] @staticmethod - def parse_guids_from_dec(stream, filename: str) -> list: + def parse_guids_from_dec(stream: IO, filename: str) -> list: """Find all guids in a dec file contents contained with stream. Args: - stream (obj): lines of dec file content - filename (str): abspath to dec file + stream: lines of dec file content + filename: abspath to dec file Returns: (list[GuidListEntry]): Guids diff --git a/edk2toollib/uefi/edk2/parsers/base_parser.py b/edk2toollib/uefi/edk2/parsers/base_parser.py index bc628ec52..2641454d7 100644 --- a/edk2toollib/uefi/edk2/parsers/base_parser.py +++ b/edk2toollib/uefi/edk2/parsers/base_parser.py @@ -8,6 +8,7 @@ """Code to support parsing EDK2 files.""" import logging import os +from typing import Optional, Union from warnings import warn from edk2toollib.uefi.edk2 import path_utilities @@ -28,7 +29,7 @@ class BaseParser(object): """ operators = ["OR", "AND", "IN", "==", "!=", ">", "<", "<=", ">="] - def __init__(self, log="BaseParser"): + def __init__(self, log: str="BaseParser") -> None: """Inits an empty Parser.""" self.Logger = logging.getLogger(log) self.Lines = [] @@ -49,7 +50,7 @@ def __init__(self, log="BaseParser"): # For include files set the base root path # - def SetEdk2Path(self, pathobj: path_utilities.Edk2Path): + def SetEdk2Path(self, pathobj: path_utilities.Edk2Path) -> 'BaseParser': """Sets the internal attribute Edk2PathUtil. !!! note @@ -87,7 +88,7 @@ def SetEdk2Path(self, pathobj: path_utilities.Edk2Path): self._Edk2PathUtil = pathobj return self - def SetBaseAbsPath(self, path): + def SetBaseAbsPath(self, path: str) -> 'BaseParser': """Sets the attribute RootPath. Args: @@ -101,11 +102,11 @@ def SetBaseAbsPath(self, path): self._ConfigEdk2PathUtil() return self - def _ConfigEdk2PathUtil(self): + def _ConfigEdk2PathUtil(self) -> None: """Creates the path utility object based on the root path and package paths.""" self._Edk2PathUtil = path_utilities.Edk2Path(self.RootPath, self.PPs, error_on_invalid_pp=False) - def SetPackagePaths(self, pps=[]): + def SetPackagePaths(self, pps: Optional[list[str]]=None) -> 'BaseParser': """Sets the attribute PPs. Args: @@ -117,11 +118,11 @@ def SetPackagePaths(self, pps=[]): (BaseParser): self """ warn("SetPackagePaths is deprecated. Use SetEdk2Path instead", DeprecationWarning) - self.PPs = pps + self.PPs = pps or [] self._ConfigEdk2PathUtil() return self - def SetInputVars(self, inputdict): + def SetInputVars(self, inputdict: dict) -> 'BaseParser': """Sets the attribute InputVars. Args: @@ -133,7 +134,7 @@ def SetInputVars(self, inputdict): self.InputVars = inputdict return self - def FindPath(self, *p): + def FindPath(self, *p: str) -> str: """Given a path, it will find it relative to the root, the current target file, or the packages path. Args: @@ -175,7 +176,7 @@ def FindPath(self, *p): self.Logger.error(f"Invalid file path: {p}") return None - def WriteLinesToFile(self, filepath): + def WriteLinesToFile(self, filepath: str) -> None: """Write all parsed lines to a file. Args: @@ -187,13 +188,13 @@ def WriteLinesToFile(self, filepath): file_handle.write(line + "\n") file_handle.close() - def ComputeResult(self, value, cond, value2): + def ComputeResult(self, value: Union[str, int], cond: str, value2: Union[str, int]) -> bool: """Compute a logical comaprison. Args: - value (str, int): First value - cond (str): comparison to do - value2 (str, int): Second value + value: First value + cond: comparison to do + value2: Second value Returns: (bool): result of comparison @@ -266,7 +267,7 @@ def ComputeResult(self, value, cond, value2): self.Logger.error(f"{self.__class__}: Unknown conditional: {cond}") raise RuntimeError("Unknown conditional") - def ConvertToInt(self, value): + def ConvertToInt(self, value: Union[str, int]) -> int: """Converts a str or int to an int based on prefix. Args: @@ -286,15 +287,15 @@ def ConvertToInt(self, value): else: return int(value, 10) - def PushConditional(self, v): + def PushConditional(self, v: bool) -> None: """Push new value onto the conditional stack. Args: - v (obj): Value to push + v: Value to push """ self.ConditionalStack.append(v) - def PopConditional(self): + def PopConditional(self) -> bool: """Pops the current conditional and return the value.""" if (len(self.ConditionalStack) > 0): return self.ConditionalStack.pop() @@ -302,7 +303,7 @@ def PopConditional(self): self.Logger.critical("Tried to pop an empty conditional stack. Line Number %d" % self.CurrentLine) return self.ConditionalStack.pop() # this should cause a crash but will give trace. - def _FindReplacementForToken(self, token, replace_if_not_found=False): + def _FindReplacementForToken(self, token: str, replace_if_not_found: bool=False) -> str: v = self.LocalVars.get(token) @@ -323,7 +324,7 @@ def _FindReplacementForToken(self, token, replace_if_not_found=False): return str(v) - def ReplaceVariables(self, line): + def ReplaceVariables(self, line: str) -> str: """Replaces a variable in a string. Args: @@ -363,7 +364,7 @@ def ReplaceVariables(self, line): return result - def ProcessConditional(self, text): + def ProcessConditional(self, text: str) -> bool: """Processes a conditional. Args: @@ -413,7 +414,7 @@ def ProcessConditional(self, text): return False - def EvaluateConditional(self, text): + def EvaluateConditional(self, text: str) -> bool: """Uses a pushdown resolver.""" text = str(text).strip() if not text.lower().startswith("!if "): @@ -480,7 +481,7 @@ def EvaluateConditional(self, text): return bool(final) @classmethod - def _TokenizeConditional(cls, text): + def _TokenizeConditional(cls: 'BaseParser', text: str) -> str: """Takes in a string that has macros replaced.""" # TOKENIZER # first we create tokens @@ -560,7 +561,7 @@ def _TokenizeConditional(cls, text): return collapsed_tokens @classmethod - def _ConvertTokensToPostFix(cls, tokens): + def _ConvertTokensToPostFix(cls: 'BaseParser', tokens: list[str]) -> list[str]: # convert infix into post fix stack = ["("] tokens.append(")") # add an extra parathesis @@ -606,7 +607,7 @@ def _ConvertTokensToPostFix(cls, tokens): return expression @classmethod - def _IsOperator(cls, token): + def _IsOperator(cls: 'BaseParser', token: str) -> bool: if type(token) is not str: return False if token.startswith("!+"): @@ -616,7 +617,7 @@ def _IsOperator(cls, token): return token in cls.operators @classmethod - def _GetOperatorPrecedence(cls, token): + def _GetOperatorPrecedence(cls: 'BaseParser', token: str) -> int: if not cls._IsOperator(token): return -1 if token == "(" or token == ")": @@ -627,7 +628,7 @@ def _GetOperatorPrecedence(cls, token): return 1 return 0 - def InActiveCode(self): + def InActiveCode(self) -> bool: """Determines what the state of the conditional you are currently in. Returns: @@ -641,7 +642,7 @@ def InActiveCode(self): return ret - def IsGuidString(self, line): + def IsGuidString(self, line: str) -> str: """Determines if a line is a guid string. Args: @@ -657,7 +658,7 @@ def IsGuidString(self, line): return True return False - def ParseGuid(self, line): + def ParseGuid(self, line: str) -> str: """Parse a guid into a different format. Args: @@ -738,7 +739,7 @@ def ParseGuid(self, line): return gu.upper() - def ResetParserState(self): + def ResetParserState(self) -> None: """Resets the state of the parser.""" self.ConditionalStack = [] self.CurrentSection = '' @@ -749,11 +750,11 @@ def ResetParserState(self): class HashFileParser(BaseParser): """Base class for Edk2 build files that use # for comments.""" - def __init__(self, log): + def __init__(self, log: str) -> None: """Inits an empty Parser for files that use # for comments..""" BaseParser.__init__(self, log) - def StripComment(self, line): + def StripComment(self, line: str) -> str: """Removes a comment from a line. Args: @@ -761,7 +762,7 @@ def StripComment(self, line): """ return line.split('#')[0].strip() - def ParseNewSection(self, line): + def ParseNewSection(self, line: str) -> tuple[bool, str]: """Parses a new section line. Args: diff --git a/edk2toollib/uefi/edk2/parsers/buildreport_parser.py b/edk2toollib/uefi/edk2/parsers/buildreport_parser.py index d9b19e216..baeaeec8d 100644 --- a/edk2toollib/uefi/edk2/parsers/buildreport_parser.py +++ b/edk2toollib/uefi/edk2/parsers/buildreport_parser.py @@ -9,6 +9,7 @@ import logging import os from enum import Enum +from typing import Optional import edk2toollib.uefi.edk2.path_utilities as pu @@ -28,7 +29,7 @@ class ModuleSummary(object): PackagePathList (list): list of package paths FvName (str): Name of Fv """ - def __init__(self, content, ws, packagepatahlist, pathconverter): + def __init__(self, content: str, ws: str, packagepatahlist: list, pathconverter: pu.Edk2Path) -> None: """Inits an empty Module Summary Object.""" self._RawContent = content self.Guid = "" @@ -43,7 +44,7 @@ def __init__(self, content, ws, packagepatahlist, pathconverter): self.FvName = None self.pathConverter = pathconverter - def Parse(self): + def Parse(self) -> None: """Parses the Module summary object.""" inPcdSection = False inLibSection = False @@ -194,7 +195,7 @@ class RegionTypes(Enum): MODULE = 'MODULE' UNKNOWN = 'UNKNOWN' - def __init__(self, filepath, ws, packagepathcsv, protectedWordsDict): + def __init__(self, filepath: str, ws: str, packagepathcsv: str, protectedWordsDict: dict) -> None: """Inits an empty BuildReport object.""" self.PlatformName = "" self.DscPath = "" @@ -217,7 +218,7 @@ def __init__(self, filepath, ws, packagepathcsv, protectedWordsDict): # do region level parsing # to get the layout, lists, and dictionaries setup. # - def BasicParse(self): + def BasicParse(self) -> None: """Performs region level parsing. Gets the layout, lists, and dictionaries setup. @@ -290,11 +291,11 @@ def BasicParse(self): if (r[0] == BuildReport.RegionTypes.FD): self._ParseFdRegionForModules(self._ReportContents[r[1]:r[2]]) - def FindComponentByInfPath(self, InfPath): + def FindComponentByInfPath(self, InfPath: str) -> Optional['ModuleSummary']: """Attempts to find the Component the Inf is apart of. Args: - InfPath (str): Inf Path + InfPath: Inf Path Returns: (ModuleSummary): Module if found @@ -308,7 +309,7 @@ def FindComponentByInfPath(self, InfPath): logging.error("Failed to find Module by InfPath %s" % InfPath) return None - def _ParseFdRegionForModules(self, rawcontents): + def _ParseFdRegionForModules(self, rawcontents: str) -> None: FvName = None index = 0 WorkspaceAndPPList = [self.Workspace] @@ -349,7 +350,7 @@ def _ParseFdRegionForModules(self, rawcontents): # # Get the start of region # - def _GetNextRegionStart(self, number): + def _GetNextRegionStart(self, number: int) -> Optional[int]: lineNumber = number while (lineNumber < len(self._ReportContents)): if self._ReportContents[lineNumber] == ">======================================================================================================================<": # noqa: E501 @@ -362,7 +363,7 @@ def _GetNextRegionStart(self, number): # # Get the end of region # - def _GetEndOfRegion(self, number): + def _GetEndOfRegion(self, number: int) -> Optional[int]: lineNumber = number while (lineNumber < len(self._ReportContents)): if self._ReportContents[lineNumber] == "<======================================================================================================================>": # noqa: E501 @@ -373,7 +374,7 @@ def _GetEndOfRegion(self, number): # didn't find new region return None - def _GetRegionType(self, lineNumber): + def _GetRegionType(self, lineNumber: int) -> 'BuildReport.RegionTypes': line = self._ReportContents[lineNumber].strip() if (line == "Firmware Device (FD)"): return BuildReport.RegionTypes.FD diff --git a/edk2toollib/uefi/edk2/parsers/dec_parser.py b/edk2toollib/uefi/edk2/parsers/dec_parser.py index 0a9446490..539afc862 100644 --- a/edk2toollib/uefi/edk2/parsers/dec_parser.py +++ b/edk2toollib/uefi/edk2/parsers/dec_parser.py @@ -8,6 +8,7 @@ """Code to help parse DEC files.""" import os import re +from typing import IO from edk2toollib.uefi.edk2.parsers.base_parser import HashFileParser from edk2toollib.uefi.edk2.parsers.guid_parser import GuidParser @@ -15,7 +16,7 @@ class LibraryClassDeclarationEntry(): """Object representing a Library Class Declaration Entry.""" - def __init__(self, packagename: str, rawtext: str = None): + def __init__(self, packagename: str, rawtext: str = None) -> None: """Init a library Class Declaration Entry.""" self.path = "" self.name = "" @@ -51,7 +52,7 @@ class GuidedDeclarationEntry(): PPI = 2 GUID = 3 - def __init__(self, packagename: str, rawtext: str = None): + def __init__(self, packagename: str, rawtext: str = None) -> None: """Init a protocol/Ppi/or Guid declaration entry.""" self.name = "" self.guidstring = "" @@ -76,7 +77,7 @@ def _parse(self, rawtext: str) -> None: class ProtocolDeclarationEntry(GuidedDeclarationEntry): """Object representing a Protocol Declaration Entry.""" - def __init__(self, packagename: str, rawtext: str = None): + def __init__(self, packagename: str, rawtext: str = None) -> None: """Init a protocol declaration entry.""" super().__init__(packagename, rawtext) self.type = GuidedDeclarationEntry.PROTOCOL @@ -84,7 +85,7 @@ def __init__(self, packagename: str, rawtext: str = None): class PpiDeclarationEntry(GuidedDeclarationEntry): """Object representing a Ppi Declaration Entry.""" - def __init__(self, packagename: str, rawtext: str = None): + def __init__(self, packagename: str, rawtext: str = None) -> None: """Init a Ppi declaration entry.""" super().__init__(packagename, rawtext) self.type = GuidedDeclarationEntry.PPI @@ -92,7 +93,7 @@ def __init__(self, packagename: str, rawtext: str = None): class GuidDeclarationEntry(GuidedDeclarationEntry): """Object representing a Guid Declaration Entry.""" - def __init__(self, packagename: str, rawtext: str = None): + def __init__(self, packagename: str, rawtext: str = None) -> None: """Init a Ppi declaration entry.""" super().__init__(packagename, rawtext) self.type = GuidedDeclarationEntry.GUID @@ -109,7 +110,7 @@ class PcdDeclarationEntry(): id (str): id package_name: package name """ - def __init__(self, packagename: str, rawtext: str = None): + def __init__(self, packagename: str, rawtext: str = None) -> None: """Creates a PCD Declaration Entry for one PCD.""" self.token_space_name = "" self.name = "" @@ -120,7 +121,7 @@ def __init__(self, packagename: str, rawtext: str = None): if (rawtext is not None): self._parse(rawtext) - def _parse(self, rawtext: str): + def _parse(self, rawtext: str) -> None: """Parses the PcdDeclaration Entry for one PCD.""" sp = rawtext.partition(".") self.token_space_name = sp[0].strip() @@ -165,7 +166,7 @@ class DecParser(HashFileParser): Path (str): path to the DEC file """ - def __init__(self): + def __init__(self) -> None: """Init an empty Dec Parser.""" HashFileParser.__init__(self, 'DecParser') self.Lines = [] @@ -285,7 +286,7 @@ def _Parse(self) -> None: self.Parsed = True - def ParseStream(self, stream) -> None: + def ParseStream(self, stream: IO) -> None: """Parse the supplied IO as a DEC file. Args: diff --git a/edk2toollib/uefi/edk2/parsers/dsc_parser.py b/edk2toollib/uefi/edk2/parsers/dsc_parser.py index 3d4c16590..d33a220f0 100644 --- a/edk2toollib/uefi/edk2/parsers/dsc_parser.py +++ b/edk2toollib/uefi/edk2/parsers/dsc_parser.py @@ -7,6 +7,7 @@ ## """Code to help parse DSC files.""" import os +from typing import Optional from edk2toollib.uefi.edk2.parsers.base_parser import HashFileParser @@ -25,7 +26,7 @@ class DscParser(HashFileParser): LibraryClassToInstanceDict (dict): Key (Library class) Value (Instance) Pcds (list): List of Pcds """ - def __init__(self): + def __init__(self) -> None: """Init an empty Parser.""" super(DscParser, self).__init__('DscParser') self.SixMods = [] @@ -41,7 +42,7 @@ def __init__(self): self._no_fail_mode = False self._dsc_file_paths = set() # This includes the full paths for every DSC that makes up the file - def __ParseLine(self, Line, file_name=None, lineno=None): + def __ParseLine(self, Line: str, file_name: Optional[str]=None, lineno: int=None) -> tuple: line_stripped = self.StripComment(Line).strip() if (len(line_stripped) < 1): return ("", [], None) @@ -178,7 +179,7 @@ def __ParseLine(self, Line, file_name=None, lineno=None): else: return (line_resolved, [], None) - def __ParseDefineLine(self, Line): + def __ParseDefineLine(self, Line: str) -> tuple: line_stripped = self.StripComment(Line).strip() if (len(line_stripped) < 1): return ("", []) @@ -240,7 +241,7 @@ def __ParseDefineLine(self, Line): else: return (line_resolved, []) - def ParseInfPathLib(self, line): + def ParseInfPathLib(self, line: str) -> str: """Parses a line with an INF path Lib.""" if (line.count("|") > 0): line_parts = [] @@ -255,11 +256,11 @@ def ParseInfPathLib(self, line): else: return line.strip().split()[0] - def ParseInfPathMod(self, line): + def ParseInfPathMod(self, line: str) -> str: """Parses a line with an INF path.""" return line.strip().split()[0].rstrip("{") - def __ProcessMore(self, lines, file_name=None): + def __ProcessMore(self, lines: list, file_name: Optional[str]=None) -> None: """Runs after ProcessDefines and does a full parsing of the DSC. Everything is resolved to a final state @@ -283,7 +284,7 @@ def __ProcessMore(self, lines, file_name=None): self.Logger.warning(f"DSC Parser (No-Fail Mode): {raw_line}") self.Logger.warning(e) - def __ProcessDefines(self, lines): + def __ProcessDefines(self, lines: list) -> None: """Goes through a file once to look for [Define] sections. Only Sections, DEFINE, X = Y, and !includes are resolved @@ -305,21 +306,21 @@ def __ProcessDefines(self, lines): if not self._no_fail_mode: raise - def SetNoFailMode(self, enabled=True): + def SetNoFailMode(self, enabled: bool=True) -> None: """The parser won't throw exceptions when this is turned on. WARNING: This can result in some weird behavior """ self._no_fail_mode = enabled - def ResetParserState(self): + def ResetParserState(self) -> None: """Resets the parser.""" # # add more DSC parser based state reset here, if necessary # super(DscParser, self).ResetParserState() - def ParseFile(self, filepath): + def ParseFile(self, filepath: str) -> None: """Parses the DSC file at the provided path.""" self.Logger.debug("Parsing file: %s" % filepath) sp = self.FindPath(filepath) @@ -337,27 +338,27 @@ def ParseFile(self, filepath): f.close() self.Parsed = True - def _PushTargetFile(self, targetFile): + def _PushTargetFile(self, targetFile: str) -> None: self.TargetFilePath = os.path.abspath(targetFile) self._dsc_file_paths.add(self.TargetFilePath) - def GetMods(self): + def GetMods(self) -> list: """Returns a list with all Mods.""" return self.ThreeMods + self.SixMods - def GetModsEnhanced(self): + def GetModsEnhanced(self) -> list: """Returns a list with all ModsEnhanced.""" return self.ThreeModsEnhanced + self.SixModsEnhanced - def GetLibs(self): + def GetLibs(self) -> list: """Returns a list with all Libs.""" return self.Libs - def GetLibsEnhanced(self): + def GetLibsEnhanced(self) -> list: """Returns a list with all LibsEnhanced.""" return self.LibsEnhanced - def GetAllDscPaths(self): + def GetAllDscPaths(self) -> set: """Returns a list with all the paths that this DSC uses (the base file and any includes). They are not all guaranteed to be DSC files diff --git a/edk2toollib/uefi/edk2/parsers/fdf_parser.py b/edk2toollib/uefi/edk2/parsers/fdf_parser.py index a7cbdc208..349691b28 100644 --- a/edk2toollib/uefi/edk2/parsers/fdf_parser.py +++ b/edk2toollib/uefi/edk2/parsers/fdf_parser.py @@ -25,7 +25,7 @@ class FdfParser(HashFileParser): Note: Dict Key Value pairs come from lines that contain a single =. """ - def __init__(self): + def __init__(self) -> None: """Inits an empty FDF parser.""" HashFileParser.__init__(self, 'ModuleFdfParser') self.Lines = [] @@ -36,7 +36,7 @@ def __init__(self): self.CurrentSection = [] self.Path = "" - def GetNextLine(self): + def GetNextLine(self) -> str: """Returns the next line to parse. Performs manipulation on the line like replacing variables, @@ -64,14 +64,14 @@ def GetNextLine(self): return sline - def InsertLinesFromFile(self, file_path: str): + def InsertLinesFromFile(self, file_path: str) -> None: """Adds additional lines to the Lines Attribute from the provided file.""" with open(file_path, 'r') as lines_file: self.Lines += reversed(lines_file.readlines()) # Back off the line count to ignore the include line itself. self.CurrentLine -= 1 - def ParseFile(self, filepath): + def ParseFile(self, filepath: str) -> None: """Parses the provided FDF file.""" self.Logger.debug("Parsing file: %s" % filepath) if (not os.path.isabs(filepath)): diff --git a/edk2toollib/uefi/edk2/parsers/guid_parser.py b/edk2toollib/uefi/edk2/parsers/guid_parser.py index 488531da3..031417a3e 100644 --- a/edk2toollib/uefi/edk2/parsers/guid_parser.py +++ b/edk2toollib/uefi/edk2/parsers/guid_parser.py @@ -40,7 +40,7 @@ class GuidParser(): GuidRegFormatRegEx = re.compile(r'{}'.format(_GuidPattern)) @classmethod - def is_guid_in_c_format(cls, guidstring: str) -> bool: + def is_guid_in_c_format(cls: 'GuidParser', guidstring: str) -> bool: """Determine if guidstring is in c format. Args: @@ -54,7 +54,7 @@ def is_guid_in_c_format(cls, guidstring: str) -> bool: return cls.GuidCFormatRegEx.match(guidstring) @classmethod - def is_guid_in_reg_format(cls, guidstring: str) -> bool: + def is_guid_in_reg_format(cls: 'GuidParser', guidstring: str) -> bool: """Determine if guidstring is in registry format. Args: @@ -67,7 +67,7 @@ def is_guid_in_reg_format(cls, guidstring: str) -> bool: return cls.GuidRegFormatRegEx.match(guidstring) @classmethod - def reg_guid_from_c_format(cls, guidstring: str) -> str: + def reg_guid_from_c_format(cls: 'GuidParser', guidstring: str) -> str: """Convert a c formatted guidstring to a registry formatted guidstring. Args: @@ -103,7 +103,7 @@ def reg_guid_from_c_format(cls, guidstring: str) -> str: return '' @classmethod - def c_guid_from_reg_format(cls, guidstring: str) -> str: + def c_guid_from_reg_format(cls: 'GuidParser', guidstring: str) -> str: """Convert registry format guidstring to c format guidstring. Args: @@ -128,7 +128,7 @@ def c_guid_from_reg_format(cls, guidstring: str) -> str: return Result @classmethod - def uuid_from_guidstring(cls, guidstring: str) -> uuid.UUID: + def uuid_from_guidstring(cls: 'GuidParser', guidstring: str) -> uuid.UUID: """Create a uuid object from the supplied guidstring.""" if (cls.is_guid_in_c_format(guidstring)): return uuid.UUID(cls.reg_guid_from_c_format(guidstring)) @@ -139,7 +139,7 @@ def uuid_from_guidstring(cls, guidstring: str) -> uuid.UUID: return None @classmethod - def c_guid_str_from_uuid(cls, guid: uuid.UUID) -> str: + def c_guid_str_from_uuid(cls: 'GuidParser', guid: uuid.UUID) -> str: """Get a C string formatted guidstring from a uuid object. Args: @@ -153,7 +153,7 @@ def c_guid_str_from_uuid(cls, guid: uuid.UUID) -> str: return cls.c_guid_from_reg_format(reg) @classmethod - def reg_guid_str_from_uuid(cls, guid: uuid.UUID) -> str: + def reg_guid_str_from_uuid(cls: 'GuidParser', guid: uuid.UUID) -> str: """Get a registry string formatted guidstring from a uuid object. Args: diff --git a/edk2toollib/uefi/edk2/parsers/inf_parser.py b/edk2toollib/uefi/edk2/parsers/inf_parser.py index 31f416dc8..ac1140a20 100644 --- a/edk2toollib/uefi/edk2/parsers/inf_parser.py +++ b/edk2toollib/uefi/edk2/parsers/inf_parser.py @@ -35,7 +35,7 @@ class InfParser(HashFileParser): NOTE: Key / Value pairs determined by lines that contain a single = """ - def __init__(self): + def __init__(self) -> None: """Inits an empty parser.""" HashFileParser.__init__(self, 'ModuleInfParser') self.Lines = [] @@ -53,7 +53,7 @@ def __init__(self): self.Binaries = [] self.Path = "" - def ParseFile(self, filepath): + def ParseFile(self, filepath: str) -> None: """Parses the INF file provided.""" self.Logger.debug("Parsing file: %s" % filepath) if (not os.path.isabs(filepath)): diff --git a/edk2toollib/uefi/edk2/parsers/override_parser.py b/edk2toollib/uefi/edk2/parsers/override_parser.py index f17e6167c..c1e88f61c 100644 --- a/edk2toollib/uefi/edk2/parsers/override_parser.py +++ b/edk2toollib/uefi/edk2/parsers/override_parser.py @@ -10,6 +10,7 @@ """Contains classes to help with parsing INF files that may contain OVERRIDE information.""" import datetime import os +from typing import Optional FORMAT_VERSION_1 = (1, 4) # Version 1: #OVERRIDE : VERSION | PATH_TO_MODULE | HASH | YYYY-MM-DDThh-mm-ss @@ -21,14 +22,14 @@ class OpParseError(Exception): PE_HASH = 'HASH' PE_DATE = 'DATE' - def __init__(self, my_type): + def __init__(self, my_type: str) -> None: """Verifies type is a valid OpParseError type.""" if my_type not in (OpParseError.PE_VER, OpParseError.PE_PATH, OpParseError.PE_HASH, OpParseError.PE_DATE): raise ValueError("Unknown type '%s'" % my_type) self.type = my_type - def __str__(self): + def __str__(self) -> str: """String representation of the OpParseError type.""" return repr(self.type) @@ -53,12 +54,12 @@ class OverrideParser(object): parsers. The pros and cons of this should also be weighed during any parser refactor. """ - def __init__(self, file_path=None, inf_contents=None): + def __init__(self, file_path: Optional[str]=None, inf_contents: Optional[str]=None) -> None: """Inits and parses either a file or already parsed contents. Args: - file_path (:obj:`PathLike`, optional): Path to an INF file - inf_contents (:obj:`str`, optional): Parsed lines as a string + file_path: Path to an INF file + inf_contents: Parsed lines as a string NOTE: Either file_path or inf_contents must be provided. """ @@ -100,7 +101,7 @@ def __init__(self, file_path=None, inf_contents=None): (pe, override_line['lineno'], override_line['line'])) @staticmethod - def get_override_lines(parse_contents): + def get_override_lines(parse_contents: str) -> list: """Parses contents and returns only lines that start with #OVERRIDE. Returns: @@ -116,7 +117,7 @@ def get_override_lines(parse_contents): return result @staticmethod - def parse_override_line(line_contents): + def parse_override_line(line_contents: str) -> dict: """Parses an override_line. Args: diff --git a/edk2toollib/uefi/edk2/parsers/targettxt_parser.py b/edk2toollib/uefi/edk2/parsers/targettxt_parser.py index 47b898112..a6058def7 100644 --- a/edk2toollib/uefi/edk2/parsers/targettxt_parser.py +++ b/edk2toollib/uefi/edk2/parsers/targettxt_parser.py @@ -20,7 +20,7 @@ class TargetTxtParser(HashFileParser): Dict (dict): Key / Value pair of all lines that contain a `=` in them (key=value) Path (str): path to Target.txt file """ - def __init__(self): + def __init__(self) -> None: """Inits an empty parser.""" HashFileParser.__init__(self, 'TargetTxtParser') self.Lines = [] @@ -28,7 +28,7 @@ def __init__(self): self.Dict = {} self.Path = "" - def ParseFile(self, filepath): + def ParseFile(self, filepath: str) -> None: """Parses the file provided.""" self.Logger.debug("Parsing file: %s" % filepath) if (not os.path.isabs(filepath)): diff --git a/edk2toollib/uefi/edk2/path_utilities.py b/edk2toollib/uefi/edk2/path_utilities.py index fe4d50045..190ecfd85 100644 --- a/edk2toollib/uefi/edk2/path_utilities.py +++ b/edk2toollib/uefi/edk2/path_utilities.py @@ -11,7 +11,7 @@ import logging import os from pathlib import Path -from typing import Iterable +from typing import Iterable, Optional class Edk2Path(object): @@ -36,8 +36,12 @@ class Edk2Path(object): """ - def __init__(self, ws: os.PathLike, package_path_list: Iterable[os.PathLike], - error_on_invalid_pp: bool = True): + def __init__( + self, + ws: os.PathLike, + package_path_list: Iterable[os.PathLike], + error_on_invalid_pp: bool = True + ) -> None: """Constructor. Args: @@ -171,17 +175,17 @@ def __init__(self, ws: os.PathLike, package_path_list: Iterable[os.PathLike], f"environment variable to \"true\" as a temporary workaround " f"until you fix the packages so they are no longer nested.") - def GetEdk2RelativePathFromAbsolutePath(self, abspath): + def GetEdk2RelativePathFromAbsolutePath(self, abspath: str) -> Optional[str]: """Given an absolute path return a edk2 path relative to workspace or packagespath. Note: absolute path must be in the OS specific path form Note: the relative path will be in POSIX-like path form Args: - abspath (os.PathLike): absolute path to a file or directory. Path must contain OS specific separator. + abspath: absolute path to a file or directory. Path must contain OS specific separator. Returns: - (os.PathLike): POSIX-like relative path to workspace or packagespath + (str): POSIX-like relative path to workspace or packagespath (None): abspath is none (None): path is not valid """ @@ -222,15 +226,19 @@ def GetEdk2RelativePathFromAbsolutePath(self, abspath): self.logger.error(f'AbsolutePath: {abspath}') return None - def GetAbsolutePathOnThisSystemFromEdk2RelativePath(self, relpath, log_errors=True): + def GetAbsolutePathOnThisSystemFromEdk2RelativePath( + self, + relpath: str, + log_errors: bool=True + ) -> Optional[str]: """Given a edk2 relative path return an absolute path to the file in this workspace. Args: - relpath (os.PathLike): POSIX-like path - log_errors (:obj:`bool`, optional): whether to log errors + relpath: POSIX-like path + log_errors: whether to log errors Returns: - (os.PathLike): absolute path in the OS specific form + (str): absolute path in the OS specific form (None): invalid relpath (None): Unable to get the absolute path """ @@ -319,7 +327,7 @@ def GetContainingModules(self, input_path: str) -> list[str]: will be returned in a list of file path strings. Args: - input_path (str): Absolute path to a file, directory, or module. + input_path: Absolute path to a file, directory, or module. Supports both Windows and Linux like paths. Returns: diff --git a/edk2toollib/uefi/edk2/variable_format.py b/edk2toollib/uefi/edk2/variable_format.py index 917576ea6..618713e7a 100644 --- a/edk2toollib/uefi/edk2/variable_format.py +++ b/edk2toollib/uefi/edk2/variable_format.py @@ -9,6 +9,7 @@ import struct import sys import uuid +from typing import Self import edk2toollib.uefi.uefi_multi_phase as ump @@ -45,7 +46,7 @@ class VariableStoreHeader(object): UINT32 Reserved1; } VARIABLE_STORE_HEADER; """ - def __init__(self): + def __init__(self) -> None: """Init the empty structure.""" self.StructString = "=16sLBBHL" # spell-checker: disable-line self.StructSize = struct.calcsize(self.StructString) @@ -57,7 +58,7 @@ def __init__(self): self.Reserved1 = None self.Type = 'Var' - def load_from_file(self, file): + def load_from_file(self, file: str) -> Self: """Load the structure from a file.""" # This function assumes that the file has been seeked # to the correct starting location. @@ -83,7 +84,7 @@ def load_from_file(self, file): return self - def serialize(self): + def serialize(self) -> bytes: """Serialize the structure.""" signature_bin = self.Signature.bytes if sys.byteorder == 'big' else self.Signature.bytes_le return struct.pack(self.StructString, signature_bin, self.Size, self.Format, @@ -110,7 +111,7 @@ class VariableHeader(object): EFI_GUID VendorGuid; } VARIABLE_HEADER; """ - def __init__(self): + def __init__(self) -> None: """Init the structure.""" self.StructString = "=HBBLLL16s" # spell-checker: disable-line self.StructSize = struct.calcsize(self.StructString) @@ -123,12 +124,12 @@ def __init__(self): self.Name = None self.Data = None - def populate_structure_fields(self, in_bytes): + def populate_structure_fields(self, in_bytes: bytes) -> None: """Populate the structure field from bytes.""" (self.StartId, self.State, reserved, self.Attributes, self.NameSize, self.DataSize, self.VendorGuid) = struct.unpack(self.StructString, in_bytes) - def load_from_bytes(self, in_bytes): + def load_from_bytes(self, in_bytes: bytes) -> Self: """Load the structure from a bytes.""" # Load this object with the contents of the data. self.populate_structure_fields(in_bytes[0:self.StructSize]) @@ -152,7 +153,7 @@ def load_from_bytes(self, in_bytes): return self - def load_from_file(self, file): + def load_from_file(self, file: str) -> Self: """Load the struct from a file.""" # This function assumes that the file has been seeked # to the correct starting location. @@ -180,11 +181,11 @@ def load_from_file(self, file): file.seek(orig_seek) return self - def get_buffer_data_size(self): + def get_buffer_data_size(self) -> int: """Get the buffer data size.""" return self.StructSize + self.NameSize + self.DataSize - def get_buffer_padding_size(self): + def get_buffer_padding_size(self) -> int: """Get the buffer padding size.""" buffer_data_size = self.get_buffer_data_size() padding_size = 0 @@ -192,11 +193,11 @@ def get_buffer_padding_size(self): padding_size += HEADER_ALIGNMENT - (buffer_data_size % HEADER_ALIGNMENT) return padding_size - def get_buffer_size(self): + def get_buffer_size(self) -> int: """Get the buffer size.""" return self.get_buffer_data_size() + self.get_buffer_padding_size() - def get_packed_name(self): + def get_packed_name(self) -> bytes: """Get the name attribute.""" # Make sure to replace the terminating char. # name_bytes = b"\x00".join([char for char in (self.Name + b'\x00')]) @@ -211,23 +212,23 @@ def get_packed_name(self): return name_bytes - def set_name(self, new_name): + def set_name(self, new_name: str) -> None: """Set the name attribute.""" self.Name = new_name self.NameSize = len(self.get_packed_name()) - def set_data(self, new_data): + def set_data(self, new_data: bytes) -> None: """Set the data attribute.""" self.Data = new_data self.DataSize = len(new_data) - def pack_struct(self): + def pack_struct(self) -> bytes: """Pack the object.""" vendor_guid = self.VendorGuid.bytes if sys.byteorder == 'big' else self.VendorGuid.bytes_le return struct.pack(self.StructString, self.StartId, self.State, 0, self.Attributes, self.NameSize, self.DataSize, vendor_guid) - def serialize(self, with_padding=False): + def serialize(self, with_padding: bool=False) -> bytes: """Serialize the object.""" bytes = self.pack_struct() @@ -260,7 +261,7 @@ class AuthenticatedVariableHeader(VariableHeader): EFI_GUID VendorGuid; } AUTHENTICATED_VARIABLE_HEADER; """ - def __init__(self): + def __init__(self) -> None: """Initializes the struct.""" super(AuthenticatedVariableHeader, self).__init__() self.StructString = "=HBBLQ16sLLL16s" # spell-checker: disable-line @@ -269,12 +270,12 @@ def __init__(self): self.TimeStamp = b'' self.PubKeyIndex = 0 - def populate_structure_fields(self, in_bytes): + def populate_structure_fields(self, in_bytes: bytes) -> None: """Populates the struct.""" (self.StartId, self.State, reserved, self.Attributes, self.MonotonicCount, self.TimeStamp, self.PubKeyIndex, self.NameSize, self.DataSize, self.VendorGuid) = struct.unpack(self.StructString, in_bytes) - def pack_struct(self, with_padding=False): + def pack_struct(self, with_padding: bool=False) -> bytes: """Packs the struct.""" vendor_guid = self.VendorGuid.bytes if sys.byteorder == 'big' else self.VendorGuid.bytes_le return struct.pack(self.StructString, self.StartId, self.State, 0, self.Attributes, self.MonotonicCount, diff --git a/edk2toollib/uefi/edk2/variable_policy.py b/edk2toollib/uefi/edk2/variable_policy.py index 7d938dee3..daaf047cc 100644 --- a/edk2toollib/uefi/edk2/variable_policy.py +++ b/edk2toollib/uefi/edk2/variable_policy.py @@ -9,6 +9,7 @@ """Module containing helper classes and functions to work with Variable Policy structures and substructures.""" import struct import uuid +from typing import IO from edk2toollib.uefi.uefi_multi_phase import EfiVariableAttributes @@ -26,17 +27,17 @@ class VariableLockOnVarStatePolicy(object): _HdrStructFormat = "<16sBB" _HdrStructSize = struct.calcsize(_HdrStructFormat) - def __init__(self): + def __init__(self) -> None: """Initializes the Variable Lock On Var State Policy.""" self.Namespace = uuid.UUID(bytes=b'\x00' * 16) self.Value = 0 self.Name = None - def __str__(self): + def __str__(self) -> str: """String representation of the object.""" return "VARIABLE_LOCK_ON_VAR_STATE_POLICY(%s, %d, %s)" % (self.Namespace, self.Value, self.Name) - def decode(self, buffer): + def decode(self, buffer: IO) -> bytes: """Load this object from a bytes buffer. Returns: @@ -107,7 +108,7 @@ class VariablePolicyEntry(object): TYPE_LOCK_ON_VAR_STATE: "ON_VAR_STATE", } - def __init__(self): + def __init__(self) -> None: """Initializes the Variable Policy Entry.""" self.Version = VariablePolicyEntry.ENTRY_REVISION self.Size = VariablePolicyEntry._HdrStructSize @@ -121,7 +122,7 @@ def __init__(self): self.LockPolicy = None self.Name = None - def __str__(self): + def __str__(self) -> str: """String representation of the object.""" result = "VARIABLE_POLICY_ENTRY(%s, %s)\n" % (self.Namespace, self.Name) @@ -138,12 +139,12 @@ def __str__(self): return result @staticmethod - def csv_header(): + def csv_header() -> list: """Returns a list containing the names of the ordered columns that are produced by csv_row().""" return ['Namespace', 'Name', 'LockPolicyType', 'VarStateNamespace', 'VarStateName', 'VarStateValue', 'MinSize', 'MaxSize', 'AttributesMustHave', 'AttributesCantHave'] - def csv_row(self, guid_xref: dict = None): + def csv_row(self, guid_xref: dict = None) -> list: """Returns a list containing the elements of this structure. (in the same order as the csv_header) ready to be written to a csv file @@ -172,11 +173,11 @@ def csv_row(self, guid_xref: dict = None): return result - def decode(self, buffer): + def decode(self, buffer: IO) -> bytes: """Load this object from a bytes buffer. Returns: - (obj): Any remaining buffer + (bytes): Any remaining buffer """ (self.Version, self.Size, self.OffsetToName, _namespace, self.MinSize, self.MaxSize, self.AttributesMustHave, diff --git a/edk2toollib/uefi/edk2/variablestore_manulipulations.py b/edk2toollib/uefi/edk2/variablestore_manulipulations.py index a33647f0b..6b2814da2 100644 --- a/edk2toollib/uefi/edk2/variablestore_manulipulations.py +++ b/edk2toollib/uefi/edk2/variablestore_manulipulations.py @@ -8,6 +8,7 @@ """Contains classes and helper functions to modify variables in a UEFI ROM image.""" import mmap import os +from typing import Optional import edk2toollib.uefi.edk2.variable_format as VF import edk2toollib.uefi.pi_firmware_volume as PiFV @@ -15,7 +16,7 @@ class VariableStore(object): """Class representing the variable store.""" - def __init__(self, romfile, store_base=None, store_size=None): + def __init__(self, romfile: str, store_base: Optional[int]=None, store_size: Optional[int]=None) -> None: """Initialize the Variable store and read necessary files. Loads the data. @@ -72,7 +73,7 @@ def __init__(self, romfile, store_base=None, store_size=None): # Finally, reset the file cursor to the beginning of the VarStore FV. self.rom_file.seek(self.store_base) - def __del__(self): + def __del__(self) -> None: """Flushes and closes files.""" if self.rom_file_map is not None: self.rom_file_map.flush() @@ -81,7 +82,7 @@ def __del__(self): if self.rom_file is not None: self.rom_file.close() - def get_new_var_class(self): + def get_new_var_class(self) -> VF.VariableHeader | VF.AuthenticatedVariableHeader: """Var class builder method depending on var type.""" if self.var_store_header.Type == 'Var': new_var = VF.VariableHeader() @@ -90,11 +91,11 @@ def get_new_var_class(self): return new_var - def add_variable(self, new_var): + def add_variable(self, new_var: VF.VariableHeader | VF.AuthenticatedVariableHeader) -> None: """Add a variable to the variable list.""" self.variables.append(new_var) - def flush_to_file(self): + def flush_to_file(self) -> None: """Flush the changes to file.""" # First, we need to make sure that our variables will fit in the VarStore. var_size = sum([var.get_buffer_size() for var in self.variables]) diff --git a/edk2toollib/uefi/fmp_auth_header.py b/edk2toollib/uefi/fmp_auth_header.py index 599bf8eb4..602fc40d1 100644 --- a/edk2toollib/uefi/fmp_auth_header.py +++ b/edk2toollib/uefi/fmp_auth_header.py @@ -10,6 +10,7 @@ """Module for encoding and decoding EFI_FIRMWARE_IMAGE_AUTHENTICATION with certificate data and payload data.""" import struct +from typing import IO from edk2toollib.uefi.edk2.fmp_payload_header import FmpPayloadHeaderClass from edk2toollib.uefi.wincert import WinCertUefiGuid @@ -37,18 +38,18 @@ class FmpAuthHeaderClass (object): _MonotonicCountFormat = ' None: """Inits an empty object.""" self.MonotonicCount = 0 self.AuthInfo = WinCertUefiGuid() self.Payload = b'' self.FmpPayloadHeader = None - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the Auth header + AuthInfo + Payload/FmpPayloadHeader. Returns: - (str): string representing packed data as bytes (i.e. b'\x01\x00\x03') + (bytes): string representing packed data as bytes (i.e. b'\x01\x00\x03') """ FmpAuthHeader = struct.pack( self._MonotonicCountFormat, @@ -60,7 +61,7 @@ def Encode(self): else: return FmpAuthHeader + self.AuthInfo.Encode() + self.Payload - def Decode(self, Buffer): + def Decode(self, Buffer: IO) -> bytes: """Loads data into the Object by parsing a buffer. Args: @@ -86,7 +87,7 @@ def Decode(self, Buffer): self.FmpPayloadHeader.Decode(self.Payload) return self.Payload - def IsSigned(self, Buffer): + def IsSigned(self, Buffer: IO) -> bool: """Parses the buffer and returns if the Cert is signed or not. Returns: @@ -102,7 +103,7 @@ def IsSigned(self, Buffer): return False return True - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints object to console.""" print('EFI_FIRMWARE_IMAGE_AUTHENTICATION.MonotonicCount = {MonotonicCount:016X}' .format(MonotonicCount=self.MonotonicCount)) diff --git a/edk2toollib/uefi/fmp_capsule_header.py b/edk2toollib/uefi/fmp_capsule_header.py index 1ffe6403b..2d049b234 100644 --- a/edk2toollib/uefi/fmp_capsule_header.py +++ b/edk2toollib/uefi/fmp_capsule_header.py @@ -10,6 +10,7 @@ import struct import uuid +from typing import IO from edk2toollib.uefi.fmp_auth_header import FmpAuthHeaderClass @@ -51,7 +52,7 @@ class FmpCapsuleImageHeaderClass (object): EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000002 - def __init__(self): + def __init__(self) -> None: """Inits an empty object.""" self.Version = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION self.UpdateImageTypeId = uuid.UUID('00000000-0000-0000-0000-000000000000') @@ -63,7 +64,7 @@ def __init__(self): self.VendorCodeBytes = b'' self.FmpAuthHeader = None - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -87,14 +88,14 @@ def Encode(self): ) return FmpCapsuleImageHeader + self.Payload + self.VendorCodeBytes - def Decode(self, Buffer): + def Decode(self, Buffer: IO) -> bytes: """Loads data into the object from a filestream. Args: - Buffer (obj): Buffer containing data + Buffer: Buffer containing data Returns: - (obj): remaining buffer + bytes: remaining buffer Raises: (ValueError): Invalid buffer length @@ -128,7 +129,7 @@ def Decode(self, Buffer): self.VendorCodeBytes = Buffer[self._StructSize + UpdateImageSize:] return Buffer[self._StructSize:] - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints object to Console.""" print('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.Version = {Version:08X}' .format(Version=self.Version)) @@ -180,7 +181,7 @@ class FmpCapsuleHeaderClass (object): EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION = 0x00000001 - def __init__(self): + def __init__(self) -> None: """Inits an empty object.""" self.Version = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION self.EmbeddedDriverCount = 0 @@ -188,25 +189,25 @@ def __init__(self): self._EmbeddedDriverList = [] self._FmpCapsuleImageHeaderList = [] - def AddEmbeddedDriver(self, EmbeddedDriver): + def AddEmbeddedDriver(self, EmbeddedDriver: bytes) -> None: """Adds an embedded driver to the list.""" self._EmbeddedDriverList.append(EmbeddedDriver) self.EmbeddedDriverCount += 1 - def GetEmbeddedDriver(self, Index): + def GetEmbeddedDriver(self, Index: int) -> bytes: """Returns the embedded driver at the index.""" return self._EmbeddedDriverList[Index] - def AddFmpCapsuleImageHeader(self, FmpCapsuleHeader): + def AddFmpCapsuleImageHeader(self, FmpCapsuleHeader: 'FmpCapsuleImageHeaderClass') -> None: """Adds an Fmp Capsule Image header to the list.""" self._FmpCapsuleImageHeaderList.append(FmpCapsuleHeader) self.PayloadItemCount += 1 - def GetFmpCapsuleImageHeader(self, Index): + def GetFmpCapsuleImageHeader(self, Index: int) -> 'FmpCapsuleImageHeaderClass': """Returns the Fmp Capsule Image header at the index.""" return self._FmpCapsuleImageHeaderList[Index] - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the object. Returns: @@ -240,7 +241,7 @@ def Encode(self): return FmpCapsuleHeader + FmpCapsuleData - def Decode(self, Buffer): + def Decode(self, Buffer: IO) -> bytes: """Loads data into the object from a Buffer. Args: @@ -308,7 +309,7 @@ def Decode(self, Buffer): return Result - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints the object to the console.""" print('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.Version = {Version:08X}'.format(Version=self.Version)) print('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.EmbeddedDriverCount = {EmbeddedDriverCount:08X}'.format( diff --git a/edk2toollib/uefi/pi_firmware_file.py b/edk2toollib/uefi/pi_firmware_file.py index 0aea07df4..5c2c49ec0 100644 --- a/edk2toollib/uefi/pi_firmware_file.py +++ b/edk2toollib/uefi/pi_firmware_file.py @@ -9,6 +9,7 @@ import struct import sys import uuid +from typing import IO, Self class EfiFirmwareFileSystemHeader(object): @@ -27,7 +28,7 @@ class EfiFirmwareFileSystemHeader(object): } EFI_FFS_FILE_HEADER; ``` """ - def __init__(self): + def __init__(self) -> None: """Inits an empty object.""" self.StructString = "=16sHBBBBBB" # spell-checker: disable-line self.FileSystemGuid = None @@ -38,11 +39,11 @@ def __init__(self): self.Type = None self.State = None - def get_size(self): + def get_size(self) -> int: """Returns the size of the header.""" return self.Size0 + (self.Size1 << 8) + (self.Size2 << 16) - def load_from_file(self, file): + def load_from_file(self, file: IO) -> Self: """Loads data into the object from a filestream. Args: @@ -67,11 +68,11 @@ def load_from_file(self, file): return self - def serialize(self): + def serialize(self) -> bytes: r"""Serializes the object. Returns: - (str): string representing packed data as bytes (i.e. b'\x01\x00\x03') + (bytes): string representing packed data as bytes (i.e. b'\x01\x00\x03') """ file_system_guid_bin = self.FileSystemGuid.bytes if sys.byteorder == 'big' else self.FileSystemGuid.bytes_le return struct.pack(self.StructString, file_system_guid_bin, self.Checksum, diff --git a/edk2toollib/uefi/pi_firmware_volume.py b/edk2toollib/uefi/pi_firmware_volume.py index 4fd6fcf5d..2c1eeef8f 100644 --- a/edk2toollib/uefi/pi_firmware_volume.py +++ b/edk2toollib/uefi/pi_firmware_volume.py @@ -11,6 +11,7 @@ import struct import sys import uuid +from typing import IO # # UEFI GUIDs @@ -45,7 +46,7 @@ class EfiFirmwareVolumeHeader(object): } EFI_FIRMWARE_VOLUME_HEADER; ``` """ - def __init__(self): + def __init__(self) -> None: """Inits an empty object.""" self.StructString = "=16s16sQ4sLHHHBBQQ" # spell-checker: disable-line self.ZeroVector = None @@ -60,7 +61,7 @@ def __init__(self): self.Blockmap0 = None self.Blockmap1 = None - def load_from_file(self, file): + def load_from_file(self, file: IO) -> 'EfiFirmwareVolumeHeader': """Loads data into the object from a filestream. Args: @@ -95,7 +96,7 @@ def load_from_file(self, file): return self - def serialize(self): + def serialize(self) -> bytes: r"""Serializes the object. Returns: @@ -119,17 +120,17 @@ class EfiFirmwareVolumeExtHeader(object): } EFI_FIRMWARE_VOLUME_EXT_HEADER; ``` """ - def __init__(self): + def __init__(self) -> None: """Inits an empty object.""" self.StructString = "=16sL" self.FileSystemGuid = None self.ExtHeaderSize = None - def load_from_file(self, file): + def load_from_file(self, file: IO) -> 'EfiFirmwareVolumeExtHeader': """Loads data into the object from a filestream. Args: - file (obj): An open file that has been seeked to the correct location. + file: An open file that has been seeked to the correct location. Returns: (EfiFirmwareVolumeExtHeader): self diff --git a/edk2toollib/uefi/status_codes.py b/edk2toollib/uefi/status_codes.py index b787e6573..176ed8365 100644 --- a/edk2toollib/uefi/status_codes.py +++ b/edk2toollib/uefi/status_codes.py @@ -56,7 +56,7 @@ def ConvertHexString64ToString(self, hexstring: str) -> str: value = int(hexstring, 16) return self.Convert64BitToString(value) - def ConvertHexString32ToString(self, hexstring): + def ConvertHexString32ToString(self, hexstring: str) -> str: """Convert 32 bit hexstring in 0x format to a UEFI status code.""" value = int(hexstring, 16) return self.Convert32BitToString(value) diff --git a/edk2toollib/uefi/uefi_capsule_header.py b/edk2toollib/uefi/uefi_capsule_header.py index a4ea70d6d..77a5bb80f 100644 --- a/edk2toollib/uefi/uefi_capsule_header.py +++ b/edk2toollib/uefi/uefi_capsule_header.py @@ -8,6 +8,7 @@ import struct import uuid +from io import BytesIO from edk2toollib.uefi.fmp_capsule_header import FmpCapsuleHeaderClass @@ -25,7 +26,7 @@ class UefiCapsuleHeaderClass (object): PersistAcrossReset (bool): Flag pulled from OemFlags PopulateSystemTable (bool): Flag pulled from OemFlags InitiateReset (bool): Flag pulled from OemFlags - Payload (str): string representing packed data as bytes (i.e. b'\x01\x00\x03') + Payload (bytes): string representing packed data as bytes (i.e. b'\x01\x00\x03') FmpCapsuleHeader (FmpCapsuleHeaderClass): Fmp Capsule Header ``` @@ -50,7 +51,7 @@ class UefiCapsuleHeaderClass (object): _CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE = 0x00020000 _CAPSULE_FLAGS_INITIATE_RESET = 0x00040000 - def __init__(self): + def __init__(self) -> None: """Inits an empty object.""" self.CapsuleGuid = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID self.HeaderSize = self._StructSize @@ -62,11 +63,11 @@ def __init__(self): self.Payload = b'' self.FmpCapsuleHeader = None - def Encode(self): + def Encode(self) -> bytes: r"""Serializes the Header + payload. Returns: - (str): string representing packed data as bytes (i.e. b'\x01\x00\x03') + (bytes): string representing packed data as bytes (i.e. b'\x01\x00\x03') """ Flags = self.OemFlags if self.PersistAcrossReset: @@ -93,7 +94,7 @@ def Encode(self): return UefiCapsuleHeader + self.Payload - def Decode(self, Buffer): + def Decode(self, Buffer: BytesIO) -> bytes: """Loads data into the Object by parsing a buffer. Args: @@ -131,7 +132,7 @@ def Decode(self, Buffer): return self.Payload - def DumpInfo(self): + def DumpInfo(self) -> None: """Prints payload header information.""" Flags = self.OemFlags if self.PersistAcrossReset: diff --git a/edk2toollib/uefi/uefi_multi_phase.py b/edk2toollib/uefi/uefi_multi_phase.py index 524865d18..a3479c9f2 100644 --- a/edk2toollib/uefi/uefi_multi_phase.py +++ b/edk2toollib/uefi/uefi_multi_phase.py @@ -9,6 +9,7 @@ """Module for working with UEFI Authenticated Variable Atrributes.""" import struct +from typing import IO EFI_VARIABLE_NON_VOLATILE = 0x00000001 EFI_VARIABLE_BOOTSERVICE_ACCESS = 0x00000002 @@ -47,7 +48,7 @@ class EfiVariableAttributes(object): } INVERSE_STRING_MAP = {v: k for k, v in STRING_MAP.items()} - def __init__(self, attributes=0x0000_0000, decodefs=None) -> None: + def __init__(self, attributes: int | str=0x0000_0000, decodefs: IO=None) -> None: """Creates a EfiVariableAttributes object. Args: @@ -62,11 +63,11 @@ def __init__(self, attributes=0x0000_0000, decodefs=None) -> None: else: self.update(attributes) - def update(self, attributes: 0x0000_00000) -> None: + def update(self, attributes: int | str = 0x0000_00000) -> None: """Updates instance to provided attributes. Args: - attributes (int | str): attributes to parse + attributes: attributes to parse Returns: None @@ -83,11 +84,11 @@ def update(self, attributes: 0x0000_00000) -> None: f"Invalid type: {type(attributes)}") @staticmethod - def parse_attributes_str(attributes_str) -> int: + def parse_attributes_str(attributes_str: str) -> int: """Converts attributes string into integer representation. Args: - attributes_str (str): string containing attributes that have been comma delimated. + attributes_str: string containing attributes that have been comma delimated. Examples: ```python @@ -130,7 +131,7 @@ def parse_attributes_str(attributes_str) -> int: return attributes - def decode(self, fs) -> int: + def decode(self, fs: IO) -> int: """Reads in attributes from a file stream. This updates the attributes value of the object @@ -154,7 +155,7 @@ def decode(self, fs) -> int: return attributes - def encode(self) -> bytes: + def encode(self,) -> bytes: """Returns the attributes as a packed structure. !!! Examples @@ -171,7 +172,7 @@ def encode(self) -> bytes: """ return struct.pack(EfiVariableAttributes._struct_format, self.attributes) - def get_short_string(self) -> str: + def get_short_string(self,) -> str: """Short form string representation of the attributes. !!! Examples @@ -190,7 +191,7 @@ def get_short_string(self) -> str: result.append(EfiVariableAttributes.SHORT_STRING_MAP[key]) return ",".join(result) - def __str__(self) -> str: + def __str__(self,) -> str: """String representation of the attributes. Returns: @@ -202,6 +203,6 @@ def __str__(self) -> str: result.append(EfiVariableAttributes.STRING_MAP[key]) return ",".join(result) - def __int__(self): + def __int__(self,) -> int: """Returns attributes as an int.""" return self.attributes diff --git a/edk2toollib/uefi/wincert.py b/edk2toollib/uefi/wincert.py index 0bb79797f..cf5a44068 100644 --- a/edk2toollib/uefi/wincert.py +++ b/edk2toollib/uefi/wincert.py @@ -13,6 +13,8 @@ import struct import sys import uuid +from io import BytesIO, StringIO +from typing import Optional from warnings import warn from pyasn1.codec.der.decoder import decode as der_decode @@ -56,7 +58,7 @@ class WinCertPkcs1(object): STATIC_STRUCT_SIZE = (4 + 2 + 2 + 16) EFI_HASH_SHA256 = uuid.UUID("{51AA59DE-FDF2-4EA3-BC63-875FB7842EE9}") # EFI_HASH_SHA256 guid defined by UEFI spec - def __init__(self, filestream=None): + def __init__(self, filestream: Optional[BytesIO]=None) -> None: """Inits the object.""" if filestream is None: self.Hdr_dwLength = WinCertPkcs1.STATIC_STRUCT_SIZE @@ -68,30 +70,30 @@ def __init__(self, filestream=None): self.decode(filestream) @property - def HashAlgorithm(self): + def HashAlgorithm(self) -> uuid.UUID: """Returns the HashAlgorithm.""" warn("HashAlgorithm is deprecated. Use hash_algorithm instead.", DeprecationWarning, 2) return self.hash_algorithm @HashAlgorithm.setter - def HashAlgorithm(self, value): + def HashAlgorithm(self, value: uuid.UUID) -> None: """Sets the HashAlgorithm.""" warn("HashAlgorithm is deprecated. Use hash_algorithm instead.", DeprecationWarning, 2) self.hash_algorithm = value @property - def CertData(self): + def CertData(self) -> bytes: """Returns the CertData.""" warn("CertData is deprecated. Use cert_data instead.", DeprecationWarning, 2) return self.cert_data @CertData.setter - def CertData(self, value): + def CertData(self, value: bytes) -> None: """Sets the CertData.""" warn("CertData is deprecated. Use cert_data instead.", DeprecationWarning, 2) self.cert_data = value - def add_cert_data(self, fs): + def add_cert_data(self, fs: BytesIO) -> None: """Adds the Cert Data to the struct. Args: @@ -110,7 +112,7 @@ def add_cert_data(self, fs): self.cert_data = memoryview(fs.read()) self.Hdr_dwLength = self.Hdr_dwLength + len(self.cert_data) - def AddCertData(self, fs): + def AddCertData(self, fs: BytesIO) -> None: """Adds the Cert Data to the struct. Raises: @@ -120,7 +122,7 @@ def AddCertData(self, fs): warn("AddCertData is deprecated, use add_cert_data instead", DeprecationWarning, 2) self.add_cert_data(fs) - def set_hash_algorithm(self, hash_algorithm: uuid.UUID): + def set_hash_algorithm(self, hash_algorithm: uuid.UUID) -> None: """Sets the hash algorithm for the wincert. Args: @@ -128,11 +130,11 @@ def set_hash_algorithm(self, hash_algorithm: uuid.UUID): """ self.hash_algorithm = hash_algorithm - def decode(self, fs): + def decode(self, fs: BytesIO) -> None: """Populates the struct from a filestream. Args: - fs (obj): An open file + fs: An open file Raises: (ValueError): Invalid stream @@ -164,11 +166,11 @@ def decode(self, fs): self.cert_data = memoryview(fs.read(self.Hdr_dwLength - WinCertPkcs1.STATIC_STRUCT_SIZE)) - def PopulateFromFileStream(self, fs): + def PopulateFromFileStream(self, fs: BytesIO) -> None: """Populates the struct from a filestream. Args: - fs (obj): an open file + fs: an open file Raises: (ValueError): Invalid stream @@ -177,7 +179,7 @@ def PopulateFromFileStream(self, fs): warn("PopulateFromFileStream is deprecated, use decode instead", DeprecationWarning, 2) return self.decode(fs) - def print(self, out_fs=sys.stdout): + def print(self, out_fs: Optional[BytesIO]=sys.stdout) -> None: """Prints the struct to the console.""" out_fs.write("\n-------------------- WinCertPKCS115 ---------------------\n") out_fs.write(f" Hdr_dwLength: 0x{self.Hdr_dwLength:0X}\n") @@ -188,16 +190,16 @@ def print(self, out_fs=sys.stdout): cdl = self.cert_data.tolist() hexdump(cdl, out_fs=out_fs) - def Print(self, out_fs=sys.stdout): + def Print(self, out_fs: Optional[BytesIO]=sys.stdout) -> None: """Prints the struct to the console.""" warn("Print is deprecated, use print instead", DeprecationWarning, 2) self.print(out_fs) - def encode(self): + def encode(self) -> bytes: r"""Serializes the object. Returns: - (str): string representing packed data as bytes (i.e. b'\x01\x00\x03') + (bytes): string representing packed data as bytes (i.e. b'\x01\x00\x03') """ output = b"" output += struct.pack("=I", self.Hdr_dwLength) @@ -208,25 +210,20 @@ def encode(self): return output - def write(self, fs): + def write(self, fs: BytesIO) -> None: r"""Writes an serialized object to a filestream. Args: fs (obj): an open file - Returns: - (str): string representing packed data as bytes (i.e. b'\x01\x00\x03') """ fs.write(self.encode()) - def Write(self, fs): + def Write(self, fs: BytesIO) -> None: r"""Serializes the object. Args: - fs (obj): an open file - - Returns: - (str): string representing packed data as bytes (i.e. b'\x01\x00\x03') + fs: an open file """ warn("Write is deprecated, use encode instead", DeprecationWarning, 2) self.write(fs) @@ -267,7 +264,7 @@ class WinCertUefiGuid(object): STATIC_STRUCT_SIZE = _StructSize PKCS7Guid = _EFI_CERT_TYPE_PKCS7_GUID - def __init__(self, in_data=None): + def __init__(self, in_data: Optional[BytesIO]=None) -> None: """Inits the object.""" self.Hdr_dwLength = self._StructSize self.Hdr_wRevision = WinCert.REVISION @@ -279,34 +276,34 @@ def __init__(self, in_data=None): self.decode(in_data) @property - def CertData(self): + def CertData(self) -> uuid.UUID: """Returns the CertData.""" warn("CertData is deprecated. Use cert_data instead.", DeprecationWarning, 2) return self.cert_data @CertData.setter - def CertData(self, value): + def CertData(self, value: uuid.UUID) -> None: """Sets the CertData.""" warn("CertData is deprecated. Use cert_data instead.", DeprecationWarning, 2) self.cert_data = value @property - def CertType(self): + def CertType(self) -> uuid.UUID: """Returns the CertType.""" warn("CertType is deprecated. Use cert_type instead.", DeprecationWarning, 2) return self.cert_type @CertType.setter - def CertType(self, value): + def CertType(self, value: uuid.UUID) -> None: """Sets the CertType.""" warn("CertType is deprecated. Use cert_type instead.", DeprecationWarning, 2) self.cert_type = value - def get_length(self): + def get_length(self) -> int: """Returns the length of the WinCertUefiGuid and it's data.""" return self.Hdr_dwLength - def Encode(self): + def Encode(self) -> str: r"""Serializes the object. Returns: @@ -319,7 +316,7 @@ def Encode(self): warn("Encode is deprecated, use encode instead", DeprecationWarning, 2) return self.encode() - def encode(self): + def encode(self) -> str: r"""Serializes the object. Returns: @@ -347,14 +344,14 @@ def encode(self): return win_cert_header + self.cert_data - def Decode(self, Buffer): + def Decode(self, Buffer: BytesIO) -> bytes: """Loads the struct with values from a buffer. Args: - Buffer (filestream | bytes): Buffer containing serialized data + Buffer: Buffer containing serialized data Returns: - (obj): Any remaining buffer + (bytes): Any remaining buffer Raises: (ValueError): Invalid Buffer @@ -365,14 +362,14 @@ def Decode(self, Buffer): warn("Decode is deprecated, use decode instead", DeprecationWarning, 2) return self.decode(Buffer) - def decode(self, in_data): + def decode(self, in_data: BytesIO) -> bytes: """Loads the struct with values from a buffer. Args: - in_data (filestream | bytes): in_data containing serialized data + in_data: in_data containing serialized data Returns: - (obj): Any remaining buffer + (bytes): Any remaining buffer Raises: (ValueError): Invalid Buffer @@ -390,14 +387,14 @@ def decode(self, in_data): raise ValueError( f"Invalid datatype provided: {type(in_data)}, data may only be of type filestream or bytes") - def _from_buffer(self, buffer): + def _from_buffer(self, buffer: BytesIO) -> bytes: """Loads the struct with values from a buffer. Args: - buffer (obj): Buffer containing serialized data + buffer: Buffer containing serialized data Returns: - (obj): Any remaining buffer + (BytesIO): Any remaining buffer Raises: (ValueError): Invalid buffer @@ -428,7 +425,7 @@ def _from_buffer(self, buffer): # Return the remaining buffer, if any exists. return buffer[self.Hdr_dwLength:] - def _from_filestream(self, fs): + def _from_filestream(self, fs: StringIO) -> bytes: """Un-serialized from a filestream. Args: @@ -463,7 +460,7 @@ def _from_filestream(self, fs): return self._from_buffer(object_buffer) - def AddCertData(self, in_data): + def AddCertData(self, in_data: BytesIO) -> None: """Adds the Cert Data to the struct. Args: @@ -472,7 +469,7 @@ def AddCertData(self, in_data): warn("AddCertData is deprecated, use add_cert_data instead", DeprecationWarning, 2) return self.add_cert_data(in_data) - def add_cert_data(self, in_data): + def add_cert_data(self, in_data: BytesIO) -> None: """Adds the Cert Data to the struct. Args: @@ -493,11 +490,11 @@ def add_cert_data(self, in_data): self.Hdr_dwLength = self.Hdr_dwLength + len(self.cert_data) - def PopulateFromFileStream(self, fs): + def PopulateFromFileStream(self, fs: BytesIO) -> bytes: """Un-serialized from a filestream. Args: - fs (obj): Already opened file + fs: Already opened file Raises: (ValueError): Invalid fs @@ -506,25 +503,25 @@ def PopulateFromFileStream(self, fs): warn("PopulateFromFileStream is deprecated, use decode instead", DeprecationWarning, 2) return self.decode(fs) - def get_certificate(self): + def get_certificate(self) -> bytes: """Returns certificate data, if certificate data exists.""" return self.cert_data - def GetCertificate(self): + def GetCertificate(self) -> bytes: """Returns certificate data, if certificate data exists.""" warn("GetCertificate is deprecated, use get_certificate instead", DeprecationWarning, 2) return self.get_certificate() - def print(self, outfs=sys.stdout): + def print(self, outfs: StringIO=sys.stdout) -> None: """Prints struct to console.""" self.dump_info(outfs) - def Print(self, outfs=sys.stdout): + def Print(self, outfs: StringIO=sys.stdout) -> None: """Prints struct to console.""" warn("Print() is deprecated, use print() instead.", DeprecationWarning, 2) self.dump_info(outfs) - def dump_info(self, outfs=sys.stdout): + def dump_info(self, outfs: StringIO=sys.stdout) -> None: """Prints struct to a file stream.""" outfs.write("\n-------------------- WIN_CERTIFICATE ---------------------\n") outfs.write(f"WIN_CERTIFICATE.dwLength = {self.Hdr_dwLength:08X}\n") @@ -549,21 +546,21 @@ def dump_info(self, outfs=sys.stdout): except Exception as exc: raise ValueError("Unable to decode cert_data") from exc - def DumpInfo(self, outfs=sys.stdout): + def DumpInfo(self, outfs: StringIO=sys.stdout) -> None: """Prints struct to a file stream.""" warn("DumpInfo is deprecated, use dump_info instead", DeprecationWarning, 2) self.dump_info(outfs) - def write(self, fs): + def write(self, fs: BytesIO) -> None: """Writes the struct to a filestream.""" fs.write(self.encode()) - def Write(self, fs): + def Write(self, fs: BytesIO) -> None: """Writes the struct to a filestream.""" warn("Write is deprecated, use write instead", DeprecationWarning, 2) fs.write(self.encode()) - def __str__(self): + def __str__(self) -> str: """Returns the object as a string.""" string_repr = "" with io.StringIO() as f: @@ -586,11 +583,11 @@ class WinCert(object): REVISION = 0x200 @staticmethod - def factory(fs): + def factory(fs: BytesIO) -> WinCertUefiGuid | WinCertPkcs1: """Generates a specific Cert Type depending on parsed Hdr_wCertificationType from the fs. Args: - fs (obj): filestream + fs: filestream Returns: (WinCertUefiGuid): if Hdr_wCertificationType == WIN_CERT_TYPE_EFI_GUID @@ -630,11 +627,11 @@ def factory(fs): # @staticmethod - def Factory(fs): + def Factory(fs: BytesIO) -> WinCertUefiGuid | WinCertPkcs1: """Generates a specific Cert Type depending on parsed Hdr_wCertificationType from the fs. Args: - fs (obj): filestream + fs: filestream Returns: (WinCertUefiGuid): if Hdr_wCertificationType == WIN_CERT_TYPE_EFI_GUID diff --git a/edk2toollib/utility_functions.py b/edk2toollib/utility_functions.py index c71665441..9d911641f 100644 --- a/edk2toollib/utility_functions.py +++ b/edk2toollib/utility_functions.py @@ -22,6 +22,8 @@ import threading import time from collections import namedtuple +from io import BytesIO, StringIO +from typing import Any, Callable, Optional from warnings import warn @@ -85,7 +87,7 @@ def reader(filepath, outstream, stream, logging_level=logging.INFO, encodingErro f.close() -def GetHostInfo(): +def GetHostInfo() -> namedtuple: """Returns a namedtuple containing information about host machine. Returns: @@ -120,7 +122,7 @@ def GetHostInfo(): return Host(os=os, arch=arch, bit=bit) -def timing(f): +def timing(f: Callable) -> Callable: """This is a mixing to do timing on a function. Example: @@ -129,7 +131,7 @@ def timing(f): def function_i_want_to_time(): ``` """ - def wrap(*args): + def wrap(*args: Any) -> int: # time1 = time.time() ret = f(*args) time2 = time.time() @@ -138,30 +140,40 @@ def wrap(*args): return wrap -def RunCmd(cmd, parameters, capture=True, workingdir=None, outfile=None, outstream=None, environ=None, - logging_level=logging.INFO, raise_exception_on_nonzero=False, encodingErrors='strict', - close_fds=True): +def RunCmd( + cmd: str, + parameters: str, + capture: bool=True, + workingdir: str=None, + outfile: Optional[str]=None, + outstream: Optional[str]=None, + environ: Optional[dict]=None, + logging_level: int=logging.INFO, + raise_exception_on_nonzero: bool=False, + encodingErrors: str='strict', + close_fds: bool=True +) -> int: """Run a shell command and print the output to the log file. This is the public function that should be used to run commands from the shell in python environment Attributes: - cmd (str): command being run, either quoted or not quoted - parameters (str): parameters string taken as is + cmd: command being run, either quoted or not quoted + parameters: parameters string taken as is capture (obj): boolean to determine if caller wants the output captured in any format. - workingdir (str): path to set to the working directory before running + workingdir: path to set to the working directory before running the command. - outfile (obj): capture output to file of given path. - outstream (obj): capture output to a stream. - environ (obj): shell environment variables dictionary that replaces the + outfile: capture output to file of given path. + outstream: capture output to a stream. + environ: shell environment variables dictionary that replaces the one inherited from the current process. - logging_level (obj): log level to log output at. Default is INFO - raise_exception_on_nonzero (bool): Setting to true causes exception to + logging_level: log level to log output at. Default is INFO + raise_exception_on_nonzero: Setting to true causes exception to be raised if the cmd return code is not zero. - encodingErrors (str): may be given to set the desired error handling + encodingErrors: may be given to set the desired error handling for encoding errors decoding cmd output. Default is 'strict'. - close_fds (bool): If True, file descriptors are closed before the + close_fds: If True, file descriptors are closed before the command is run. Default is True. Returns: @@ -203,20 +215,32 @@ def RunCmd(cmd, parameters, capture=True, workingdir=None, outfile=None, outstre return c.returncode -def RunPythonScript(pythonfile, params, capture=True, workingdir=None, outfile=None, outstream=None, - environ=None, logging_level=logging.INFO, raise_exception_on_nonzero=False): +def RunPythonScript( + pythonfile: str, + params: str, + capture: bool=True, + workingdir: Optional[str]=None, + outfile: Optional[str]=None, + outstream: Optional[str]=None, + environ:Optional[dict]=None, + logging_level: int=logging.INFO, + raise_exception_on_nonzero: bool=False +) -> int: """Run a python script and print the output to the log file. This is the public function that should be used to execute python scripts from the shell in python environment. The python script will be located using the path as if it was an executable. - Attributes: - cmd: cmd string to run including parameters - capture: boolean to determine if caller wants the output captured in any format. + Args: + pythonfile: python file to execute + params: parameters string taken as is + capture: if caller wants the output captured in any format. workingdir: path to set to the working directory before running the command. outfile: capture output to file of given path. outstream: capture output to a stream. environ: shell environment variables dictionary that replaces the one inherited from the current process. + logging_level: log level to log output at. Default is INFO + raise_exception_on_nonzero: causes exception to be raised if the cmd return code is not zero. Returns: (int): returncode of called cmd @@ -246,8 +270,15 @@ def RunPythonScript(pythonfile, params, capture=True, workingdir=None, outfile=N raise_exception_on_nonzero=raise_exception_on_nonzero) -def DetachedSignWithSignTool(SignToolPath, ToSignFilePath, SignatureOutputFile, PfxFilePath, - PfxPass=None, Oid="1.2.840.113549.1.7.2", Eku=None): +def DetachedSignWithSignTool( + SignToolPath: str, + ToSignFilePath: str, + SignatureOutputFile: str, + PfxFilePath: str, + PfxPass: Optional[str]=None, + Oid: str="1.2.840.113549.1.7.2", + Eku: Optional[str]=None +) -> int: """Locally Sign input file using Windows SDK signtool. This will use a local Pfx file. @@ -290,7 +321,12 @@ def DetachedSignWithSignTool(SignToolPath, ToSignFilePath, SignatureOutputFile, return ret -def CatalogSignWithSignTool(SignToolPath, ToSignFilePath, PfxFilePath, PfxPass=None): +def CatalogSignWithSignTool( + SignToolPath: str, + ToSignFilePath: str, + PfxFilePath: str, + PfxPass: Optional[str]=None +) -> int: """Locally sign input file using Windows SDK signtool. This will use a local Pfx file. @@ -327,15 +363,15 @@ def CatalogSignWithSignTool(SignToolPath, ToSignFilePath, PfxFilePath, PfxPass=N # https://stackoverflow.com/questions/1714027/version-number-comparison # With Python 3.0 help from: # https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons -def version_compare(version1, version2): +def version_compare(version1: str, version2: str) -> bool: """Compare two versions.""" - def normalize(v): + def normalize(v: str) -> bool: return [int(x) for x in re.sub(r'(\.0+)*$', '', v).split(".")] (a, b) = (normalize(version1), normalize(version2)) return (a > b) - (a < b) -def import_module_by_file_name(module_file_path): +def import_module_by_file_name(module_file_path: str) -> Any: # noqa: ANN401 """Standard method of importing a Python file. Expecting absolute path.""" module_name = os.path.basename(module_file_path) spec = importlib.util.spec_from_file_location(module_name, module_file_path) @@ -349,7 +385,7 @@ def import_module_by_file_name(module_file_path): return ImportedModule -def locate_class_in_module(Module, DesiredClass): +def locate_class_in_module(Module: Any, DesiredClass: Any) -> Any: # noqa: ANN401 """Given a module and a class, this function will return the subclass of DesiredClass found in Module. It gives preference to classes that are defined in the module itself. @@ -388,11 +424,11 @@ def RemoveTree(dir_path: str, ignore_errors: bool = False) -> None: On error try to change file attributes. Also adds retry logic. Args: - dir_path (str): Path to directory to remove. - ignore_errors (bool): ignore errors during removal + dir_path: Path to directory to remove. + ignore_errors: ignore errors during removal """ # TODO actually make this private with _ - def remove_readonly(func, path, _): + def remove_readonly(func: Callable, path: str, _: Any) -> None: # noqa: ANN401 """Private function to attempt to change permissions on file/folder being deleted.""" os.chmod(path, stat.S_IWRITE) func(path) @@ -408,7 +444,14 @@ def remove_readonly(func, path, _): raise RuntimeError(f"Failed to remove {dir_path}") -def PrintByteList(ByteList, IncludeAscii=True, IncludeOffset=True, IncludeHexSep=True, OffsetStart=0, **kwargs): +def PrintByteList( + ByteList: bytearray, + IncludeAscii: bool=True, + IncludeOffset: bool=True, + IncludeHexSep: bool=True, + OffsetStart: int=0, + **kwargs: Any # +) -> None: """Print a byte array as hex and optionally output ascii as well as offset within the buffer.""" outfs = kwargs.get("outfs", sys.stdout) kwargs["include_ascii"] = IncludeAscii @@ -422,14 +465,14 @@ def PrintByteList(ByteList, IncludeAscii=True, IncludeOffset=True, IncludeHexSep hexdump(ByteList, offset_start=OffsetStart, outfs=outfs, **kwargs) -def hexdump(byte_list, offset_start=0, outfs=sys.stdout, **kwargs) -> None: +def hexdump(byte_list: bytearray, offset_start: int=0, outfs: BytesIO=sys.stdout, **kwargs: Any) -> None: # """Print a byte array as hex and optionally output ascii as well as offset within the buffer. Args: - byte_list (bytearray): byte array to print - offset_start (int): offset to print to the side of the hexdump - outfs (io.BytesIO): output file stream to print to - kwargs (any): keyword arguments expanded below. + byte_list: byte array to print + offset_start: offset to print to the side of the hexdump + outfs: output file stream to print to + kwargs: keyword arguments expanded below. Keyword Arguments: include_ascii (bool): Option (Default: True) to include ascii @@ -489,14 +532,14 @@ def hexdump(byte_list, offset_start=0, outfs=sys.stdout, **kwargs) -> None: outfs.write("\n") -def export_c_type_array(buffer_fs, variable_name, out_fs, **kwargs) -> None: +def export_c_type_array(buffer_fs: BytesIO, variable_name: str, out_fs: StringIO, **kwargs: Any) -> None: # """Converts a given binary file to a UEFI typed C style array. Args: - buffer_fs (io.BytesIO): buffer file stream to turn into a C style array - variable_name (str): variable name to use for the C style array - out_fs (io.StringIO): output filestream to write to - kwargs (any): keyword arguments expanded below. + buffer_fs: buffer file stream to turn into a C style array + variable_name: variable name to use for the C style array + out_fs: output filestream to write to + kwargs: keyword arguments expanded below. Keyword Arguments: data_type (str): The datatype of the array (Default: UINT8) diff --git a/edk2toollib/windows/capsule/cat_generator.py b/edk2toollib/windows/capsule/cat_generator.py index a9c56ecd7..9496bdde3 100644 --- a/edk2toollib/windows/capsule/cat_generator.py +++ b/edk2toollib/windows/capsule/cat_generator.py @@ -12,6 +12,7 @@ """ import logging import os +from typing import Optional from edk2toollib.utility_functions import RunCmd from edk2toollib.windows.locate_tools import FindToolInWinSdk @@ -37,7 +38,7 @@ class CatGenerator(object): 'serverrs4': 'ServerRS4' } - def __init__(self, arch, os): + def __init__(self, arch: str, os: str) -> None: """Inits a Cat Generator. Args: @@ -48,12 +49,12 @@ def __init__(self, arch, os): self.OperatingSystem = os @property - def Arch(self): + def Arch(self) -> str: """Returns the attribute arch.""" return self._arch @Arch.setter - def Arch(self, value): + def Arch(self, value: str) -> None: """Validates the arch before setting it. Raises: @@ -71,12 +72,12 @@ def Arch(self, value): raise ValueError("Unsupported Architecture") @property - def OperatingSystem(self): + def OperatingSystem(self) -> str: """Returns the Operating system attribute.""" return self._operatingsystem @OperatingSystem.setter - def OperatingSystem(self, value): + def OperatingSystem(self, value: str) -> None: """Validates the OS is supported before setting the attribute. Raises: @@ -88,7 +89,7 @@ def OperatingSystem(self, value): raise ValueError("Unsupported Operating System") self._operatingsystem = CatGenerator.SUPPORTED_OS[key] - def MakeCat(self, OutputCatFile, PathToInf2CatTool=None): + def MakeCat(self, OutputCatFile: str, PathToInf2CatTool: Optional[str]=None) -> int: """Generates a cat file to the outputcatfile directory. Args: diff --git a/edk2toollib/windows/capsule/inf_generator.py b/edk2toollib/windows/capsule/inf_generator.py index 3b8919957..8eab06efb 100644 --- a/edk2toollib/windows/capsule/inf_generator.py +++ b/edk2toollib/windows/capsule/inf_generator.py @@ -15,11 +15,12 @@ import os import re import uuid +from typing import Optional class InfSection(object): """Object representing an INF Section.""" - def __init__(self, name) -> None: + def __init__(self, name: str) -> None: """Inits the object.""" self.Name = name self.Items = [] @@ -100,7 +101,16 @@ class InfGenerator(object): 'aarch64': 'ARM64' } - def __init__(self, name_string, provider, esrt_guid, arch, description_string, version_string, version_hex): + def __init__( + self, + name_string: str, + provider: str, + esrt_guid: str, + arch: str, + description_string: str, + version_string: str, + version_hex: str + ) -> None: """Inits the object with data necessary to generate an INF file. Args: @@ -124,12 +134,12 @@ def __init__(self, name_string, provider, esrt_guid, arch, description_string, v self._integrityfile = None @property - def Name(self): + def Name(self) -> str: """Getter for the Name Attribute.""" return self._name @Name.setter - def Name(self, value): + def Name(self, value: str) -> None: """Setter for the Name Attribute. Raises: @@ -142,17 +152,17 @@ def Name(self, value): self._name = value @property - def Provider(self): + def Provider(self) -> str: """Getter for the Provider Attribute.""" return self._provider @Provider.setter - def Provider(self, value): + def Provider(self, value: str) -> None: """Setter for the Provider Attribute.""" self._provider = value @property - def Manufacturer(self): + def Manufacturer(self) -> str: """Getter for the Manufacturer Attribute. NOTE: Returns Provider attribute if Manufacturer attribute is not set. @@ -163,27 +173,27 @@ def Manufacturer(self): return self._manufacturer @Manufacturer.setter - def Manufacturer(self, value): + def Manufacturer(self, value: str) -> None: """Setter for the Manufacturer Attribute.""" self._manufacturer = value @property - def Description(self): + def Description(self) -> str: """Getter for the Description Attribute.""" return self._description @Description.setter - def Description(self, value): + def Description(self, value: str) -> None: """Setter for the Description Attribute.""" self._description = value @property - def EsrtGuid(self): + def EsrtGuid(self) -> str: """Getter for the EsrtGuid Attribute.""" return self._esrt_guid @EsrtGuid.setter - def EsrtGuid(self, value): + def EsrtGuid(self, value: str) -> None: """Setter for the EsrtGuid Attribute. Raises: @@ -194,12 +204,12 @@ def EsrtGuid(self, value): self._esrt_guid = value @property - def VersionString(self): + def VersionString(self) -> str: """Getter for VersionString attribute.""" return self._versionstring @VersionString.setter - def VersionString(self, value): + def VersionString(self, value: str) -> None: """Setter for the VersionString attribute. Raises: @@ -212,12 +222,12 @@ def VersionString(self, value): self._versionstring = value @property - def VersionHex(self): + def VersionHex(self) -> str: """Getter for the VersionHex attribute.""" return "0x%X" % self._versionhex @VersionHex.setter - def VersionHex(self, value): + def VersionHex(self, value: int) -> None: """Setter for the VersionHex attribute. Raises: @@ -230,12 +240,12 @@ def VersionHex(self, value): self._versionhex = a @property - def Arch(self): + def Arch(self) -> str: """Getter for the Arch property.""" return self._arch @Arch.setter - def Arch(self, value): + def Arch(self, value: str) -> None: """Setter for the Arch Attribute. Raises: @@ -248,7 +258,7 @@ def Arch(self, value): self._arch = InfGenerator.SUPPORTED_ARCH[key] @property - def Date(self): + def Date(self) -> str: """Getter for the date attribute. Formats to a m/d/y str before returning @@ -256,7 +266,7 @@ def Date(self): return self._date.strftime("%m/%d/%Y") @Date.setter - def Date(self, value): + def Date(self, value: datetime.date) -> None: """Setter for the Date attribute. Raises: @@ -267,7 +277,7 @@ def Date(self, value): self._date = value @property - def IntegrityFilename(self): + def IntegrityFilename(self) -> Optional[str]: """Getter for the Integrity File Name. Transforms value into string. @@ -275,15 +285,15 @@ def IntegrityFilename(self): return str(self._integrityfile) if self._integrityfile is not None else "" @IntegrityFilename.setter - def IntegrityFilename(self, value): + def IntegrityFilename(self, value: str) -> None: """Setter for the IntegrityFile name.""" self._integrityfile = value - def MakeInf(self, OutputInfFilePath, FirmwareBinFileName, Rollback=False): + def MakeInf(self, OutputInfFilePath: os.Pathlike, FirmwareBinFileName: str, Rollback: bool=False) -> int: """Generates the INF with provided information. Args: - OutputInfFilePath (PathLike): Path to existing file + OutputInfFilePath (os.PathLike): Path to existing file FirmwareBinFileName (str): File Name Rollback (:obj:`bool`, optional): Generate with Rollback template """ diff --git a/edk2toollib/windows/capsule/inf_generator2.py b/edk2toollib/windows/capsule/inf_generator2.py index 3ef2ffe09..ca62850df 100644 --- a/edk2toollib/windows/capsule/inf_generator2.py +++ b/edk2toollib/windows/capsule/inf_generator2.py @@ -47,12 +47,12 @@ def __init__(self, Name: str, VersionStr: str, CreationDate: str, Arch: str, Pro InfStrings.AddLocalizableString("MfgName", Manufacturer) @property - def Name(self): + def Name(self) -> str: """Returns the Name attribute.""" return self._name @Name.setter - def Name(self, value): + def Name(self, value: str) -> None: """Validates a Name string before setting the attribute. Raises: @@ -64,12 +64,12 @@ def Name(self, value): self._name = value @property - def VersionStr(self): + def VersionStr(self) -> str: """Returns the VersionStr attribute.""" return self._versionstr @VersionStr.setter - def VersionStr(self, value): + def VersionStr(self, value: str) -> None: """Validates the VersionStr before setting the attribute. Raises: @@ -81,22 +81,22 @@ def VersionStr(self, value): self._versionstr = value @property - def Date(self): + def Date(self) -> str: """Returns the Date attribute, a datetime object.""" return self._date @Date.setter - def Date(self, value): + def Date(self, value: str) -> None: """Sets the Date attribute as a datetime object, from a str.""" self._date = datetime.strptime(value, "%m/%d/%Y").strftime("%m/%d/%Y") @property - def Arch(self): + def Arch(self) -> str: """Returns the Architecture.""" return self._arch @Arch.setter - def Arch(self, value): + def Arch(self, value: str) -> str: """Validates the Architecture before setting the attribute.""" key = value.lower() if (key not in SUPPORTED_ARCH.keys()): @@ -162,12 +162,12 @@ def __init__(self, Tag: str, Description: str, EsrtGuid: str, VersionInt: str, F InfStrings.AddNonLocalizableString("REG_DWORD", "0x00010001") @property - def Tag(self): + def Tag(self) -> str: """Returns the Tag value.""" return self._tag @Tag.setter - def Tag(self, value): + def Tag(self, value: str) -> None: """Verifies a valid tag before setting. Raises: @@ -179,23 +179,23 @@ def Tag(self, value): self._tag = value @property - def EsrtGuid(self): + def EsrtGuid(self) -> uuid.UUID: """Returns the EsrtGuid value.""" return self._esrt_guid @EsrtGuid.setter - def EsrtGuid(self, value): + def EsrtGuid(self, value: uuid.UUID) -> None: """Transforms string into actual guid object before setting.""" uuid.UUID(value) self._esrt_guid = value @property - def VersionInt(self): + def VersionInt(self) -> int: """Returns the VersionInt value.""" return self._version_int @VersionInt.setter - def VersionInt(self, value): + def VersionInt(self, value: int) -> None: """Sets the VersionInt value from a string.""" self._version_int = int(value, base=0) @@ -257,12 +257,12 @@ def __init__(self, Arch: str, InfStrings: 'InfStrings') -> None: self.InfStrings = InfStrings @property - def Arch(self): + def Arch(self) -> str: """Returns the Architecture.""" return self._arch @Arch.setter - def Arch(self, value): + def Arch(self, value: str) -> str: """Validates the Architecture before setting the attribute.""" key = value.lower() if (key not in SUPPORTED_ARCH.keys()): diff --git a/edk2toollib/windows/locate_tools.py b/edk2toollib/windows/locate_tools.py index 5bbd08d48..35c3c8ef3 100644 --- a/edk2toollib/windows/locate_tools.py +++ b/edk2toollib/windows/locate_tools.py @@ -25,6 +25,7 @@ import os import re import subprocess +from typing import Optional import pkg_resources @@ -50,7 +51,7 @@ # Downloads VSWhere -def _DownloadVsWhere(unpack_folder: os.PathLike = None): +def _DownloadVsWhere(unpack_folder: os.PathLike = None) -> None: if unpack_folder is None: unpack_folder = os.path.dirname(__VsWherePath()) @@ -82,7 +83,7 @@ def _DownloadVsWhere(unpack_folder: os.PathLike = None): raise RuntimeError(f"VsWhere - sha256 does not match\n\tdownloaded:\t{temp_file_sha256}\n\t") -def __VsWherePath(): +def __VsWherePath() -> str: file = "vswhere.exe" requirement = pkg_resources.Requirement.parse("edk2-pytool-library") file_path = os.path.join("edk2toollib", "bin", file) @@ -90,7 +91,7 @@ def __VsWherePath(): return vswhere_path -def GetVsWherePath(fail_on_not_found: bool = True): +def GetVsWherePath(fail_on_not_found: bool = True) -> Optional[str]: """Get the VsWhere tool path. Args: @@ -128,7 +129,7 @@ def GetVsWherePath(fail_on_not_found: bool = True): return vswhere_path -def FindWithVsWhere(products: str = "*", vs_version: str = None): +def FindWithVsWhere(products: str = "*", vs_version: str = None) -> Optional[str]: """Finds a product with VS Where. Args: @@ -168,7 +169,7 @@ def FindWithVsWhere(products: str = "*", vs_version: str = None): return None -def QueryVcVariables(keys: list, arch: str = None, product: str = None, vs_version: str = None): +def QueryVcVariables(keys: list, arch: str = None, product: str = None, vs_version: str = None) -> str: """Launch vcvarsall.bat and read the settings from its environment. This is a windows only function and Windows is case insensitive for the keys @@ -250,7 +251,7 @@ def QueryVcVariables(keys: list, arch: str = None, product: str = None, vs_versi return result -def _CompareWindowVersions(a, b): +def _CompareWindowVersions(a: str, b: str) -> int: """Compares Windows versions. Returns: @@ -278,7 +279,7 @@ def _CompareWindowVersions(a, b): return 0 -def _CheckArchOfMatch(match): +def _CheckArchOfMatch(match: str) -> bool: """Returns if this binary matches our host. Returns: @@ -322,7 +323,7 @@ def _CheckArchOfMatch(match): # does a glob in the folder that your sdk is # uses the environmental variable WindowsSdkDir and tries to use WindowsSDKVersion -def FindToolInWinSdk(tool: str, product: str = None, arch: str = None): +def FindToolInWinSdk(tool: str, product: str = None, arch: str = None) -> str: """Searches for a tool in the Windows SDK Directory. Args: diff --git a/edk2toollib/windows/policy/firmware_policy.py b/edk2toollib/windows/policy/firmware_policy.py index f7c88e88b..7aca8db45 100644 --- a/edk2toollib/windows/policy/firmware_policy.py +++ b/edk2toollib/windows/policy/firmware_policy.py @@ -88,9 +88,16 @@ class Rule(object): StructFormat = ' None: + def __init__( + self, + RootKey: int, + SubKeyName: str, + ValueName: str, + Value: 'PolicyValue', + OffsetToSubKeyName: int = 0, + OffsetToValueName: int = 0, + OffsetToValue: int = 0 +) -> None: """Inits the Rule Object. Args: @@ -110,7 +117,7 @@ def __init__(self, RootKey: int, SubKeyName: str, ValueName: str, self.ValueName = ValueName self.Value = PolicyValue(Value.valueType, Value.value) - def __eq__(self, other) -> bool: + def __eq__(self, other: 'Rule') -> bool: """Rule table offsets are not considered for equivalency, only the actual key/value.""" if (self.RootKey == other.RootKey and self.SubKeyName == other.SubKeyName @@ -121,7 +128,7 @@ def __eq__(self, other) -> bool: return False @classmethod - def FromFsAndVtOffset(cls, fs: BinaryIO, vtOffset: int): + def FromFsAndVtOffset(cls: 'Rule', fs: BinaryIO, vtOffset: int) -> 'Rule': """Construct a Rule initialized from a deserialized stream and vtOffset. Args: @@ -147,7 +154,7 @@ def FromFsAndVtOffset(cls, fs: BinaryIO, vtOffset: int): SubKeyName=SubKeyName, ValueName=ValueName, Value=Value) @classmethod - def FromFsAndVtBytes(cls, fs: BinaryIO, vt: bytes): + def FromFsAndVtBytes(cls: 'Rule', fs: BinaryIO, vt: bytes) -> 'Rule': """Contstruct a Rule initialized from a deserialized stream and value table. Args: @@ -169,7 +176,7 @@ def FromFsAndVtBytes(cls, fs: BinaryIO, vt: bytes): OffsetToValueName=OffsetToValueName, OffsetToValue=OffsetToValue, SubKeyName=SubKeyName, ValueName=ValueName, Value=Value) - def Print(self, prefix: str = ''): + def Print(self, prefix: str = '') -> None: """Prints the contents of the Rule. Args: @@ -184,7 +191,7 @@ def Print(self, prefix: str = ''): self.ValueName.Print(prefix=prefix + ' ValueName ') self.Value.Print(prefix=prefix + ' ') - def Serialize(self, ruleOut: bytearray, valueOut: bytearray, offsetInVT: int): + def Serialize(self, ruleOut: bytearray, valueOut: bytearray, offsetInVT: int) -> None: """Serialize Rule. Args: @@ -235,7 +242,7 @@ class PolicyValueType(): POLICY_VALUE_TYPE_QWORD, POLICY_VALUE_TYPE_STRING} - def __init__(self, Type): + def __init__(self, Type: int) -> None: """Inits the PolicyValueType. Args: @@ -254,7 +261,7 @@ def __init__(self, Type): self.vt = Type @classmethod - def FromFileStream(cls, fs: BinaryIO, fsOffset: int = None): + def FromFileStream(cls: 'PolicyValueType', fs: BinaryIO, fsOffset: int = None) -> 'PolicyValueType': """Load a Policy Value Type from a file stream. NOTE: if fsOffset is not specified, stream fs position is at beginning of struct. @@ -269,7 +276,7 @@ def FromFileStream(cls, fs: BinaryIO, fsOffset: int = None): return cls(valueType) @classmethod - def FromBytes(cls, b: bytes, bOffset: int = 0): + def FromBytes(cls: 'PolicyValueType', b: bytes, bOffset: int = 0) -> 'PolicyValueType': """Inits a PolicyStringValue from a filestream. Args: @@ -279,7 +286,7 @@ def FromBytes(cls, b: bytes, bOffset: int = 0): valueType = struct.unpack_from(cls.StructFormat, b, bOffset)[0] return cls(valueType) - def Print(self, prefix: str = ''): + def Print(self, prefix: str = '') -> None: """Prints the contents of the Policy String Type. Args: @@ -287,7 +294,7 @@ def Print(self, prefix: str = ''): """ print('%s%s%s' % (prefix, 'ValueType: ', self.vt)) - def Serialize(self, valueOut: bytearray): + def Serialize(self, valueOut: bytearray) -> None: """Serialize the Policy String Type. Args: @@ -295,7 +302,7 @@ def Serialize(self, valueOut: bytearray): """ valueOut += struct.pack(self.StructFormat, self.vt) - def Get(self): + def Get(self: 'PolicyValueType') -> int: """Returns the value type.""" return self.vt @@ -319,7 +326,7 @@ class PolicyString(): StringLengthFormat = ' None: """Inits PolicyStructure. Args: @@ -332,7 +339,7 @@ def __init__(self, String: str = None): return @classmethod - def FromFileStream(cls, fs: BinaryIO, fsOffset: int = None): + def FromFileStream(cls: 'PolicyString', fs: BinaryIO, fsOffset: int = None) -> 'PolicyString': """Inits a PolicyString from a file stream. Args: @@ -352,7 +359,7 @@ def FromFileStream(cls, fs: BinaryIO, fsOffset: int = None): return cls(String=LocalString) @classmethod - def FromBytes(cls, b: bytes, bOffset: int = 0): + def FromBytes(cls: 'PolicyString', b: bytes, bOffset: int = 0) -> 'PolicyString': """Inits a PolicyString from a filestream. Args: @@ -370,7 +377,7 @@ def FromBytes(cls, b: bytes, bOffset: int = 0): raise Exception('String length mismatch') return cls(String=LocalString) - def Print(self, prefix: str = ''): + def Print(self, prefix: str = '') -> None: """Prints the contents of the Policy String. Args: @@ -378,7 +385,7 @@ def Print(self, prefix: str = ''): """ print('%s%s%s' % (prefix, 'String: ', self.String)) - def Serialize(self, valueOut: bytearray): + def Serialize(self, valueOut: bytearray) -> None: """Serialize the Policy String. Args: @@ -400,7 +407,7 @@ class PolicyValue(): valueType (PolicyValueType): Policy Value Type value (struct): Policy String, dword, qword """ - def __init__(self, valueType, value): + def __init__(self, valueType: PolicyValueType, value: str) -> None: """Inits a Policy Value. Args: @@ -411,7 +418,7 @@ def __init__(self, valueType, value): self.value = value @classmethod - def FromFileStream(cls, fs: BinaryIO, fsOffset: int = None): + def FromFileStream(cls: 'PolicyValue', fs: BinaryIO, fsOffset: int = None) -> 'PolicyValue': """Load a Policy Value from a file stream. NOTE: if fsOffset is not specified, stream fs position is at beginning of struct. @@ -442,7 +449,7 @@ def FromFileStream(cls, fs: BinaryIO, fsOffset: int = None): return cls(valueType=valueType, value=value) @classmethod - def FromBytes(cls, b: bytes, bOffset: int = 0): + def FromBytes(cls: 'PolicyValue', b: bytes, bOffset: int = 0) -> 'PolicyValue': """Load a Policy Value from bytes. Args: @@ -465,11 +472,11 @@ def FromBytes(cls, b: bytes, bOffset: int = 0): return cls(valueType=valueType, value=value) - def GetValueType(self): + def GetValueType(self) -> str: """Returns the value type.""" return self.valueType - def Print(self, prefix: str = ''): + def Print(self, prefix: str = '') -> None: """Prints the contents of the object. Args: @@ -483,7 +490,7 @@ def Print(self, prefix: str = ''): else: print('%s%s"%s"' % (prefix, 'Value: ', str(self.value))) - def Serialize(self, valueOut: bytearray): + def Serialize(self, valueOut: bytearray) -> None: """Serializes the object to valueOut. Args: @@ -519,7 +526,7 @@ class Reserved2(object): StructFormat = ' None: """Initializes the Reserved2 structure. Args: @@ -537,7 +544,7 @@ def __init__(self, fs: BinaryIO = None, vtOffset: int = 0): if (STRICT is True): raise Exception(errorMessage) - def PopulateFromFileStream(self, fs: BinaryIO, vtOffset: int = 0): + def PopulateFromFileStream(self, fs: BinaryIO, vtOffset: int = 0) -> None: """Initializes the Reserved2 structure from a filestream. Args: @@ -558,7 +565,7 @@ def PopulateFromFileStream(self, fs: BinaryIO, vtOffset: int = 0): if (STRICT is True): raise Exception(errorMessage) - def Print(self, prefix: str = ''): + def Print(self, prefix: str = '') -> None: """Prints the Reserved2 structure. Args: @@ -569,7 +576,7 @@ def Print(self, prefix: str = ''): print('%s Element: %x' % (prefix, self.Element)) print('%s ValueOffset: %x' % (prefix, self.OffsetToValue)) - def Serialize(self, ruleOut: bytearray, valueOut: bytearray = None, offsetInVT: int = 0): + def Serialize(self, ruleOut: bytearray, valueOut: bytearray = None, offsetInVT: int = 0) -> None: """Serialize Reserved2 rule. Args: @@ -628,7 +635,7 @@ class FirmwarePolicy(object): FW_POLICY_VALUE_STATE_TBD: "To Be Defined Placeholder" } - def __init__(self, fs: BinaryIO = None): + def __init__(self, fs: BinaryIO = None) -> None: """Initializes a Firmware Policy object. Args: @@ -671,7 +678,7 @@ def AddRule(self, regRule: Rule) -> bool: self.RulesCount += 1 return True - def SetDevicePolicy(self, policy: int): + def SetDevicePolicy(self, policy: int) -> None: """Adds a Rule for the 64-bit policy value bitfield. NOTE: The "key" is a well-known constant assigned in the body of this method @@ -688,7 +695,7 @@ def SetDevicePolicy(self, policy: int): ValueName=ValueName, Value=Value) self.AddRule(rule) - def SetDeviceTarget(self, target: dict): + def SetDeviceTarget(self, target: dict) -> None: """Sets the device target dictionary. Args: @@ -707,7 +714,7 @@ def SetDeviceTarget(self, target: dict): ValueName=ValueName, Value=Value) self.AddRule(rule) - def SerializeToStream(self, stream: BinaryIO): + def SerializeToStream(self, stream: BinaryIO) -> None: """Serializes the Firmware Policy to a stream. Args: @@ -717,7 +724,7 @@ def SerializeToStream(self, stream: BinaryIO): self.Serialize(output=ba) stream.write(ba) - def Serialize(self, output: bytearray): + def Serialize(self, output: bytearray) -> None: """Serializes the Firmware Policy to a bytearray. Args: @@ -771,7 +778,7 @@ def Serialize(self, output: bytearray): output += serial self.ValueTableFromFile = False - def FromFileStream(self, fs: BinaryIO, parseByBytes: bool = True): + def FromFileStream(self, fs: BinaryIO, parseByBytes: bool = True) -> None: """Initializes the Firmware Policy from a FileStream. Args: @@ -853,7 +860,7 @@ def FromFileStream(self, fs: BinaryIO, parseByBytes: bool = True): RegRule = Rule.FromFsAndVtOffset(fs=fs, vtOffset=self.ValueTableOffset) self.Rules.append(RegRule) - def PrintDevicePolicy(self, devicePolicy: int, prefix: str = ''): + def PrintDevicePolicy(self, devicePolicy: int, prefix: str = '') -> None: """Prints the device policy.""" prefix = prefix + ' ' for bit in self.FW_POLICY_VALUE_ACTION_STRINGS.keys(): diff --git a/pyproject.toml b/pyproject.toml index f1f0c7eef..ed72c7791 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,13 +67,18 @@ select = [ "F", # PyFlakes "D", # pydocstyle "I", # isort - "PIE", # flake8 - PIE + "PIE", # flake8 - PIEpip + "ANN", ] line-length = 120 +ignore = ["ANN101"] [tool.ruff.pydocstyle] convention = "google" +[tool.ruff.flake8-annotations] +allow-star-arg-any = true + [tool.pytest.ini_options] testpaths = [ "tests.unit"