def createFields(self): # Header yield String(self, "magic", 4, "PMGL", charset="ASCII") yield filesizeHandler(Int32(self, "free_space", "Length of free space and/or quickref area at end of directory chunk")) yield Int32(self, "unknown") yield Int32(self, "previous", "Chunk number of previous listing chunk") yield Int32(self, "next", "Chunk number of previous listing chunk") # Entries stop = self.size - self["free_space"].value * 8 entry_count = 0 while self.current_size < stop: yield PMGL_Entry(self, "entry[]") entry_count += 1 # Padding quickref_frequency = 1 + (1 << self["/dir/itsp/density"].value) num_quickref = (entry_count // quickref_frequency) if entry_count % quickref_frequency == 0: num_quickref -= 1 print(self.current_size // 8, quickref_frequency, num_quickref) padding = (self["free_space"].value - (num_quickref * 2 + 2)) if padding: yield PaddingBytes(self, "padding", padding) for i in range(num_quickref * quickref_frequency, 0, -quickref_frequency): yield UInt16(self, "quickref[%i]" % i) yield UInt16(self, "entry_count")
def createFields(self): yield String(self, "header_id", 4, "DataBase Header Markup (\"mhbd\")", charset="ISO-8859-1") yield UInt32(self, "header_length", "Header Length") yield UInt32(self, "entry_length", "Entry Length") yield UInt32(self, "unknown[]") yield UInt32(self, "version_number", "Version Number") yield UInt32(self, "child_number", "Number of Children") yield UInt64(self, "id", "ID for this database") yield UInt16(self, "unknown[]") yield UInt32(self, "unknown[]") yield UInt64(self, "unknown[]") yield UInt16(self, "unknown[]") yield UInt16(self, "hashing_scheme[]", "Algorithm used to calculate the database hash") yield NullBytes(self, "unknown[]", 20) yield String(self, "language_id", 2, "Language ID") yield UInt64(self, "persistent_id", "Library Persistent ID") yield UInt32(self, "unknown[]") yield UInt32(self, "unknown[]") yield RawBytes(self, "hash[]", 20) yield Int32(self, "timezone_offset[]", "Timezone offset in seconds") yield UInt16(self, "unknown[]") yield RawBytes(self, "iphone_hash[]", 45) size = self["header_length"].value - self.current_size / 8 if size > 0: yield NullBytes(self, "padding", size) for i in range(self["child_number"].value): yield DataSet(self, "dataset[]") padding = self.seekByte(self["entry_length"].value, "entry padding") if padding: yield padding
def createFields(self): # Version 2 (12 bytes) yield UInt32(self, "header_size", "Header size") yield UInt32(self, "width", "Width (pixels)") yield UInt32(self, "height", "Height (pixels)") yield UInt16(self, "nb_plan", "Number of plan (=1)") # may be zero for PNG/JPEG picture yield UInt16(self, "bpp", "Bits per pixel") # Version 3 (40 bytes) if self["header_size"].value < 40: return yield Enum(UInt32(self, "compression", "Compression method"), BmpFile.COMPRESSION_NAME) yield UInt32(self, "image_size", "Image size (bytes)") yield UInt32(self, "horizontal_dpi", "Horizontal DPI") yield UInt32(self, "vertical_dpi", "Vertical DPI") yield UInt32(self, "used_colors", "Number of color used") yield UInt32(self, "important_color", "Number of import colors") # Version 4 (108 bytes) if self["header_size"].value < 108: return yield textHandler(UInt32(self, "red_mask"), hexadecimal) yield textHandler(UInt32(self, "green_mask"), hexadecimal) yield textHandler(UInt32(self, "blue_mask"), hexadecimal) yield textHandler(UInt32(self, "alpha_mask"), hexadecimal) yield Enum(UInt32(self, "color_space"), self.color_space_name) yield CIEXYZ(self, "red_primary") yield CIEXYZ(self, "green_primary") yield CIEXYZ(self, "blue_primary") yield UInt32(self, "gamma_red") yield UInt32(self, "gamma_green") yield UInt32(self, "gamma_blue")
def createFields(self): yield Enum(UInt16(self, "field_id", "Extra field ID"), self.EXTRA_FIELD_ID) size = UInt16(self, "field_data_size", "Extra field data size") yield size if size.value > 0: yield RawBytes(self, "field_data", size.value, "Unknown field data")
def parseCode(parent): if 0x3000000 <= parent.root.getVersion(): yield UInt32(parent, "arg_count", "Argument count") yield UInt32(parent, "kwonlyargcount", "Keyword only argument count") yield UInt32(parent, "nb_locals", "Number of local variables") yield UInt32(parent, "stack_size", "Stack size") yield UInt32(parent, "flags") elif 0x2030000 <= parent.root.getVersion(): yield UInt32(parent, "arg_count", "Argument count") yield UInt32(parent, "nb_locals", "Number of local variables") yield UInt32(parent, "stack_size", "Stack size") yield UInt32(parent, "flags") else: yield UInt16(parent, "arg_count", "Argument count") yield UInt16(parent, "nb_locals", "Number of local variables") yield UInt16(parent, "stack_size", "Stack size") yield UInt16(parent, "flags") yield Object(parent, "compiled_code") yield Object(parent, "consts") yield Object(parent, "names") yield Object(parent, "varnames") if 0x2000000 <= parent.root.getVersion(): yield Object(parent, "freevars") yield Object(parent, "cellvars") yield Object(parent, "filename") yield Object(parent, "name") if 0x2030000 <= parent.root.getVersion(): yield UInt32(parent, "firstlineno", "First line number") else: yield UInt16(parent, "firstlineno", "First line number") yield Object(parent, "lnotab")
def parseCommon(self): yield UInt16(self, "nb_channel") yield UInt32(self, "nb_sample") yield UInt16(self, "sample_size") yield Float80(self, "sample_rate") yield Enum(String(self, "codec", 4, strip="\0", charset="ASCII"), CODEC_NAME)
def fileHeader(self): yield filesizeHandler( UInt32(self, "compressed_size", "Size of the compressed file")) yield filesizeHandler( UInt32(self, "uncompressed_size", "Uncompressed file size")) yield TimeDateMSDOS32(self, "ftime", "Date and time (MS DOS format)") if self["/header/host_os"].value in (OS_MSDOS, OS_WIN32): yield MSDOSFileAttr32(self, "file_attr", "File attributes") else: yield textHandler(UInt32(self, "file_attr", "File attributes"), hexadecimal) yield textHandler( UInt32(self, "file_crc32", "CRC32 checksum over the compressed file)"), hexadecimal) yield Enum(UInt8(self, "compression_type", "Type of compression"), COMPRESSION_TYPE) yield Enum(UInt8(self, "compression_mode", "Quality of compression"), COMPRESSION_MODE) yield textHandler(UInt16(self, "parameters", "Compression parameters"), hexadecimal) yield textHandler(UInt16(self, "reserved", "Reserved data"), hexadecimal) # Filename yield PascalString16(self, "filename", "Filename") # Comment if self["flags/has_comment"].value: yield filesizeHandler( UInt16(self, "comment_size", "Size of the compressed comment")) if self["comment_size"].value > 0: yield RawBytes(self, "comment_data", self["comment_size"].value, "Comment data")
def createFields(self): yield String(self, "signature", 4, "PSD signature (8BPS)", charset="ASCII") yield UInt16(self, "version") yield NullBytes(self, "reserved[]", 6) yield UInt16(self, "nb_channels") yield UInt32(self, "width") yield UInt32(self, "height") yield UInt16(self, "depth") yield Enum(UInt16(self, "color_mode"), self.COLOR_MODE) # Mode data yield UInt32(self, "mode_data_size") size = self["mode_data_size"].value if size: yield RawBytes(self, "mode_data", size) # Resources yield Config(self, "config") # Reserved yield UInt32(self, "reserved_data_size") size = self["reserved_data_size"].value if size: yield RawBytes(self, "reserved_data", size) yield Enum(UInt16(self, "compression"), self.COMPRESSION_NAME) size = (self.size - self.current_size) // 8 if size: yield RawBytes(self, "end", size)
def parseDeclareFunction(parent, size): yield CString(parent, "name") argCount = UInt16(parent, "arg_count") yield argCount for i in range(argCount.value): yield CString(parent, "arg[]") yield UInt16(parent, "function_length")
def createFields(self): yield textHandler(UInt32(self, "crc32"), hexadecimal) yield UInt16(self, "size") yield UInt16(self, "uncompressed_size", "If this is 0, this block is continued in a subsequent cabinet") if self["/flags/has_reserved"].value and self["/reserved_data_size"].value: yield RawBytes(self, "reserved_data", self["/reserved_data_size"].value, "Per-datablock reserved area") compr_method = self.parent.folder["compr_method"].value if compr_method == 0: # Uncompressed yield RawBytes(self, "data", self["size"].value, "Folder Data") self.parent.uncompressed_data += self["data"].value elif compr_method == 1: # MSZIP yield String(self, "mszip_signature", 2, "MSZIP Signature (CK)") yield DeflateBlock(self, "deflate_block", self.parent.uncompressed_data) padding = paddingSize(self.current_size, 8) if padding: yield PaddingBits(self, "padding[]", padding) self.parent.uncompressed_data = self["deflate_block"].uncomp_data elif compr_method == 2: # Quantum yield RawBytes(self, "compr_data", self["size"].value, "Compressed Folder Data") elif compr_method == 3: # LZX group = getattr(self.parent.folder, "lzx_group", None) field = CustomFragment( self, "data", self["size"].value * 8, LZXStream, "LZX data fragment", group) if group is None: field.group.args["compr_level"] = self.parent.folder["compr_level"].value self.parent.folder.lzx_group = field.group yield field
def createFields(self): yield String(self, "name", 22, strip='\0') yield UInt16(self, "sample_count") yield textHandler(UInt8(self, "fine_tune"), getFineTune) yield textHandler(UInt8(self, "volume"), getVolume) yield UInt16(self, "loop_start", "Loop start offset in samples") yield UInt16(self, "loop_len", "Loop length in samples")
def createFields(self): yield textHandler( UInt32(self, "magic", "File information magic (0xFEEF04BD)"), hexadecimal) if self["magic"].value != 0xFEEF04BD: raise ParserError("EXE resource: invalid file info magic") yield Version(self, "struct_ver", "Structure version (1.0)") yield Version(self, "file_ver_ms", "File version MS") yield Version(self, "file_ver_ls", "File version LS") yield Version(self, "product_ver_ms", "Product version MS") yield Version(self, "product_ver_ls", "Product version LS") yield textHandler(UInt32(self, "file_flags_mask"), hexadecimal) yield Bit(self, "debug") yield Bit(self, "prerelease") yield Bit(self, "patched") yield Bit(self, "private_build") yield Bit(self, "info_inferred") yield Bit(self, "special_build") yield NullBits(self, "reserved", 26) yield Enum(textHandler(UInt16(self, "file_os_major"), hexadecimal), MAJOR_OS_NAME) yield Enum(textHandler(UInt16(self, "file_os_minor"), hexadecimal), MINOR_OS_NAME) yield Enum(textHandler(UInt32(self, "file_type"), hexadecimal), FILETYPE_NAME) field = textHandler(UInt32(self, "file_subfile"), hexadecimal) if field.value == FILETYPE_DRIVER: field = Enum(field, DRIVER_SUBTYPE_NAME) elif field.value == FILETYPE_FONT: field = Enum(field, FONT_SUBTYPE_NAME) yield field yield TimestampUnix32(self, "date_ms") yield TimestampUnix32(self, "date_ls")
def createFields(self): yield Enum(UInt16(self, "src"), self.port_name) yield Enum(UInt16(self, "dst"), self.port_name) yield UInt32(self, "seq_num") yield UInt32(self, "ack_num") yield Bits(self, "hdrlen", 6, "Header lenght") yield NullBits(self, "reserved", 2, "Reserved") yield Bit(self, "cgst", "Congestion Window Reduced") yield Bit(self, "ecn-echo", "ECN-echo") yield Bit(self, "urg", "Urgent") yield Bit(self, "ack", "Acknowledge") yield Bit(self, "psh", "Push mmode") yield Bit(self, "rst", "Reset connection") yield Bit(self, "syn", "Synchronize") yield Bit(self, "fin", "Stop the connection") yield UInt16(self, "winsize", "Windows size") yield textHandler(UInt16(self, "checksum"), hexadecimal) yield UInt16(self, "urgent") size = self["hdrlen"].value * 8 - self.current_size while 0 < size: option = TCP_Option(self, "option[]") yield option size -= option.size
def createFields(self): yield UInt16(self, "left", "Left") yield UInt16(self, "top", "Top") yield UInt16(self, "width", "Width") yield UInt16(self, "height", "Height") yield Bits(self, "size_local_map", 3, "log2(size of local map) minus one") yield NullBits(self, "reserved", 2) yield Bit(self, "sort_flag", "Is the local map sorted by decreasing importance?") yield Bit(self, "interlaced", "Interlaced?") yield Bit(self, "has_local_map", "Use local color map?") if self["has_local_map"].value: nb_color = 1 << (1 + self["size_local_map"].value) yield PaletteRGB(self, "local_map", nb_color, "Local color map") yield UInt8(self, "lzw_min_code_size", "LZW Minimum Code Size") group = None while True: size = UInt8(self, "image_block_size[]") if size.value == 0: break yield size block = CustomFragment(self, "image_block[]", size.value * 8, GifImageBlock, "GIF Image Block", group) if group is None: block.group.args["startbits"] = self["lzw_min_code_size"].value group = block.group yield block yield NullBytes(self, "terminator", 1, "Terminator (0)")
def createFields(self): yield UInt16(self, "size", "Node size (in bytes)") yield UInt16(self, "data_size") yield Enum(UInt16(self, "type"), self.TYPE_NAME) yield CString(self, "name", charset="UTF-16-LE") size = paddingSize(self.current_size // 8, 4) if size: yield NullBytes(self, "padding[]", size) size = self["data_size"].value if size: if self["type"].value == self.TYPE_STRING: if self.is_32bit: size *= 2 yield String(self, "value", size, charset="UTF-16-LE", truncate="\0") elif self["name"].value == "VS_VERSION_INFO": yield VersionInfoBinary(self, "value", size=size * 8) if self["value/file_flags_mask"].value == 0: self.is_32bit = False else: yield RawBytes(self, "value", size) while 12 <= (self.size - self.current_size) // 8: yield VersionInfoNode(self, "node[]", self.is_32bit) size = (self.size - self.current_size) // 8 if size: yield NullBytes(self, "padding[]", size)
def createFields(self): yield NullBytes(self, "options", 4) yield TimestampUnix32(self, "creation_date") yield UInt16(self, "maj_ver", "Major version") yield UInt16(self, "min_ver", "Minor version") yield UInt16(self, "nb_name", "Number of named entries") yield UInt16(self, "nb_index", "Number of indexed entries")
def createFields(self): yield Bits(self, "version", 4, "Version") yield Bits(self, "hdr_size", 4, "Header size divided by 5") # Type of service yield Enum(Bits(self, "precedence", 3, "Precedence"), self.precedence_name) yield Bit(self, "low_delay", "If set, low delay, else normal delay") yield Bit(self, "high_throu", "If set, high throughput, else normal throughput") yield Bit(self, "high_rel", "If set, high relibility, else normal") yield NullBits(self, "reserved[]", 2, "(reserved for future use)") yield UInt16(self, "length") yield UInt16(self, "id") yield NullBits(self, "reserved[]", 1) yield Bit(self, "df", "Don't fragment") yield Bit(self, "more_frag", "There are more fragments? if not set, it's the last one") yield Bits(self, "frag_ofst_lo", 5) yield UInt8(self, "frag_ofst_hi") yield UInt8(self, "ttl", "Type to live") yield Enum(UInt8(self, "protocol"), self.PROTOCOL_NAME) yield textHandler(UInt16(self, "checksum"), hexadecimal) yield IPv4_Address(self, "src") yield IPv4_Address(self, "dst") size = (self.size - self.current_size) // 8 if size: yield RawBytes(self, "options", size)
def createFields(self): # Header yield NullBytes(self, "zero_vector", 16) yield GUID(self, "fs_guid") yield UInt64(self, "volume_len") yield String(self, "signature", 4) yield UInt32(self, "attributes") yield UInt16(self, "header_len") yield UInt16(self, "checksum") yield UInt16(self, "ext_header_offset") yield UInt8(self, "reserved") yield UInt8(self, "revision") while True: bm = BlockMap(self, "block_map[]") yield bm if bm['num_blocks'].value == 0 and bm['len'].value == 0: break # TODO must handle extended header # Content while not self.eof: padding = paddingSize(self.current_size // 8, 8) if padding: yield PaddingBytes(self, "padding[]", padding) yield File(self, "file[]")
def createFields(self): yield String(self, "header_id", 4, "Playlist Header Markup (\"mhyp\")", charset="ISO-8859-1") yield UInt32(self, "header_length", "Header Length") yield UInt32(self, "entry_length", "Entry Length") yield UInt32(self, "data_object_child_count", "Number of Child Data Objects") yield UInt32(self, "playlist_count", "Number of Playlist Items") yield Enum(UInt8(self, "type", "Normal or master playlist?"), self.is_master_pl_name) yield UInt8(self, "XXX1", "XXX1") yield UInt8(self, "XXX2", "XXX2") yield UInt8(self, "XXX3", "XXX3") yield TimestampMac32(self, "creation_date", "Date when the playlist was created") yield UInt64(self, "playlistid", "Persistent Playlist ID") yield UInt32(self, "unk3", "unk3") yield UInt16(self, "string_mhod_count", "Number of string MHODs for this playlist") yield Enum(UInt16(self, "is_podcast", "Playlist or Podcast List?"), self.is_podcast_name) yield Enum(UInt32(self, "sort_order", "Playlist Sort Order"), self.list_sort_order_name) padding = self.seekByte(self["header_length"].value, "entry padding") if padding: yield padding for i in range(self["data_object_child_count"].value): yield DataObject(self, "mhod[]") for i in range(self["playlist_count"].value): yield PlaylistItem(self, "playlist_item[]")
def createFields(self): yield Bytes(self, "endian", 2, "Endian (\\xfe\\xff for little endian)") yield UInt16(self, "format", "Format (0)") yield UInt8(self, "os_version") yield UInt8(self, "os_revision") yield Enum(UInt16(self, "os_type"), OS_NAME) yield GUID(self, "format_id") yield UInt32(self, "section_count") if MAX_SECTION_COUNT < self["section_count"].value: raise ParserError("OLE2: Too much sections (%s)" % self["section_count"].value) section_indexes = [] for index in range(self["section_count"].value): section_index = SummaryIndex(self, "section_index[]") yield section_index section_indexes.append(section_index) for section_index in section_indexes: self.seekByte(section_index["offset"].value) yield SummarySection(self, "section[]") size = (self.size - self.current_size) // 8 if 0 < size: yield NullBytes(self, "end_padding", size)
def createFields(self): yield Bytes(self, "header", 4, r"PE header signature (PE\0\0)") if self["header"].value != b"PE\0\0": raise ParserError("Invalid PE header signature") yield Enum(UInt16(self, "cpu", "CPU type"), self.cpu_name) yield UInt16(self, "nb_section", "Number of sections") yield TimestampUnix32(self, "creation_date", "Creation date") yield UInt32(self, "ptr_to_sym", "Pointer to symbol table") yield UInt32(self, "nb_symbols", "Number of symbols") yield UInt16(self, "opt_hdr_size", "Optional header size") yield Bit(self, "reloc_stripped", "If true, don't contain base relocations.") yield Bit(self, "exec_image", "Executable image?") yield Bit(self, "line_nb_stripped", "COFF line numbers stripped?") yield Bit(self, "local_sym_stripped", "COFF symbol table entries stripped?") yield Bit(self, "aggr_ws", "Aggressively trim working set") yield Bit(self, "large_addr", "Application can handle addresses greater than 2 GB") yield NullBits(self, "reserved", 1) yield Bit(self, "reverse_lo", "Little endian: LSB precedes MSB in memory") yield Bit(self, "32bit", "Machine based on 32-bit-word architecture") yield Bit(self, "is_stripped", "Debugging information removed?") yield Bit(self, "swap", "If image is on removable media, copy and run from swap file") yield PaddingBits(self, "reserved2", 1) yield Bit(self, "is_system", "It's a system file") yield Bit(self, "is_dll", "It's a dynamic-link library (DLL)") yield Bit(self, "up", "File should be run only on a UP machine") yield Bit(self, "reverse_hi", "Big endian: MSB precedes LSB in memory")
def createFields(self): yield UInt16(self, "unknown[]") yield UInt16(self, "unknown[]") yield UInt32(self, "count") yield UInt32(self, "unknown[]") yield UInt32(self, "unknown[]") for i in range(self['count'].value): yield ThumbsCatalog.ThumbsEntry(self, "entry[]")
def createFields(self): yield Enum(UInt16(self, "type"), self.BLOCK_TYPE) if self["type"].value == 0: return yield UInt16(self, "size") size = self["size"].value if size: yield RawBytes(self, "data", size)
def commentHeader(s): yield filesizeHandler( UInt16(s, "total_size", "Comment header size + comment size")) yield filesizeHandler( UInt16(s, "uncompressed_size", "Uncompressed comment size")) yield UInt8(s, "required_version", "RAR version needed to extract comment") yield UInt8(s, "packing_method", "Comment packing method") yield UInt16(s, "comment_crc16", "Comment CRC")
def createFields(self): yield UInt16(self, "length", "Length of name list in 2-byte blocks") yield UInt16(self, "count", "Number of entries in name list") for index in range(self["count"].value): length = UInt16( self, "name_len[]", "Length of name in 2-byte blocks, excluding terminating null") yield length yield String(self, "name[]", length.value * 2 + 2, charset="UTF-16-LE")
def createFields(self): yield Enum(UInt8(self, "type"), self.TYPE_DESC) yield UInt8(self, "code") yield textHandler(UInt16(self, "checksum"), hexadecimal) if self['type'].value in (self.ECHO_REQUEST, self.ECHO_REPLY): yield UInt16(self, "id") yield UInt16(self, "sequence")
def createFields(self): # Gzip header yield Bytes(self, "signature", 2, r"GZip file signature (\x1F\x8B)") yield Enum(UInt8(self, "compression", "Compression method"), self.COMPRESSION_NAME) # Flags yield Bit(self, "is_text", "File content is probably ASCII text") yield Bit(self, "has_crc16", "Header CRC16") yield Bit(self, "has_extra", "Extra informations (variable size)") yield Bit(self, "has_filename", "Contains filename?") yield Bit(self, "has_comment", "Contains comment?") yield NullBits(self, "reserved[]", 3) yield TimestampUnix32(self, "mtime", "Modification time") # Extra flags yield NullBits(self, "reserved[]", 1) yield Bit(self, "slowest", "Compressor used maximum compression (slowest)") yield Bit(self, "fastest", "Compressor used the fastest compression") yield NullBits(self, "reserved[]", 5) yield Enum(UInt8(self, "os", "Operating system"), self.os_name) # Optional fields if self["has_extra"].value: yield UInt16(self, "extra_length", "Extra length") yield RawBytes(self, "extra", self["extra_length"].value, "Extra") if self["has_filename"].value: yield CString(self, "filename", "Filename", charset="ISO-8859-1") if self["has_comment"].value: yield CString(self, "comment", "Comment") if self["has_crc16"].value: yield textHandler(UInt16(self, "hdr_crc16", "CRC16 of the header"), hexadecimal) if self._size is None: # TODO: is it possible to handle piped input? raise NotImplementedError() # Read file size = (self._size - self.current_size) // 8 - 8 # -8: crc32+size if 0 < size: if self["has_filename"].value: filename = self["filename"].value else: for tag, filename in self.stream.tags: if tag == "filename" and filename.endswith(".gz"): filename = filename[:-3] break else: filename = None yield Deflate(SubFile(self, "file", size, filename=filename)) # Footer yield textHandler( UInt32(self, "crc32", "Uncompressed data content CRC32"), hexadecimal) yield filesizeHandler(UInt32(self, "size", "Uncompressed size"))
def createFields(self): yield UInt8(self, "precision") yield UInt16(self, "height") yield UInt16(self, "width") yield UInt8(self, "nr_components") for index in range(self["nr_components"].value): yield SOFComponent(self, "component[]")
def createFields(self): yield textHandler( UInt32(self, "signature", "Placeable Metafiles signature (0x9AC6CDD7)"), hexadecimal) yield UInt16(self, "handle") yield RECT16(self, "rect") yield UInt16(self, "inch") yield NullBytes(self, "reserved", 4) yield textHandler(UInt16(self, "checksum"), hexadecimal)
def createFields(self): yield UInt32(self, "header_size", r"Header length (9)") yield UInt8(self, "packing_type", r"Packing type (always 0)") yield UInt16(self, "rows", r"Number of rows in pattern (1..256)") yield UInt16(self, "data_size", r"Packed patterndata size") rows = self["rows"].value self.info("Pattern: %i rows" % rows) for index in range(rows): yield Row(self, "row[]")