def check_messages(checkables: Iterable[Checkable], **kw) -> ComparableLists: msgs = run_checkables(checkables) if kw.get("state") != MessageType.CONFIRMED: # Normally, ignore confirmation messages: msgs = [m for m in msgs if m.state != MessageType.CONFIRMED] else: # When we want CONFIRMED, take the message with the worst status: msgs = [max(msgs, key=lambda m: m.state)] default_msg = AnalysisMessage(MessageType.CANNOT_CONFIRM, "", "", 0, 0, "") msg = msgs[0] if msgs else replace(default_msg) fields = ( "state", "message", "filename", "line", "column", "traceback", "test_fn", "condition_src", ) for k in fields: if k not in kw: default_val = getattr(default_msg, k) msg = replace(msg, **{k: default_val}) kw[k] = default_val if msgs: msgs[0] = msg return (msgs, [AnalysisMessage(**kw)])
def check_messages(msgs: List[AnalysisMessage], **kw) -> ComparableLists: default_msg = AnalysisMessage(MessageType.CANNOT_CONFIRM, '', '', 0, 0, '') msg = msgs[0] if msgs else replace(default_msg) fields = ('state', 'message', 'filename', 'line', 'column', 'traceback', 'execution_log', 'test_fn', 'condition_src') for k in fields: if k not in kw: default_val = getattr(default_msg, k) msg = replace(msg, **{k: default_val}) kw[k] = default_val if msgs: msgs[0] = msg return (msgs, [AnalysisMessage(**kw)])
def check_file_changed( self, curfile: str) -> Tuple[List[WatchedMember], List[AnalysisMessage]]: members = [] path_to_root, module_name = extract_module_from_file(curfile) debug(f'Attempting to import {curfile} as module "{module_name}"') if path_to_root not in sys.path: sys.path.append(path_to_root) try: module = importlib.import_module(module_name) importlib.reload(module) except Exception: exc_type, exc_value, exc_traceback = sys.exc_info() assert exc_traceback is not None lineno = exception_line_in_file( traceback.extract_tb(exc_traceback), curfile) if lineno is None: lineno = 1 debug( f'Unable to load module "{module_name}" in {curfile}: {exc_type}: {exc_value}' ) return ([], [ AnalysisMessage(MessageType.IMPORT_ERR, str(exc_value), curfile, lineno, 0, '') ]) for (name, member) in analyzable_members(module): qualname = module.__name__ + '.' + member.__name__ src = inspect.getsource(member) members.append(WatchedMember(qualname, src)) return (members, [])
def pool_worker_main(item: WorkItemInput, output: multiprocessing.queues.Queue) -> None: try: # TODO figure out a more reliable way to suppress this. Redirect output? # Ignore ctrl-c in workers to reduce noisy tracebacks (the parent will kill us): signal.signal(signal.SIGINT, signal.SIG_IGN) if hasattr(os, 'nice'): # analysis should run at a low priority os.nice(10) set_debug(False) filename, options, deadline = item stats: Counter[str] = Counter() options.stats = stats _, module_name = extract_module_from_file(filename) try: module = load_by_qualname(module_name) except NotFound: return except ErrorDuringImport as e: orig, frame = e.args message = AnalysisMessage(MessageType.IMPORT_ERR, str(orig), frame.filename, frame.lineno, 0, '') output.put((filename, stats, [message])) debug(f'Not analyzing "{filename}" because import failed: {e}') return messages = analyze_any(module, options) output.put((filename, stats, messages)) except BaseException as e: raise CrosshairInternal('Worker failed while analyzing ' + filename) from e
def check_messages(msgs: List[AnalysisMessage], **kw) -> ComparableLists: if kw.get('state') != MessageType.CONFIRMED: # Normally, ignore confirmation messages: msgs = [m for m in msgs if m.state != MessageType.CONFIRMED] else: # When we are checking confirmation, just check one: msgs = [msgs[0]] default_msg = AnalysisMessage(MessageType.CANNOT_CONFIRM, '', '', 0, 0, '') msg = msgs[0] if msgs else replace(default_msg) fields = ('state', 'message', 'filename', 'line', 'column', 'traceback', 'execution_log', 'test_fn', 'condition_src') for k in fields: if k not in kw: default_val = getattr(default_msg, k) msg = replace(msg, **{k: default_val}) kw[k] = default_val if msgs: msgs[0] = msg return (msgs, [AnalysisMessage(**kw)])
def showresults(args: argparse.Namespace, options: AnalysisOptions) -> int: messages_by_file: Dict[ str, List[AnalysisMessage]] = collections.defaultdict(list) states = list(read_states()) for fname, content in states: debug('Found watch state file at ', fname) state = json.loads(content) for message in state['messages']: messages_by_file[message['filename']].append( AnalysisMessage.fromJSON(message)) debug('Found results for these files: [', ', '.join(messages_by_file.keys()), ']') for name in walk_paths(args.files): name = os.path.abspath(name) debug('Checking file ', name) for message in messages_by_file[name]: desc = short_describe_message(message) debug('Describing ', message) if desc is not None: print(desc) return 0