def __iter__(self): # pylint: disable=too-many-branches """Iterate over messages in the file""" logger.debug("Starting File Read") logger.debug("File Position: %d File Counter: %d File Name: %s", self.file_position, self.counter, self.filename) cached_mtime = 0 cached_file_pos = 0 corruption_check_try = True self._open_file() found_data = False while not self.stop_reading.isSet() or corruption_check_try: # pylint: disable=too-many-nested-blocks os_stat = os.stat(self.filename) mtime = os_stat.st_mtime if mtime != cached_mtime and os_stat.st_size or corruption_check_try: cached_mtime = mtime corruption_check_try = False while dltlib.dlt_file_read(ctypes.byref(self), self.verbose) >= DLT_RETURN_OK: found_data = True if self.filter and dltlib.dlt_message_filter_check( ctypes.byref(self.msg), self.filter, 0) != DLT_RETURN_TRUE: continue index = self.position msg = self[index] if not index % 100000: self._log_message_progress() yield msg if cached_file_pos != self.file_position: # We were able to read messages, don't do a corrupt message check yet. corruption_check_try = True cached_file_pos = self.file_position else: next_header_position = self._find_next_header() if next_header_position: if self.file_position == next_header_position: if not self.live_run: logger.warning("Incomplete message while parsing DLT file at %s", self.file_position) break else: logger.warning("Found a corrupt message at %s, skipping it", self.file_position) self.file_position = next_header_position self.corrupt_msg_count += 1 corruption_check_try = True # Wait for further messages to determine if corrupt, else just end of file else: if not self.live_run: logger.info("End of file reached at %s", self.file_position) break time.sleep(0.1) if not found_data: raise IOError(DLT_EMPTY_FILE_ERROR)
def compare(self, other=None): # pylint: disable=too-many-return-statements,too-many-branches """Compare messages by given attributes :param [DLTMessage|DLTFilter|dict] other: DLTMessage object (or DLTFilter or a dict with selected keys) to compare with. Use DLTFilter object with APID,CTID pairs for the best performance. :returns: True if all attributes match or False if any of the given attributes differs :rtype: bool :raises TypeError: if other is neither DLTMessage nor a dictionary Example: message.compare(other=message2) message.compare(message2) message.compare(other=dict(apid="AP1", ctid="CT1")) message.compare(dict(apid="AP1", ctid="CT1")) message.compare(dict(apid=re.compile(r"^A.*")) # match all messages which apid starting with A message.compare(dict(apid="AP1", ctid="CT1", payload_decoded=re.compile(r".connected.*"))) """ if hasattr(other, "apid") and hasattr(other, "ctid") and hasattr(other, "payload_decoded"): # other is DLTMessage - full compare return self.apid == other.apid and self.ctid == other.ctid and self.__eq__(other) # pylint: disable=protected-access if hasattr(other, "_fields_") and [x[0] for x in other._fields_] == ["apid", "ctid", "counter"]: # other id DLTFilter return dltlib.dlt_message_filter_check(ctypes.byref(self), ctypes.byref(other), 0) if not isinstance(other, dict): raise TypeError("other must be instance of mgu_dlt.dlt.DLTMessage, mgu_dlt.dlt.DLTFilter or a dictionary" " found: {}".format(type(other))) other = other.copy() apid = other.get("apid", None) if apid and not isinstance(apid, re._pattern_type) and self.apid != apid: # pylint: disable=protected-access return False ctid = other.get("ctid", None) if ctid and not isinstance(ctid, re._pattern_type) and self.ctid != ctid: # pylint: disable=protected-access return False for key, val in other.items(): if val is None: continue key = key.rsplit(".", 1)[-1] # In case the obsolete "extendedheader.apid" notation is used msg_val = getattr(self, key, "") if not msg_val: return False if isinstance(val, re._pattern_type): # pylint: disable=protected-access if not val.search(msg_val): return False elif msg_val != val: return False return True