From 211221a944c3d7fd3575915f8a3e363bf289c9ce Mon Sep 17 00:00:00 2001 From: Marius Smytzek Date: Wed, 29 May 2024 11:45:00 +0200 Subject: [PATCH] updated analyzer with coverage --- BugsInPy.ipynb | 1177 ++++---------------------- Demo.ipynb | 440 ++-------- src/sflkit/analysis/analysis_type.py | 1 + src/sflkit/analysis/analyzer.py | 31 +- src/sflkit/analysis/spectra.py | 1 - src/sflkit/model/event_file.py | 7 +- src/sflkit/model/model.py | 5 +- tests/test_coverage.py | 19 + 8 files changed, 280 insertions(+), 1401 deletions(-) create mode 100644 tests/test_coverage.py diff --git a/BugsInPy.ipynb b/BugsInPy.ipynb index ece588c..4605ea5 100644 --- a/BugsInPy.ipynb +++ b/BugsInPy.ipynb @@ -29,31 +29,16 @@ "execution_count": 3, "id": "6fe1d278", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Collecting whatthepatch\n", - " Downloading whatthepatch-1.0.5-py3-none-any.whl (11 kB)\n", - "Installing collected packages: whatthepatch\n", - "Successfully installed whatthepatch-1.0.5\n", - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip available: \u001b[0m\u001b[31;49m22.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.1.2\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" - ] - } - ], "source": [ "!pip install whatthepatch" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 5, "id": "71944b13-ca1f-4f5b-b1dd-7f0447e01626", "metadata": {}, - "outputs": [], "source": [ "import json\n", "import hashlib\n", @@ -66,7 +51,8 @@ "from typing import List, Set\n", "from xml.etree import ElementTree as etree\n", "from sflkit.analysis.suggestion import Location" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -81,105 +67,83 @@ "execution_count": 6, "id": "7a4db981-8306-4bb0-88d8-5b3f711adaee", "metadata": {}, - "outputs": [], "source": [ "subject_selection = False\n", "continue_subject_selection = True" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 7, "id": "6d269bfe-e9eb-43ac-977f-6bed9080173e", "metadata": {}, - "outputs": [], "source": [ "events_extraction = True\n", "continue_events_extraction = True" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 8, "id": "41cfb43a-fa07-49d4-82e3-b1a0cb04971f", "metadata": {}, - "outputs": [], "source": [ "tmp = '/tmp'\n", "subjects_file = 'subjects.json'\n", "default_project = 'project'\n", "events_path = 'EVENTS_PATH'\n", "config_tmp = 'tmp.ini'" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 9, "id": "84c154e6-9bd3-4a46-9604-73a895457f45", "metadata": {}, - "outputs": [], "source": [ "def get_dir(p):\n", " return os.path.join(tmp, p)\n", "\n", "def clean_project(project):\n", " shutil.rmtree(get_dir(project), ignore_errors=True)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 10, "id": "54609932-e26f-4fd1-86b6-b6e49fa78fde", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'/Users/marius/Desktop/work/projects/sflkit'" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "sflkit_dir = os.path.abspath('.')\n", "sflkit_dir" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 11, "id": "93d35204-e3a9-4911-a7cf-a588d08fc2ef", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'/Users/marius/Desktop/work/projects/sflkit/events'" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "events_output = os.path.abspath('events')\n", "events_output" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 12, "id": "deb300c5-7fd1-4ada-9198-566cdd859b61", "metadata": {}, - "outputs": [], "source": [ "PASSED = 'PASSED'\n", "FAILED = 'FAILED'" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -194,7 +158,6 @@ "execution_count": 13, "id": "106b4a86-48a2-46b1-94fe-e447df2b7647", "metadata": {}, - "outputs": [], "source": [ "bip_info = 'bugsinpy-info'\n", "bip_checkout = 'bugsinpy-checkout'\n", @@ -207,14 +170,14 @@ " 'bugsinpy_bug_patch.txt',\n", " 'bugsinpy_patchfile.info'\n", "]" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 14, "id": "cb6dc70f-82cc-4475-9cbe-3d481e914cea", "metadata": {}, - "outputs": [], "source": [ "projects = [\n", " 'PySnooper',\n", @@ -235,48 +198,48 @@ " 'tqdm',\n", " 'youtube-dl'\n", "]" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 15, "id": "65b9d0a4-2d20-4326-88a2-8a7a6a9ee8f2", "metadata": {}, - "outputs": [], "source": [ "for project in projects:\n", " globals()[project.replace('-', '_')] = project\n", " clean_project(project)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 16, "id": "37e38835-1276-4db0-9a64-41d3e13df982", "metadata": {}, - "outputs": [], "source": [ "excluded_subjects = [matplotlib, pandas, spacy]\n", "max_bugs_per_subject = 500" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 17, "id": "ce05a37b-ae11-4009-9e48-d1a5b65ff51a", "metadata": {}, - "outputs": [], "source": [ "test_project = PySnooper\n", "test_bug_id = 3" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 18, "id": "362b469d-6c69-4642-8932-a5ea97873716", "metadata": {}, - "outputs": [], "source": [ "number_of_bugs_pattern = re.compile(r'Number\\s*of\\s*bugs\\s*:\\s*(?P\\d+)')\n", "\n", @@ -285,24 +248,24 @@ " match = number_of_bugs_pattern.search(process.stdout.decode('utf8'))\n", " if match:\n", " return int(match.group('bugs'))" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 19, "id": "b67456e2-3039-4a4d-a45c-bc9c40d3583d", "metadata": {}, - "outputs": [], "source": [ "assert get_bugs(test_project) == 3" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 20, "id": "97fb587c-8706-4436-94f9-7ff3dcd79e4b", "metadata": {}, - "outputs": [], "source": [ "test_file_pattern = re.compile(r'Triggering\\s*test\\s*file\\s*(?P[^\\n]+)')\n", "\n", @@ -311,25 +274,25 @@ " match = test_file_pattern.search(process.stdout.decode('utf8'))\n", " if match:\n", " return match.group('test_file')" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 21, "id": "f832b7ac-1b57-4c42-acf3-c05e2796850e", "metadata": {}, - "outputs": [], "source": [ "test_test_file = get_test_file(test_project, test_bug_id)\n", "assert test_test_file == 'tests/test_pysnooper.py'" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 22, "id": "4d2c4307-626c-4c7c-8494-d641fbe5cfa0", "metadata": {}, - "outputs": [], "source": [ "def get_project(project: str, buggy: bool = True, bug_id: int = 0, delete: bool = False, verbose: bool = False):\n", " if delete:\n", @@ -338,27 +301,27 @@ " stdout=None if verbose else subprocess.DEVNULL,\n", " stderr=subprocess.STDOUT if verbose else subprocess.DEVNULL)\n", " assert process.returncode == 0" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 23, "id": "a02a4869-32d7-4e92-bd5a-7651820f8332", "metadata": {}, - "outputs": [], "source": [ "def is_unittest(project):\n", " with open(os.path.join(get_dir(project), run_test_file), 'r') as fp:\n", " s = fp.read()\n", " return 'unittest' in s" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 24, "id": "9dea83dd-812b-43d7-8579-7963a3d6e6cf", "metadata": {}, - "outputs": [], "source": [ "version_pattern = re.compile(r'python_version=\"(?P[^\\\"]+)\"')\n", "\n", @@ -379,14 +342,14 @@ " process = subprocess.run(['pip', 'install', '--upgrade', 'pip'], \n", " stdout=None if verbose else subprocess.DEVNULL,\n", " stderr=subprocess.STDOUT if verbose else subprocess.DEVNULL)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 25, "id": "21c43449-662d-42c9-b8e4-2ad5099948b9", "metadata": {}, - "outputs": [], "source": [ "def setup_project(project: str, verbose: bool = False):\n", " env_on(project, verbose=verbose)\n", @@ -394,26 +357,26 @@ " stdout=None if verbose else subprocess.DEVNULL,\n", " stderr=subprocess.STDOUT if verbose else subprocess.DEVNULL, env=os.environ)\n", " assert process.returncode == 0" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 26, "id": "8fcfecfb-ddd0-4173-9b87-1da35a89ff87", "metadata": {}, - "outputs": [], "source": [ "def install_project(project: str, bug_id: int, buggy: bool = True, delete: bool = True, verbose: bool = False):\n", " get_project(project, buggy=buggy, bug_id=bug_id, verbose=verbose)\n", " setup_project(project, verbose=verbose)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 27, "id": "1cf603b1-a683-4d47-8fe9-bb461722548c", "metadata": {}, - "outputs": [], "source": [ "NEWLINE_TOKEN = 'SDNEWLINE'\n", "\n", @@ -487,14 +450,14 @@ " (len(list(testcase)) == 2 and (testcase.find('system-out') is not None and testcase.find('system-err') is not None))):\n", " tests.append((test, PASSED))\n", " return tests" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 28, "id": "d6e48520-de25-44aa-8e80-6f6ab1a6f086", "metadata": {}, - "outputs": [], "source": [ "def get_tests(project: str, test_file: str, verbose: bool = False):\n", " tmp_file = os.path.join(get_dir(project), 'tmp.xml')\n", @@ -523,156 +486,112 @@ " elif s == FAILED:\n", " failing.append(t)\n", " return passing, failing" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 29, "id": "d22a6a38-393a-4e91-8f0a-fa513a87d37f", "metadata": {}, - "outputs": [], "source": [ "def verify_correct_version(project: str, bug_id: int, test_file: str, verbose: bool = False):\n", " install_project(project, bug_id, buggy=False, verbose=verbose)\n", " passing, failing = get_tests(project, test_file, verbose=verbose)\n", " return len(failing) == 0 and len(passing) > 0" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 30, "id": "7ddd63f4-5d9b-46e1-b1ad-e6bbe630cb6b", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "pytest did not generate file\n" - ] - }, - { - "ename": "AssertionError", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[30], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[39massert\u001b[39;00m verify_correct_version(test_project, test_bug_id, test_test_file)\n", - "\u001b[0;31mAssertionError\u001b[0m: " - ] - } - ], "source": [ "assert verify_correct_version(test_project, test_bug_id, test_test_file)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 27, "id": "589f7dd6-6c2d-4091-ab6e-e0af3180bf82", "metadata": {}, - "outputs": [], "source": [ "install_project(test_project, bug_id=test_bug_id)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 28, "id": "45ef8657-48f6-42a9-9e35-1280e2225ce2", "metadata": {}, - "outputs": [], "source": [ "assert not is_unittest(test_project)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 29, "id": "0ab6bf87-130b-48e3-ba9d-75092a27f2d9", "metadata": {}, - "outputs": [], "source": [ "test_passing, test_failing = get_tests(test_project, test_test_file)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 30, "id": "6639244a-b19c-4ebf-9dc3-8689268edb20", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['tests/test_pysnooper.py::test_string_io',\n", - " 'tests/test_pysnooper.py::test_variables',\n", - " 'tests/test_pysnooper.py::test_depth',\n", - " 'tests/test_pysnooper.py::test_method_and_prefix']" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "test_passing" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 31, "id": "cffdf1ad-0e61-4370-af5d-4980dd8177fa", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['tests/test_pysnooper.py::test_file_output']" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "test_failing" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 32, "id": "e9d91d53-dafe-4352-aa5a-5e2dd59a14a2", "metadata": {}, - "outputs": [], "source": [ "def run_test(project: str, test_case: str, verbose: bool = False):\n", " passing, failing = get_tests(project, test_case, verbose=verbose)\n", " return len(passing) > 0 and len(failing) == 0" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 33, "id": "8867aec5-03e9-4658-88bc-749b4765f3a3", "metadata": {}, - "outputs": [], "source": [ "for t in test_passing:\n", " assert run_test(test_project, t)\n", "for t in test_failing:\n", " assert not run_test(test_project, t)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 34, "id": "5ed1595e-dd34-42a3-a20c-ab026e452c3d", "metadata": {}, - "outputs": [], "source": [ "def get_faulty_lines(project: str):\n", " locations = list()\n", @@ -695,42 +614,25 @@ " except (IOError, whatthepatch.exceptions.WhatThePatchException):\n", " pass\n", " return locations" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 35, "id": "ca900924-c5a9-4a2e-a1c4-951d69618eb4", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[pysnooper/pysnooper.py:23,\n", - " pysnooper/pysnooper.py:24,\n", - " pysnooper/pysnooper.py:25,\n", - " pysnooper/pysnooper.py:26,\n", - " pysnooper/pysnooper.py:27,\n", - " pysnooper/pysnooper.py:28,\n", - " pysnooper/pysnooper.py:29]" - ] - }, - "execution_count": 35, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "test_faulty_lines = get_faulty_lines(test_project)\n", "test_faulty_lines" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 36, "id": "8e4b9e48-aa2f-4158-b7bc-735532c78c5c", "metadata": {}, - "outputs": [], "source": [ "class Subject:\n", " def __init__(self, project: str, bug_id: int, passing: List[str], failing: List[str], is_unittest_: bool, faulty_lines: List[Location]):\n", @@ -766,14 +668,14 @@ " @staticmethod\n", " def deserialize(values: dict):\n", " return Subject(values['project'], values['bugId'], values['passing'], values['failing'], values['is_unittest'], [Location(file, line) for file, line in values['faulty_lines']])" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 37, "id": "864d96db-0323-44c5-82cc-cd1b11c5b415", "metadata": {}, - "outputs": [], "source": [ "def verify_project(project: str, bug_id: int, fast: bool = False, verbose=False) -> Subject:\n", " install_project(project, bug_id=bug_id, verbose=verbose)\n", @@ -789,70 +691,35 @@ " else:\n", " print(f' {project:<40}{bug_id:<3} - Failing tests on correct version')\n", " return Subject(project, bug_id, passing, failing, is_unittest(project), get_faulty_lines(project))" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 38, "id": "32ff893b-4149-496d-ab58-327f2212ffbb", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " PySnooper 3 \n" - ] - }, - { - "data": { - "text/plain": [ - "Subject(project=PySnooper,bugId=3,#passing=4,#failing=1)" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "test_subject = verify_project(test_project, test_bug_id)\n", "test_subject" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 39, "id": "94366ba5-55e0-4f71-961e-5ab8091b3199", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[pysnooper/pysnooper.py:23,\n", - " pysnooper/pysnooper.py:24,\n", - " pysnooper/pysnooper.py:25,\n", - " pysnooper/pysnooper.py:26,\n", - " pysnooper/pysnooper.py:27,\n", - " pysnooper/pysnooper.py:28,\n", - " pysnooper/pysnooper.py:29]" - ] - }, - "execution_count": 39, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "test_subject.faulty_lines" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 40, "id": "025371d6-23e6-43c8-82de-37d504f5485e", "metadata": {}, - "outputs": [], "source": [ "def get_all_valid(found_subjects: list = None, fast: bool = False, excludes: list = None, max_number: int = None):\n", " \n", @@ -875,14 +742,14 @@ " return subjects\n", " finally:\n", " globals()['subjects'] = subjects" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 41, "id": "1827e90b-3bf2-416b-b658-3667b312186e", "metadata": {}, - "outputs": [], "source": [ "if subject_selection:\n", " if continue_subject_selection:\n", @@ -903,83 +770,47 @@ " json_subjects = json.load(fp)\n", " for values in json_subjects:\n", " subjects.append(Subject.deserialize(values))" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 42, "id": "a0aa5102-a5d9-40c2-a35c-e65f00bc4855", "metadata": {}, - "outputs": [], "source": [ "if subject_selection:\n", " with open(subjects_file, 'w') as fp:\n", " json.dump(list(map(Subject.serialize, subjects)), fp, indent = 4)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 43, "id": "1d7cb84e-25c2-4ce1-b1c1-d8f9cadab2a5", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "40" - ] - }, - "execution_count": 43, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "len(subjects)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 44, "id": "95e0f584-f802-4540-a485-ccdafc23df42", "metadata": {}, - "outputs": [], "source": [ "for subject in subjects:\n", " globals()[f'subject_{subject.project.replace(\"-\", \"_\")}_{subject.bug_id}'] = subject" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 45, "id": "6efc3f7d-7470-482f-8bbd-dfd864cc9286", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "project bugs used tests \n", - "PySnooper 3 1 5 \n", - "ansible 18 3 245 \n", - "black 23 3 372 \n", - "cookiecutter 4 3 26 \n", - "fastapi 16 3 20 \n", - "httpie 5 3 37 \n", - "keras 45 3 199 \n", - "luigi 33 3 216 \n", - "matplotlib 30 0 0 \n", - "pandas 169 0 0 \n", - "sanic 5 3 158 \n", - "scrapy 40 3 53 \n", - "spacy 10 0 0 \n", - "thefuck 32 3 65 \n", - "tornado 16 3 146 \n", - "tqdm 9 3 153 \n", - "youtube-dl 43 3 164 \n" - ] - } - ], "source": [ "stats = {p: {'bugs': get_bugs(p), 'used': 0, 'tests': 0} for p in projects}\n", "\n", @@ -991,7 +822,8 @@ "\n", "for p in stats:\n", " print(f'{p:<20}{stats[p][\"bugs\"]:<6}{stats[p][\"used\"]:<6}{stats[p][\"tests\"]:<6}')" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -1006,30 +838,29 @@ "execution_count": 46, "id": "6a2c2c4a-d229-44e3-b8b3-a47a4064d42b", "metadata": {}, - "outputs": [], "source": [ "from sflkit import instrument, analyze\n", "from sflkit.config import Config\n", "from sflkit.analysis.analysis_type import AnalysisType\n", "from sflkit.analysis.suggestion import Suggestion" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 47, "id": "725ee1e9-5475-4bb1-90f8-89916be26fd4", "metadata": {}, - "outputs": [], "source": [ "from configparser import ConfigParser" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 48, "id": "3f4f90e5-21d8-475e-a577-f6a5b69f33b1", "metadata": {}, - "outputs": [], "source": [ "def generate_config(project, dst, excluded_project_files, passing, failing):\n", " config = ConfigParser()\n", @@ -1049,7 +880,8 @@ " config['instrumentation']['exclude'] = '\"' + '\",\"'.join(excluded_project_files) + '\"'\n", " with open(config_tmp, 'w') as fp:\n", " config.write(fp)" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -1064,19 +896,18 @@ "execution_count": 49, "id": "fb9a1a7a-0e14-4275-85ee-053a781c2830", "metadata": {}, - "outputs": [], "source": [ "excluded_project_files = ['test', 'tests', 'setup.py', 'env', 'build', 'bin', 'docs', 'examples', \n", " 'hacking', '.git', '.github', 'extras', 'profiling', 'plugin', 'gallery', \n", " 'blib2to3', 'docker', 'contrib', 'changelogs', 'licenses', 'packaging']" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 50, "id": "9ba3df7e-141d-4919-a41a-ad23306aace9", "metadata": {}, - "outputs": [], "source": [ "excluded_tests = [\n", " 'tests/test_black.py::BlackTestCase::test_self',\n", @@ -1089,25 +920,25 @@ " 'tests/test_black.py::BlackTestCase::test_expression_ff',\n", " 'tests/test_black.py::BlackTestCase::test_expression',\n", "]" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 51, "id": "9b9d2f7a-bb4d-4872-9772-d1c877eb397f", "metadata": {}, - "outputs": [], "source": [ "def get_path(project: str, bug_id: int, passing: bool = True):\n", " return os.path.join(events_output, project, str(bug_id), 'passing' if passing else 'failing')" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 52, "id": "07de2d2a-625c-4fdd-b2c2-58a200d3feeb", "metadata": {}, - "outputs": [], "source": [ "def instrument_and_install_project(project: str, bug_id: int, dst: str, verbose=False):\n", " shutil.rmtree(dst, ignore_errors=True)\n", @@ -1119,57 +950,57 @@ " stdout=None if verbose else subprocess.DEVNULL,\n", " stderr=subprocess.STDOUT if verbose else subprocess.DEVNULL, env=os.environ)\n", " assert process.returncode == 0" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 53, "id": "1572018c-d6af-4d60-8c0c-c0697a1111ae", "metadata": {}, - "outputs": [], "source": [ "instrument_and_install_project(test_project, test_bug_id, default_project)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 54, "id": "3ec5843d-a850-4b31-a3b4-d274e924224d", "metadata": {}, - "outputs": [], "source": [ "def get_events_path_file(project: str):\n", " return os.path.join(get_dir(project), events_path)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 55, "id": "0de5fb30-3f9f-402b-8fb6-f1d5a42ab90c", "metadata": {}, - "outputs": [], "source": [ "class TestDiscard(Exception):\n", " pass" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 56, "id": "2e47fe6f-32a5-4ac1-8281-20666296aa1f", "metadata": {}, - "outputs": [], "source": [ "def get_file(test_case: str, passing: bool = True):\n", " return f'{\"p\" if passing else \"f\"}_{hashlib.md5(test_case.encode(\"utf8\")).hexdigest()}'" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 57, "id": "1b803d98-a5f1-4662-983e-6133b56faf0c", "metadata": {}, - "outputs": [], "source": [ "def get_events_path(project: str, bug_id: int, dst: str, test_case: str, passing: bool = True, verbose=False):\n", " if not os.path.exists(events_output):\n", @@ -1195,47 +1026,24 @@ " get_file(test_case, passing)))\n", " else:\n", " raise TestDiscard(f'Events path not found for {test_case}.')" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 58, "id": "df67911d-76c2-461e-bccc-6ace5a56aa2d", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "pytest -q -s tests/test_pysnooper.py::test_file_output\n", - "============================= test session starts ==============================\n", - "platform linux -- Python 3.8.1, pytest-7.0.1, pluggy-1.0.0\n", - "rootdir: /tmp/project\n", - "collected 1 item\n", - "\n", - "tests/test_pysnooper.py . [100%]\n", - "\n", - "=============================== warnings summary ===============================\n", - "env/lib/python3.8/site-packages/future-0.18.2-py3.8.egg/future/standard_library/__init__.py:65\n", - " /tmp/project/env/lib/python3.8/site-packages/future-0.18.2-py3.8.egg/future/standard_library/__init__.py:65: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses\n", - " import imp\n", - "\n", - "-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html\n", - "------------------- generated xml file: /tmp/project/tmp.xml -------------------\n", - "========================= 1 passed, 1 warning in 0.17s =========================\n" - ] - } - ], "source": [ "get_events_path(test_project, test_bug_id, default_project, test_passing[0], verbose=True)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 59, "id": "5dbbe504-d1ae-49bf-8cde-4dd02099475e", "metadata": {}, - "outputs": [], "source": [ "def get_all_events_paths(project: str, bug_id: int, dst: str, passing: List[str], failing: bool = List[str], verbose=False):\n", " p = 0\n", @@ -1266,83 +1074,57 @@ " \n", " print(f'{project:<40}{bug_id:<6}{p:<6}{f:<6}{d:<6}')\n", " return p > 0 and f > 0" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 60, "id": "f723e399-98cd-46bb-afde-c9bb8a16b13c", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "PySnooper 3 4 1 0 \n" - ] - } - ], "source": [ "assert get_all_events_paths(test_project, test_bug_id, default_project, test_passing, test_failing)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 61, "id": "5a676c98-2ca4-4927-9611-fa57068602fe", "metadata": {}, - "outputs": [], "source": [ "def extract_events_for_project(project: str, bug_id: int, dst: str, passing: List[str], failing: bool = List[str], verbose=False):\n", " instrument_and_install_project(project, bug_id, dst, verbose=verbose)\n", " return get_all_events_paths(project, bug_id, dst, passing, failing, verbose=verbose)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 62, "id": "565235c1-1ec9-4eed-97b8-19e6c425cba7", "metadata": {}, - "outputs": [], "source": [ "def extract_events(subject: Subject, dst: str, verbose=False):\n", " return extract_events_for_project(subject.project, subject.bug_id, dst, subject.passing, subject.failing, verbose=verbose)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 63, "id": "c2e4376c-3673-4c43-95da-21bd200d4398", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "PySnooper 3 4 1 0 \n" - ] - }, - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 63, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "extract_events(test_subject, default_project)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 64, "id": "6524a8b9-2668-4b84-969e-6435a7405cb8", "metadata": {}, - "outputs": [], "source": [ "def get_all_events(subjects: List[Subject], continue_: bool = False):\n", " for subject in subjects:\n", @@ -1352,65 +1134,19 @@ " p = len(os.listdir(get_path(subject.project, subject.bug_id, passing=True)))\n", " f = len(os.listdir(get_path(subject.project, subject.bug_id, passing=False)))\n", " print(f'{subject.project:<40}{subject.bug_id:<6}{p:<6}{f:<6}{len(subject.passing) - p + len(subject.failing) - f:<6}')" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 65, "id": "4ab19803-d881-40d6-a47e-993d061dee1e", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "PySnooper 3 4 1 0 \n", - "ansible 1 58 1 0 \n", - "ansible 2 130 2 0 \n", - "ansible 3 53 1 0 \n", - "black 1 117 1 11 \n", - "black 2 111 1 10 \n", - "black 3 110 1 10 \n", - "cookiecutter 1 10 1 0 \n", - "cookiecutter 2 7 3 0 \n", - "cookiecutter 3 1 4 0 \n", - "fastapi 1 11 1 0 \n", - "fastapi 2 5 1 0 \n", - "fastapi 4 1 1 0 \n", - "httpie 1 14 13 0 \n", - "httpie 2 2 1 0 \n", - "httpie 3 5 2 0 \n", - "keras 1 31 5 0 \n", - "keras 2 144 6 0 \n", - "keras 3 12 1 0 \n", - "luigi 1 46 17 5 \n", - "luigi 2 10 1 0 \n", - "luigi 3 136 1 0 \n", - "sanic 1 33 1 0 \n", - "sanic 4 117 1 0 \n", - "sanic 5 3 3 0 \n", - "scrapy 1 3 3 0 \n", - "scrapy 2 22 1 0 \n", - "scrapy 3 23 1 0 \n", - "thefuck 1 2 1 0 \n", - "thefuck 2 30 1 0 \n", - "thefuck 3 30 1 0 \n", - "tornado 1 45 1 0 \n", - "tornado 2 50 1 1 \n", - "tornado 3 48 1 -1 \n", - "tqdm 1 2 1 1 \n", - "tqdm 2 19 39 36 \n", - "tqdm 3 54 1 0 \n", - "youtube-dl 1 78 1 0 \n", - "youtube-dl 2 8 1 0 \n", - "youtube-dl 3 75 1 0 \n" - ] - } - ], "source": [ "if events_extraction:\n", " get_all_events(subjects, continue_=continue_events_extraction)" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -1425,12 +1161,12 @@ "execution_count": 66, "id": "1f6d0455-645d-4c5c-b5aa-0571ef5004bd", "metadata": {}, - "outputs": [], "source": [ "def get_results(project: str, bug_id: int, dst: str, verbose=False):\n", " config = generate_config(project, dst, excluded_project_files, get_path(project, bug_id, True), get_path(project, bug_id, False))\n", " return analyze(config_tmp)" - ] + ], + "outputs": [] }, { "cell_type": "code", @@ -1440,480 +1176,28 @@ "scrolled": true, "tags": [] }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'LINE': {'Ochiai': [[pysnooper/pysnooper.py:26]:1.0,\n", - " [pysnooper/pysnooper.py:24]:0.5773502691896258,\n", - " [pysnooper/tracer.py:137]:0.5,\n", - " [pysnooper/tracer.py:107]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:8]:0.4472135954999579,\n", - " [pysnooper/pycompat.py:20]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:16]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:14]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:15]:0.4472135954999579,\n", - " [pysnooper/pycompat.py:8]:0.4472135954999579,\n", - " [pysnooper/pycompat.py:19]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:5]:0.4472135954999579,\n", - " [pysnooper/tracer.py:108]:0.4472135954999579,\n", - " [pysnooper/pycompat.py:6]:0.4472135954999579,\n", - " [pysnooper/tracer.py:117]:0.4472135954999579,\n", - " [pysnooper/utils.py:5]:0.4472135954999579,\n", - " [pysnooper/tracer.py:132]:0.4472135954999579,\n", - " [pysnooper/tracer.py:118]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:6]:0.4472135954999579,\n", - " [pysnooper/tracer.py:14]:0.4472135954999579,\n", - " [pysnooper/tracer.py:42]:0.4472135954999579,\n", - " [pysnooper/tracer.py:43]:0.4472135954999579,\n", - " [pysnooper/tracer.py:111]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:4]:0.4472135954999579,\n", - " [pysnooper/tracer.py:166]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:65]:0.4472135954999579,\n", - " [pysnooper/tracer.py:8]:0.4472135954999579,\n", - " [pysnooper/__init__.py:6]:0.4472135954999579,\n", - " [pysnooper/tracer.py:4]:0.4472135954999579,\n", - " [pysnooper/tracer.py:6]:0.4472135954999579,\n", - " [pysnooper/tracer.py:5]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:10]:0.4472135954999579,\n", - " [pysnooper/tracer.py:133]:0.4472135954999579,\n", - " [pysnooper/tracer.py:10]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:9]:0.4472135954999579,\n", - " [pysnooper/tracer.py:173]:0.4472135954999579,\n", - " [pysnooper/tracer.py:22]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:72]:0.4472135954999579,\n", - " [pysnooper/tracer.py:13]:0.4472135954999579,\n", - " [pysnooper/tracer.py:150]:0.4472135954999579,\n", - " [pysnooper/__init__.py:8]:0.4472135954999579,\n", - " [pysnooper/tracer.py:20]:0.4472135954999579,\n", - " [pysnooper/tracer.py:19]:0.4472135954999579,\n", - " [pysnooper/tracer.py:170]:0.4472135954999579,\n", - " [pysnooper/tracer.py:101]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:12]:0.4472135954999579,\n", - " [pysnooper/tracer.py:102]:0.4472135954999579,\n", - " [pysnooper/__init__.py:4]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:69]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:20]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:33]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:74]:0.4472135954999579,\n", - " [pysnooper/tracer.py:158]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:68]:0.4472135954999579,\n", - " [pysnooper/tracer.py:21]:0.4472135954999579,\n", - " [pysnooper/tracer.py:156]:0.4472135954999579,\n", - " [pysnooper/tracer.py:172]:0.4472135954999579,\n", - " [pysnooper/__init__.py:5]:0.4472135954999579,\n", - " [pysnooper/tracer.py:7]:0.4472135954999579,\n", - " [pysnooper/pycompat.py:5]:0.4472135954999579,\n", - " [pysnooper/pysnooper.py:7]:0.4472135954999579,\n", - " [pysnooper/tracer.py:26]:0.4472135954999579,\n", - " [pysnooper/pycompat.py:9]:0.4472135954999579,\n", - " [pysnooper/tracer.py:164]:0.4472135954999579,\n", - " [pysnooper/tracer.py:103]:0.4472135954999579,\n", - " [pysnooper/tracer.py:162]:0.4472135954999579,\n", - " [pysnooper/tracer.py:39]:0.4472135954999579,\n", - " [pysnooper/tracer.py:165]:0.4472135954999579,\n", - " [pysnooper/tracer.py:25]:0.4472135954999579,\n", - " [pysnooper/tracer.py:105]:0.4472135954999579,\n", - " [pysnooper/tracer.py:16]:0.4472135954999579,\n", - " [pysnooper/tracer.py:161]:0.4472135954999579,\n", - " [pysnooper/tracer.py:104]:0.4472135954999579,\n", - " [pysnooper/tracer.py:121]:0.4472135954999579,\n", - " [pysnooper/utils.py:4]:0.4472135954999579,\n", - " [pysnooper/utils.py:7]:0.4472135954999579,\n", - " [pysnooper/tracer.py:106]:0.4472135954999579,\n", - " [pysnooper/tracer.py:112]:0.4472135954999579,\n", - " [pysnooper/tracer.py:114]:0.4472135954999579,\n", - " [pysnooper/tracer.py:167]:0.0,\n", - " [pysnooper/pysnooper.py:23]:0.0,\n", - " [pysnooper/tracer.py:28]:0.0,\n", - " [pysnooper/tracer.py:34]:0.0,\n", - " [pysnooper/tracer.py:30]:0.0,\n", - " [pysnooper/tracer.py:27]:0.0,\n", - " [pysnooper/tracer.py:183]:0.0,\n", - " [pysnooper/tracer.py:45]:0.0,\n", - " [pysnooper/tracer.py:182]:0.0,\n", - " [pysnooper/pysnooper.py:29]:0.0,\n", - " [pysnooper/tracer.py:185]:0.0,\n", - " [pysnooper/pysnooper.py:22]:0.0,\n", - " [pysnooper/tracer.py:175]:0.0,\n", - " [pysnooper/tracer.py:181]:0.0,\n", - " [pysnooper/tracer.py:94]:0.0,\n", - " [pysnooper/tracer.py:95]:0.0,\n", - " [pysnooper/tracer.py:29]:0.0,\n", - " [pysnooper/tracer.py:96]:0.0,\n", - " [pysnooper/tracer.py:92]:0.0,\n", - " [pysnooper/tracer.py:93]:0.0,\n", - " [pysnooper/tracer.py:140]:0.0,\n", - " [pysnooper/utils.py:30]:0.0,\n", - " [pysnooper/tracer.py:35]:0.0,\n", - " [pysnooper/utils.py:16]:0.0,\n", - " [pysnooper/utils.py:13]:0.0,\n", - " [pysnooper/tracer.py:36]:0.0,\n", - " [pysnooper/utils.py:14]:0.0,\n", - " [pysnooper/tracer.py:53]:0.0,\n", - " [pysnooper/tracer.py:176]:0.0,\n", - " [pysnooper/tracer.py:60]:0.0,\n", - " [pysnooper/tracer.py:46]:0.0,\n", - " [pysnooper/tracer.py:58]:0.0,\n", - " [pysnooper/pysnooper.py:31]:0.0,\n", - " [pysnooper/tracer.py:148]:0.0,\n", - " [pysnooper/tracer.py:80]:0.0,\n", - " [pysnooper/tracer.py:144]:0.0,\n", - " [pysnooper/tracer.py:70]:0.0,\n", - " [pysnooper/utils.py:12]:0.0,\n", - " [pysnooper/tracer.py:50]:0.0,\n", - " [pysnooper/tracer.py:85]:0.0,\n", - " [pysnooper/tracer.py:32]:0.0,\n", - " [pysnooper/tracer.py:51]:0.0,\n", - " [pysnooper/tracer.py:57]:0.0,\n", - " [pysnooper/utils.py:11]:0.0,\n", - " [pysnooper/tracer.py:89]:0.0,\n", - " [pysnooper/tracer.py:139]:0.0,\n", - " [pysnooper/tracer.py:168]:0.0,\n", - " [pysnooper/tracer.py:142]:0.0,\n", - " [pysnooper/tracer.py:141]:0.0,\n", - " [pysnooper/tracer.py:68]:0.0,\n", - " [pysnooper/tracer.py:146]:0.0,\n", - " [pysnooper/tracer.py:74]:0.0,\n", - " [pysnooper/utils.py:19]:0.0,\n", - " [pysnooper/tracer.py:82]:0.0,\n", - " [pysnooper/utils.py:29]:0.0,\n", - " [pysnooper/tracer.py:47]:0.0,\n", - " [pysnooper/tracer.py:61]:0.0,\n", - " [pysnooper/tracer.py:69]:0.0,\n", - " [pysnooper/tracer.py:54]:0.0,\n", - " [pysnooper/tracer.py:81]:0.0,\n", - " [pysnooper/tracer.py:71]:0.0,\n", - " [pysnooper/tracer.py:52]:0.0,\n", - " [pysnooper/utils.py:10]:0.0,\n", - " [pysnooper/tracer.py:86]:0.0,\n", - " [pysnooper/tracer.py:31]:0.0,\n", - " [pysnooper/tracer.py:145]:0.0,\n", - " [pysnooper/tracer.py:56]:0.0,\n", - " [pysnooper/tracer.py:48]:0.0],\n", - " 'Tarantula': [[pysnooper/pysnooper.py:26]:1.0,\n", - " [pysnooper/pysnooper.py:24]:0.6666666666666666,\n", - " [pysnooper/tracer.py:137]:0.5714285714285714,\n", - " [pysnooper/tracer.py:107]:0.5,\n", - " [pysnooper/pysnooper.py:8]:0.5,\n", - " [pysnooper/pycompat.py:20]:0.5,\n", - " [pysnooper/pysnooper.py:16]:0.5,\n", - " [pysnooper/pysnooper.py:14]:0.5,\n", - " [pysnooper/pysnooper.py:15]:0.5,\n", - " [pysnooper/pycompat.py:8]:0.5,\n", - " [pysnooper/pycompat.py:19]:0.5,\n", - " [pysnooper/pysnooper.py:5]:0.5,\n", - " [pysnooper/tracer.py:108]:0.5,\n", - " [pysnooper/pycompat.py:6]:0.5,\n", - " [pysnooper/tracer.py:117]:0.5,\n", - " [pysnooper/utils.py:5]:0.5,\n", - " [pysnooper/tracer.py:132]:0.5,\n", - " [pysnooper/tracer.py:118]:0.5,\n", - " [pysnooper/pysnooper.py:6]:0.5,\n", - " [pysnooper/tracer.py:14]:0.5,\n", - " [pysnooper/tracer.py:42]:0.5,\n", - " [pysnooper/tracer.py:43]:0.5,\n", - " [pysnooper/tracer.py:111]:0.5,\n", - " [pysnooper/pysnooper.py:4]:0.5,\n", - " [pysnooper/tracer.py:166]:0.5,\n", - " [pysnooper/pysnooper.py:65]:0.5,\n", - " [pysnooper/tracer.py:8]:0.5,\n", - " [pysnooper/__init__.py:6]:0.5,\n", - " [pysnooper/tracer.py:4]:0.5,\n", - " [pysnooper/tracer.py:6]:0.5,\n", - " [pysnooper/tracer.py:5]:0.5,\n", - " [pysnooper/pysnooper.py:10]:0.5,\n", - " [pysnooper/tracer.py:133]:0.5,\n", - " [pysnooper/tracer.py:10]:0.5,\n", - " [pysnooper/pysnooper.py:9]:0.5,\n", - " [pysnooper/tracer.py:173]:0.5,\n", - " [pysnooper/tracer.py:22]:0.5,\n", - " [pysnooper/pysnooper.py:72]:0.5,\n", - " [pysnooper/tracer.py:13]:0.5,\n", - " [pysnooper/tracer.py:150]:0.5,\n", - " [pysnooper/__init__.py:8]:0.5,\n", - " [pysnooper/tracer.py:20]:0.5,\n", - " [pysnooper/tracer.py:19]:0.5,\n", - " [pysnooper/tracer.py:170]:0.5,\n", - " [pysnooper/tracer.py:101]:0.5,\n", - " [pysnooper/pysnooper.py:12]:0.5,\n", - " [pysnooper/tracer.py:102]:0.5,\n", - " [pysnooper/__init__.py:4]:0.5,\n", - " [pysnooper/pysnooper.py:69]:0.5,\n", - " [pysnooper/pysnooper.py:20]:0.5,\n", - " [pysnooper/pysnooper.py:33]:0.5,\n", - " [pysnooper/pysnooper.py:74]:0.5,\n", - " [pysnooper/tracer.py:158]:0.5,\n", - " [pysnooper/pysnooper.py:68]:0.5,\n", - " [pysnooper/tracer.py:21]:0.5,\n", - " [pysnooper/tracer.py:156]:0.5,\n", - " [pysnooper/tracer.py:172]:0.5,\n", - " [pysnooper/__init__.py:5]:0.5,\n", - " [pysnooper/tracer.py:7]:0.5,\n", - " [pysnooper/pycompat.py:5]:0.5,\n", - " [pysnooper/pysnooper.py:7]:0.5,\n", - " [pysnooper/tracer.py:26]:0.5,\n", - " [pysnooper/pycompat.py:9]:0.5,\n", - " [pysnooper/tracer.py:164]:0.5,\n", - " [pysnooper/tracer.py:103]:0.5,\n", - " [pysnooper/tracer.py:162]:0.5,\n", - " [pysnooper/tracer.py:39]:0.5,\n", - " [pysnooper/tracer.py:165]:0.5,\n", - " [pysnooper/tracer.py:25]:0.5,\n", - " [pysnooper/tracer.py:105]:0.5,\n", - " [pysnooper/tracer.py:16]:0.5,\n", - " [pysnooper/tracer.py:161]:0.5,\n", - " [pysnooper/tracer.py:104]:0.5,\n", - " [pysnooper/tracer.py:121]:0.5,\n", - " [pysnooper/utils.py:4]:0.5,\n", - " [pysnooper/utils.py:7]:0.5,\n", - " [pysnooper/tracer.py:106]:0.5,\n", - " [pysnooper/tracer.py:112]:0.5,\n", - " [pysnooper/tracer.py:114]:0.5,\n", - " [pysnooper/tracer.py:167]:0.0,\n", - " [pysnooper/pysnooper.py:23]:0.0,\n", - " [pysnooper/tracer.py:28]:0.0,\n", - " [pysnooper/tracer.py:34]:0.0,\n", - " [pysnooper/tracer.py:30]:0.0,\n", - " [pysnooper/tracer.py:27]:0.0,\n", - " [pysnooper/tracer.py:183]:0.0,\n", - " [pysnooper/tracer.py:45]:0.0,\n", - " [pysnooper/tracer.py:182]:0.0,\n", - " [pysnooper/pysnooper.py:29]:0.0,\n", - " [pysnooper/tracer.py:185]:0.0,\n", - " [pysnooper/pysnooper.py:22]:0.0,\n", - " [pysnooper/tracer.py:175]:0.0,\n", - " [pysnooper/tracer.py:181]:0.0,\n", - " [pysnooper/tracer.py:94]:0.0,\n", - " [pysnooper/tracer.py:95]:0.0,\n", - " [pysnooper/tracer.py:29]:0.0,\n", - " [pysnooper/tracer.py:96]:0.0,\n", - " [pysnooper/tracer.py:92]:0.0,\n", - " [pysnooper/tracer.py:93]:0.0,\n", - " [pysnooper/tracer.py:140]:0.0,\n", - " [pysnooper/utils.py:30]:0.0,\n", - " [pysnooper/tracer.py:35]:0.0,\n", - " [pysnooper/utils.py:16]:0.0,\n", - " [pysnooper/utils.py:13]:0.0,\n", - " [pysnooper/tracer.py:36]:0.0,\n", - " [pysnooper/utils.py:14]:0.0,\n", - " [pysnooper/tracer.py:53]:0.0,\n", - " [pysnooper/tracer.py:176]:0.0,\n", - " [pysnooper/tracer.py:60]:0.0,\n", - " [pysnooper/tracer.py:46]:0.0,\n", - " [pysnooper/tracer.py:58]:0.0,\n", - " [pysnooper/pysnooper.py:31]:0.0,\n", - " [pysnooper/tracer.py:148]:0.0,\n", - " [pysnooper/tracer.py:80]:0.0,\n", - " [pysnooper/tracer.py:144]:0.0,\n", - " [pysnooper/tracer.py:70]:0.0,\n", - " [pysnooper/utils.py:12]:0.0,\n", - " [pysnooper/tracer.py:50]:0.0,\n", - " [pysnooper/tracer.py:85]:0.0,\n", - " [pysnooper/tracer.py:32]:0.0,\n", - " [pysnooper/tracer.py:51]:0.0,\n", - " [pysnooper/tracer.py:57]:0.0,\n", - " [pysnooper/utils.py:11]:0.0,\n", - " [pysnooper/tracer.py:89]:0.0,\n", - " [pysnooper/tracer.py:139]:0.0,\n", - " [pysnooper/tracer.py:168]:0.0,\n", - " [pysnooper/tracer.py:142]:0.0,\n", - " [pysnooper/tracer.py:141]:0.0,\n", - " [pysnooper/tracer.py:68]:0.0,\n", - " [pysnooper/tracer.py:146]:0.0,\n", - " [pysnooper/tracer.py:74]:0.0,\n", - " [pysnooper/utils.py:19]:0.0,\n", - " [pysnooper/tracer.py:82]:0.0,\n", - " [pysnooper/utils.py:29]:0.0,\n", - " [pysnooper/tracer.py:47]:0.0,\n", - " [pysnooper/tracer.py:61]:0.0,\n", - " [pysnooper/tracer.py:69]:0.0,\n", - " [pysnooper/tracer.py:54]:0.0,\n", - " [pysnooper/tracer.py:81]:0.0,\n", - " [pysnooper/tracer.py:71]:0.0,\n", - " [pysnooper/tracer.py:52]:0.0,\n", - " [pysnooper/utils.py:10]:0.0,\n", - " [pysnooper/tracer.py:86]:0.0,\n", - " [pysnooper/tracer.py:31]:0.0,\n", - " [pysnooper/tracer.py:145]:0.0,\n", - " [pysnooper/tracer.py:56]:0.0,\n", - " [pysnooper/tracer.py:48]:0.0],\n", - " 'Jaccard': [[pysnooper/pysnooper.py:26]:1.0,\n", - " [pysnooper/pysnooper.py:24]:0.3333333333333333,\n", - " [pysnooper/tracer.py:137]:0.25,\n", - " [pysnooper/tracer.py:107]:0.2,\n", - " [pysnooper/pysnooper.py:8]:0.2,\n", - " [pysnooper/pycompat.py:20]:0.2,\n", - " [pysnooper/pysnooper.py:16]:0.2,\n", - " [pysnooper/pysnooper.py:14]:0.2,\n", - " [pysnooper/pysnooper.py:15]:0.2,\n", - " [pysnooper/pycompat.py:8]:0.2,\n", - " [pysnooper/pycompat.py:19]:0.2,\n", - " [pysnooper/pysnooper.py:5]:0.2,\n", - " [pysnooper/tracer.py:108]:0.2,\n", - " [pysnooper/pycompat.py:6]:0.2,\n", - " [pysnooper/tracer.py:117]:0.2,\n", - " [pysnooper/utils.py:5]:0.2,\n", - " [pysnooper/tracer.py:132]:0.2,\n", - " [pysnooper/tracer.py:118]:0.2,\n", - " [pysnooper/pysnooper.py:6]:0.2,\n", - " [pysnooper/tracer.py:14]:0.2,\n", - " [pysnooper/tracer.py:42]:0.2,\n", - " [pysnooper/tracer.py:43]:0.2,\n", - " [pysnooper/tracer.py:111]:0.2,\n", - " [pysnooper/pysnooper.py:4]:0.2,\n", - " [pysnooper/tracer.py:166]:0.2,\n", - " [pysnooper/pysnooper.py:65]:0.2,\n", - " [pysnooper/tracer.py:8]:0.2,\n", - " [pysnooper/__init__.py:6]:0.2,\n", - " [pysnooper/tracer.py:4]:0.2,\n", - " [pysnooper/tracer.py:6]:0.2,\n", - " [pysnooper/tracer.py:5]:0.2,\n", - " [pysnooper/pysnooper.py:10]:0.2,\n", - " [pysnooper/tracer.py:133]:0.2,\n", - " [pysnooper/tracer.py:10]:0.2,\n", - " [pysnooper/pysnooper.py:9]:0.2,\n", - " [pysnooper/tracer.py:173]:0.2,\n", - " [pysnooper/tracer.py:22]:0.2,\n", - " [pysnooper/pysnooper.py:72]:0.2,\n", - " [pysnooper/tracer.py:13]:0.2,\n", - " [pysnooper/tracer.py:150]:0.2,\n", - " [pysnooper/__init__.py:8]:0.2,\n", - " [pysnooper/tracer.py:20]:0.2,\n", - " [pysnooper/tracer.py:19]:0.2,\n", - " [pysnooper/tracer.py:170]:0.2,\n", - " [pysnooper/tracer.py:101]:0.2,\n", - " [pysnooper/pysnooper.py:12]:0.2,\n", - " [pysnooper/tracer.py:102]:0.2,\n", - " [pysnooper/__init__.py:4]:0.2,\n", - " [pysnooper/pysnooper.py:69]:0.2,\n", - " [pysnooper/pysnooper.py:20]:0.2,\n", - " [pysnooper/pysnooper.py:33]:0.2,\n", - " [pysnooper/pysnooper.py:74]:0.2,\n", - " [pysnooper/tracer.py:158]:0.2,\n", - " [pysnooper/pysnooper.py:68]:0.2,\n", - " [pysnooper/tracer.py:21]:0.2,\n", - " [pysnooper/tracer.py:156]:0.2,\n", - " [pysnooper/tracer.py:172]:0.2,\n", - " [pysnooper/__init__.py:5]:0.2,\n", - " [pysnooper/tracer.py:7]:0.2,\n", - " [pysnooper/pycompat.py:5]:0.2,\n", - " [pysnooper/pysnooper.py:7]:0.2,\n", - " [pysnooper/tracer.py:26]:0.2,\n", - " [pysnooper/pycompat.py:9]:0.2,\n", - " [pysnooper/tracer.py:164]:0.2,\n", - " [pysnooper/tracer.py:103]:0.2,\n", - " [pysnooper/tracer.py:162]:0.2,\n", - " [pysnooper/tracer.py:39]:0.2,\n", - " [pysnooper/tracer.py:165]:0.2,\n", - " [pysnooper/tracer.py:25]:0.2,\n", - " [pysnooper/tracer.py:105]:0.2,\n", - " [pysnooper/tracer.py:16]:0.2,\n", - " [pysnooper/tracer.py:161]:0.2,\n", - " [pysnooper/tracer.py:104]:0.2,\n", - " [pysnooper/tracer.py:121]:0.2,\n", - " [pysnooper/utils.py:4]:0.2,\n", - " [pysnooper/utils.py:7]:0.2,\n", - " [pysnooper/tracer.py:106]:0.2,\n", - " [pysnooper/tracer.py:112]:0.2,\n", - " [pysnooper/tracer.py:114]:0.2,\n", - " [pysnooper/tracer.py:167]:0.0,\n", - " [pysnooper/pysnooper.py:23]:0.0,\n", - " [pysnooper/tracer.py:28]:0.0,\n", - " [pysnooper/tracer.py:34]:0.0,\n", - " [pysnooper/tracer.py:30]:0.0,\n", - " [pysnooper/tracer.py:27]:0.0,\n", - " [pysnooper/tracer.py:183]:0.0,\n", - " [pysnooper/tracer.py:45]:0.0,\n", - " [pysnooper/tracer.py:182]:0.0,\n", - " [pysnooper/pysnooper.py:29]:0.0,\n", - " [pysnooper/tracer.py:185]:0.0,\n", - " [pysnooper/pysnooper.py:22]:0.0,\n", - " [pysnooper/tracer.py:175]:0.0,\n", - " [pysnooper/tracer.py:181]:0.0,\n", - " [pysnooper/tracer.py:94]:0.0,\n", - " [pysnooper/tracer.py:95]:0.0,\n", - " [pysnooper/tracer.py:29]:0.0,\n", - " [pysnooper/tracer.py:96]:0.0,\n", - " [pysnooper/tracer.py:92]:0.0,\n", - " [pysnooper/tracer.py:93]:0.0,\n", - " [pysnooper/tracer.py:140]:0.0,\n", - " [pysnooper/utils.py:30]:0.0,\n", - " [pysnooper/tracer.py:35]:0.0,\n", - " [pysnooper/utils.py:16]:0.0,\n", - " [pysnooper/utils.py:13]:0.0,\n", - " [pysnooper/tracer.py:36]:0.0,\n", - " [pysnooper/utils.py:14]:0.0,\n", - " [pysnooper/tracer.py:53]:0.0,\n", - " [pysnooper/tracer.py:176]:0.0,\n", - " [pysnooper/tracer.py:60]:0.0,\n", - " [pysnooper/tracer.py:46]:0.0,\n", - " [pysnooper/tracer.py:58]:0.0,\n", - " [pysnooper/pysnooper.py:31]:0.0,\n", - " [pysnooper/tracer.py:148]:0.0,\n", - " [pysnooper/tracer.py:80]:0.0,\n", - " [pysnooper/tracer.py:144]:0.0,\n", - " [pysnooper/tracer.py:70]:0.0,\n", - " [pysnooper/utils.py:12]:0.0,\n", - " [pysnooper/tracer.py:50]:0.0,\n", - " [pysnooper/tracer.py:85]:0.0,\n", - " [pysnooper/tracer.py:32]:0.0,\n", - " [pysnooper/tracer.py:51]:0.0,\n", - " [pysnooper/tracer.py:57]:0.0,\n", - " [pysnooper/utils.py:11]:0.0,\n", - " [pysnooper/tracer.py:89]:0.0,\n", - " [pysnooper/tracer.py:139]:0.0,\n", - " [pysnooper/tracer.py:168]:0.0,\n", - " [pysnooper/tracer.py:142]:0.0,\n", - " [pysnooper/tracer.py:141]:0.0,\n", - " [pysnooper/tracer.py:68]:0.0,\n", - " [pysnooper/tracer.py:146]:0.0,\n", - " [pysnooper/tracer.py:74]:0.0,\n", - " [pysnooper/utils.py:19]:0.0,\n", - " [pysnooper/tracer.py:82]:0.0,\n", - " [pysnooper/utils.py:29]:0.0,\n", - " [pysnooper/tracer.py:47]:0.0,\n", - " [pysnooper/tracer.py:61]:0.0,\n", - " [pysnooper/tracer.py:69]:0.0,\n", - " [pysnooper/tracer.py:54]:0.0,\n", - " [pysnooper/tracer.py:81]:0.0,\n", - " [pysnooper/tracer.py:71]:0.0,\n", - " [pysnooper/tracer.py:52]:0.0,\n", - " [pysnooper/utils.py:10]:0.0,\n", - " [pysnooper/tracer.py:86]:0.0,\n", - " [pysnooper/tracer.py:31]:0.0,\n", - " [pysnooper/tracer.py:145]:0.0,\n", - " [pysnooper/tracer.py:56]:0.0,\n", - " [pysnooper/tracer.py:48]:0.0]}}" - ] - }, - "execution_count": 67, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "test_results = get_results(test_project, test_bug_id, default_project)\n", "test_results" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 68, "id": "e9048d55-5420-466e-a6ef-9f406d5caf0a", "metadata": {}, - "outputs": [], "source": [ "def get_suggestions(type_: AnalysisType, metric: str, results:dict) -> List[Suggestion]:\n", " return results[type_.name][metric]" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 69, "id": "583954fc-0455-4fcd-b613-f546ab403590", "metadata": {}, - "outputs": [], "source": [ "def get_k_suggestions(suggestions: List[Suggestion], k: int) -> Set[Suggestion]:\n", " result = set()\n", @@ -1923,118 +1207,77 @@ " break\n", " result.update(suggestion.lines)\n", " return result" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 70, "id": "48fe463f-3c0e-4bdc-b6ab-5b0ce673a99d", "metadata": {}, - "outputs": [], "source": [ "def get_k(type_: AnalysisType, metric: str, results: dict, k: int = 10) -> Set[Suggestion]:\n", " return get_k_suggestions(get_suggestions(type_, metric, results), k)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 71, "id": "057dd3d6-6c2e-40be-8c22-ba7e4068f653", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{pysnooper/pycompat.py:20,\n", - " pysnooper/pycompat.py:8,\n", - " pysnooper/pysnooper.py:14,\n", - " pysnooper/pysnooper.py:15,\n", - " pysnooper/pysnooper.py:16,\n", - " pysnooper/pysnooper.py:24,\n", - " pysnooper/pysnooper.py:26,\n", - " pysnooper/pysnooper.py:8,\n", - " pysnooper/tracer.py:107,\n", - " pysnooper/tracer.py:137}" - ] - }, - "execution_count": 71, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "get_k(AnalysisType.LINE, 'Ochiai', test_results)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 72, "id": "d804ad96-6b80-47d6-9e0c-69fffe452746", "metadata": {}, - "outputs": [], "source": [ "def precision_at_k(type_: AnalysisType, metric: str, results:dict, locations: List[Location], k: int = 10):\n", " suggestions = get_k(type_, metric, results, k=k)\n", " locations = set(locations)\n", " return len(locations.intersection(suggestions)) / len(suggestions)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 73, "id": "1df5384f-c1d9-42f6-82ca-1b8397bccb18", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "k=1 : 1.0\n", - "k=3 : 0.6666666666666666\n", - "k=5 : 0.4\n", - "k=10 : 0.2\n" - ] - } - ], "source": [ "for k in [1, 3, 5, 10]:\n", " print(f'k={k:<2} : {precision_at_k(AnalysisType.LINE, \"Ochiai\", test_results, test_faulty_lines, k=k)}')" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 74, "id": "a864a29f-5abe-4281-a4a5-6030adcc9616", "metadata": {}, - "outputs": [], "source": [ "def recall_at_k(type_: AnalysisType, metric: str, results:dict, locations: List[Location], k: int = 10):\n", " suggestions = get_k(type_, metric, results, k=k)\n", " locations = set(locations)\n", " return len(locations.intersection(suggestions)) / len(locations)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 75, "id": "01c61a73-40b8-4ed5-898e-479f5513a088", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "k=1 : 0.14285714285714285\n", - "k=3 : 0.2857142857142857\n", - "k=5 : 0.2857142857142857\n", - "k=10 : 0.2857142857142857\n" - ] - } - ], "source": [ "for k in [1, 3, 5, 10]:\n", " print(f'k={k:<2} : {recall_at_k(AnalysisType.LINE, \"Ochiai\", test_results, test_faulty_lines, k=k)}')" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -2049,7 +1292,6 @@ "execution_count": 76, "id": "2fd51684-a490-4bdd-a1d7-2ce922eef263", "metadata": {}, - "outputs": [], "source": [ "def run_for_subject(subject: Subject, ks=[1, 3, 5, 10], extract=True, continue_extraction=True, verbose=False):\n", " results = get_results(subject.project, subject.bug_id, default_project, verbose=verbose)\n", @@ -2063,65 +1305,24 @@ " evaluation[type_][metric][f'r@{k}'] = recall_at_k(AnalysisType[type_], metric, results, subject.faulty_lines, k=k)\n", " print(f'Evaluated {subject}')\n", " return evaluation" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 77, "id": "ca6d5440-415b-4160-98a1-4c6b4b584b7c", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Evaluated Subject(project=PySnooper,bugId=3,#passing=4,#failing=1)\n" - ] - }, - { - "data": { - "text/plain": [ - "{'LINE': {'Ochiai': {'p@1': 1.0,\n", - " 'r@1': 0.14285714285714285,\n", - " 'p@3': 0.6666666666666666,\n", - " 'r@3': 0.2857142857142857,\n", - " 'p@5': 0.4,\n", - " 'r@5': 0.2857142857142857,\n", - " 'p@10': 0.2,\n", - " 'r@10': 0.2857142857142857},\n", - " 'Tarantula': {'p@1': 1.0,\n", - " 'r@1': 0.14285714285714285,\n", - " 'p@3': 0.6666666666666666,\n", - " 'r@3': 0.2857142857142857,\n", - " 'p@5': 0.4,\n", - " 'r@5': 0.2857142857142857,\n", - " 'p@10': 0.2,\n", - " 'r@10': 0.2857142857142857},\n", - " 'Jaccard': {'p@1': 1.0,\n", - " 'r@1': 0.14285714285714285,\n", - " 'p@3': 0.6666666666666666,\n", - " 'r@3': 0.2857142857142857,\n", - " 'p@5': 0.4,\n", - " 'r@5': 0.2857142857142857,\n", - " 'p@10': 0.2,\n", - " 'r@10': 0.2857142857142857}}}" - ] - }, - "execution_count": 77, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "run_for_subject(test_subject)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 78, "id": "74c7cb52-f309-4b97-bbc8-802df51a6425", "metadata": {}, - "outputs": [], "source": [ "def run_for_subjects(subjects: List[Subject], ks=[1, 3, 5, 10], extract=True, continue_extraction=True, verbose=False):\n", " results = list()\n", @@ -2129,71 +1330,24 @@ " for subject in subjects:\n", " results.append(run_for_subject(subject, ks=ks, extract=extract, continue_extraction=continue_extraction, verbose=verbose))\n", " return results" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 79, "id": "0105a98d-c229-4846-b983-7c08e9528733", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Evaluated Subject(project=PySnooper,bugId=3,#passing=4,#failing=1)\n", - "Evaluated Subject(project=ansible,bugId=1,#passing=58,#failing=1)\n", - "Evaluated Subject(project=ansible,bugId=2,#passing=130,#failing=2)\n", - "Evaluated Subject(project=ansible,bugId=3,#passing=53,#failing=1)\n", - "Evaluated Subject(project=black,bugId=1,#passing=128,#failing=1)\n", - "Evaluated Subject(project=black,bugId=2,#passing=121,#failing=1)\n", - "Evaluated Subject(project=black,bugId=3,#passing=120,#failing=1)\n", - "Evaluated Subject(project=cookiecutter,bugId=1,#passing=10,#failing=1)\n", - "Evaluated Subject(project=cookiecutter,bugId=2,#passing=7,#failing=3)\n", - "Evaluated Subject(project=cookiecutter,bugId=3,#passing=1,#failing=4)\n", - "Evaluated Subject(project=fastapi,bugId=1,#passing=11,#failing=1)\n", - "Evaluated Subject(project=fastapi,bugId=2,#passing=5,#failing=1)\n", - "Evaluated Subject(project=fastapi,bugId=4,#passing=1,#failing=1)\n", - "Evaluated Subject(project=httpie,bugId=1,#passing=14,#failing=13)\n", - "Evaluated Subject(project=httpie,bugId=2,#passing=2,#failing=1)\n", - "Evaluated Subject(project=httpie,bugId=3,#passing=5,#failing=2)\n", - "Evaluated Subject(project=keras,bugId=1,#passing=31,#failing=5)\n", - "Evaluated Subject(project=keras,bugId=2,#passing=144,#failing=6)\n", - "Evaluated Subject(project=keras,bugId=3,#passing=12,#failing=1)\n", - "Evaluated Subject(project=luigi,bugId=1,#passing=46,#failing=22)\n", - "Evaluated Subject(project=luigi,bugId=2,#passing=10,#failing=1)\n", - "Evaluated Subject(project=luigi,bugId=3,#passing=136,#failing=1)\n", - "Evaluated Subject(project=sanic,bugId=1,#passing=33,#failing=1)\n", - "Evaluated Subject(project=sanic,bugId=4,#passing=117,#failing=1)\n", - "Evaluated Subject(project=sanic,bugId=5,#passing=3,#failing=3)\n", - "Evaluated Subject(project=scrapy,bugId=1,#passing=3,#failing=3)\n", - "Evaluated Subject(project=scrapy,bugId=2,#passing=22,#failing=1)\n", - "Evaluated Subject(project=scrapy,bugId=3,#passing=23,#failing=1)\n", - "Evaluated Subject(project=thefuck,bugId=1,#passing=2,#failing=1)\n", - "Evaluated Subject(project=thefuck,bugId=2,#passing=30,#failing=1)\n", - "Evaluated Subject(project=thefuck,bugId=3,#passing=30,#failing=1)\n", - "Evaluated Subject(project=tornado,bugId=1,#passing=45,#failing=1)\n", - "Evaluated Subject(project=tornado,bugId=2,#passing=51,#failing=1)\n", - "Evaluated Subject(project=tornado,bugId=3,#passing=47,#failing=1)\n", - "Evaluated Subject(project=tqdm,bugId=1,#passing=2,#failing=2)\n", - "Evaluated Subject(project=tqdm,bugId=2,#passing=19,#failing=75)\n", - "Evaluated Subject(project=tqdm,bugId=3,#passing=54,#failing=1)\n", - "Evaluated Subject(project=youtube-dl,bugId=1,#passing=78,#failing=1)\n", - "Evaluated Subject(project=youtube-dl,bugId=2,#passing=8,#failing=1)\n", - "Evaluated Subject(project=youtube-dl,bugId=3,#passing=75,#failing=1)\n" - ] - } - ], "source": [ "results = run_for_subjects(subjects, extract=extract_events, continue_extraction=continue_events_extraction)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 81, "id": "eac7036d-0a59-42b8-9562-e85eb40c02dd", "metadata": {}, - "outputs": [], "source": [ "def average(results):\n", " evaluation = dict()\n", @@ -2210,29 +1364,30 @@ " evaluation[t][m][pr] = 0\n", " evaluation[t][m][pr] += r[t][m][pr] / f\n", " return evaluation" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": null, "id": "58f98abf-b5be-4216-84ab-7d60242afcb3", "metadata": {}, - "outputs": [], "source": [ "evaluation = average(results)\n", "evaluation" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": null, "id": "711d8c91-47ec-4b9f-9edd-ad3b26fb016f", "metadata": {}, - "outputs": [], "source": [ "with open('results.json', 'w') as fp:\n", " json.dump(evaluation, fp, indent = 4)" - ] + ], + "outputs": [] } ], "metadata": { diff --git a/Demo.ipynb b/Demo.ipynb index 3066bd6..8ff9248 100644 --- a/Demo.ipynb +++ b/Demo.ipynb @@ -31,35 +31,12 @@ "execution_count": 1, "id": "e2346efa-affd-40cb-be6e-12a49f391a88", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "from IPython.display import IFrame\n", "src = f\"https://www.youtube-nocookie.com/embed/qcnmi6PgrKg\"\n", "IFrame(src, 640, 360)" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -86,55 +63,16 @@ "execution_count": 2, "id": "b48fd713-7f8f-4c00-aba6-a8052aa5ed36", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Processing /Users/marius/Desktop/work/projects/sflkit\n", - " Installing build dependencies ... \u001b[?25ldone\n", - "\u001b[?25h Getting requirements to build wheel ... \u001b[?25ldone\n", - "\u001b[?25h Preparing metadata (pyproject.toml) ... \u001b[?25ldone\n", - "\u001b[?25hRequirement already satisfied: sflkitlib>=0.0.1 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from sflkit==0.2.6) (0.0.1)\n", - "Requirement already satisfied: astor>=0.8.1 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from sflkit==0.2.6) (0.8.1)\n", - "Requirement already satisfied: numpy==1.25.1 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from sflkit==0.2.6) (1.25.1)\n", - "Requirement already satisfied: matplotlib==3.7.2 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from sflkit==0.2.6) (3.7.2)\n", - "Requirement already satisfied: sortedcollections>=2.1.0 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from sflkit==0.2.6) (2.1.0)\n", - "Requirement already satisfied: parameterized>=0.8.1 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from sflkit==0.2.6) (0.9.0)\n", - "Requirement already satisfied: contourpy>=1.0.1 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from matplotlib==3.7.2->sflkit==0.2.6) (1.1.0)\n", - "Requirement already satisfied: cycler>=0.10 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from matplotlib==3.7.2->sflkit==0.2.6) (0.11.0)\n", - "Requirement already satisfied: fonttools>=4.22.0 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from matplotlib==3.7.2->sflkit==0.2.6) (4.40.0)\n", - "Requirement already satisfied: kiwisolver>=1.0.1 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from matplotlib==3.7.2->sflkit==0.2.6) (1.4.4)\n", - "Requirement already satisfied: packaging>=20.0 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from matplotlib==3.7.2->sflkit==0.2.6) (23.1)\n", - "Requirement already satisfied: pillow>=6.2.0 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from matplotlib==3.7.2->sflkit==0.2.6) (9.5.0)\n", - "Requirement already satisfied: pyparsing<3.1,>=2.3.1 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from matplotlib==3.7.2->sflkit==0.2.6) (2.4.7)\n", - "Requirement already satisfied: python-dateutil>=2.7 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from matplotlib==3.7.2->sflkit==0.2.6) (2.8.2)\n", - "Requirement already satisfied: sortedcontainers in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from sortedcollections>=2.1.0->sflkit==0.2.6) (2.4.0)\n", - "Requirement already satisfied: six>=1.5 in /Users/marius/.pyenv/versions/3.11.1/lib/python3.11/site-packages (from python-dateutil>=2.7->matplotlib==3.7.2->sflkit==0.2.6) (1.16.0)\n", - "Building wheels for collected packages: sflkit\n", - " Building wheel for sflkit (pyproject.toml) ... \u001b[?25ldone\n", - "\u001b[?25h Created wheel for sflkit: filename=sflkit-0.2.6-py3-none-any.whl size=39297 sha256=aa8c1331ed527c0a89c0632b24b0ba146eab95760564d41188ef489542d5f516\n", - " Stored in directory: /private/var/folders/09/pt1hglws43n7fh5521n6zyyh0000gn/T/pip-ephem-wheel-cache-1d3qc8oo/wheels/eb/95/8a/7bf6ee4d50417cf8e084552e4c6c5c1932d1e96f61309af921\n", - "Successfully built sflkit\n", - "Installing collected packages: sflkit\n", - " Attempting uninstall: sflkit\n", - " Found existing installation: sflkit 0.2.6\n", - " Uninstalling sflkit-0.2.6:\n", - " Successfully uninstalled sflkit-0.2.6\n", - "Successfully installed sflkit-0.2.6\n" - ] - } - ], "source": [ "!pip install ." - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 3, "id": "e8333c71-28ed-44ba-8e4e-52a72f8f96e8", "metadata": {}, - "outputs": [], "source": [ "import enum\n", "import importlib\n", @@ -147,7 +85,8 @@ "from sflkit.color import ColorCode\n", "from sflkit import instrument_config, analyze_config\n", "from sflkit.config import Config" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -170,7 +109,6 @@ "execution_count": 4, "id": "97ceacc2-3d6f-4d8f-95b4-11d45e805760", "metadata": {}, - "outputs": [], "source": [ "def middle(x, y, z):\n", " m = z\n", @@ -185,7 +123,8 @@ " elif x > z:\n", " m = x\n", " return m" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -200,7 +139,6 @@ "execution_count": 5, "id": "374e93f7-e48b-46fd-997d-54dea2b67e12", "metadata": {}, - "outputs": [], "source": [ "class TestResult(enum.Enum):\n", " \n", @@ -209,7 +147,8 @@ " \n", " PASS = 'PASS'\n", " FAIL = 'FAIL'" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -224,7 +163,6 @@ "execution_count": 6, "id": "eea55fff-0efa-48ba-8112-ed6f5698b645", "metadata": {}, - "outputs": [], "source": [ "def test(function, x, y, z, expected):\n", " try:\n", @@ -237,7 +175,8 @@ "\n", "def test_middle(x, y, z, expected):\n", " return test(middle, x, y, z, expected)" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -252,63 +191,30 @@ "execution_count": 7, "id": "549d8951-4d04-4d38-baf6-f561e5d72888", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "PASS" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "test_middle(3, 2, 1, expected=2)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 8, "id": "45baa555-b8a8-48d1-bb82-02614bcd7c60", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "PASS" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "test_middle(3, 1, 2, expected=2)" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 9, "id": "1b35abe6-1ee9-48cc-a327-2db6c05a1784", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "FAIL" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "test_middle(2, 1, 3, expected=2)" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -505,32 +411,11 @@ "execution_count": 10, "id": "d395a695-ba1d-47e9-b21f-ef2d6c95fb37", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "def middle(x, y, z):\n", - " m = z\n", - " if y < z:\n", - " if x < y:\n", - " m = y\n", - " elif x < z:\n", - " m = y # bug\n", - " else:\n", - " if x > y:\n", - " m = y\n", - " elif x > z:\n", - " m = x\n", - " return m\n", - "\n" - ] - } - ], "source": [ "source = inspect.getsource(middle)\n", "print(source)" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -545,11 +430,11 @@ "execution_count": 11, "id": "76d8e864-1983-4d28-9403-141d20477d75", "metadata": {}, - "outputs": [], "source": [ "middle_py = 'middle.py'\n", "tmp_py = 'tmp.py'" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -564,11 +449,11 @@ "execution_count": 12, "id": "1cac1b2a-a3f4-45ca-a852-897dc1b754d7", "metadata": {}, - "outputs": [], "source": [ "with open(middle_py, 'w') as fp:\n", " fp.write(source)" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -583,12 +468,12 @@ "execution_count": 13, "id": "085526f9-fadb-4b73-a5f6-df6e6f82a267", "metadata": {}, - "outputs": [], "source": [ "def test_middle_import(x, y, z, expected):\n", " from middle import middle\n", " return test(middle, x, y, z, expected)" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -603,21 +488,10 @@ "execution_count": 14, "id": "7eb154e9-e4c4-4be6-a8ee-ee1c3f1d1fa9", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(PASS, PASS, FAIL)" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "test_middle_import(3, 2, 1, expected=2), test_middle_import(3, 1, 2, expected=2), test_middle_import(2, 1, 3, expected=2)" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -649,14 +523,14 @@ "execution_count": 15, "id": "e43c061a-807b-4bc3-b707-7e1c89799f99", "metadata": {}, - "outputs": [], "source": [ "language='python'\n", "predicates='line'\n", "metrics='Tarantula'\n", "passing='event-files/0,event-files/1'\n", "failing='event-files/2'" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -671,11 +545,11 @@ "execution_count": 19, "id": "b0cd0637-7b4a-4736-80a3-6211b7e529c9", "metadata": {}, - "outputs": [], "source": [ "def get_config():\n", " return Config.create(path=middle_py, working=tmp_py, language=language, predicates=predicates, metrics=metrics, passing=passing, failing=failing)" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -690,14 +564,14 @@ "execution_count": 20, "id": "d0a87958-fbf9-4ad8-91c5-c4f9526ebcc5", "metadata": {}, - "outputs": [], "source": [ "def instrument(out=True):\n", " instrument_config(get_config())\n", " if out:\n", " with open(tmp_py, 'r') as fp:\n", " print(fp.read())" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -712,47 +586,10 @@ "execution_count": 21, "id": "c19129e7-cf49-4028-8997-76afeafc9324", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "import sflkitlib.lib\n", - "\n", - "\n", - "def middle(x, y, z):\n", - " sflkitlib.lib.add_line_event('middle.py', 2, 0)\n", - " m = z\n", - " sflkitlib.lib.add_line_event('middle.py', 3, 1)\n", - " if y < z:\n", - " sflkitlib.lib.add_line_event('middle.py', 4, 2)\n", - " if x < y:\n", - " sflkitlib.lib.add_line_event('middle.py', 5, 3)\n", - " m = y\n", - " else:\n", - " sflkitlib.lib.add_line_event('middle.py', 6, 4)\n", - " if x < z:\n", - " sflkitlib.lib.add_line_event('middle.py', 7, 5)\n", - " m = y\n", - " else:\n", - " sflkitlib.lib.add_line_event('middle.py', 9, 6)\n", - " if x > y:\n", - " sflkitlib.lib.add_line_event('middle.py', 10, 7)\n", - " m = y\n", - " else:\n", - " sflkitlib.lib.add_line_event('middle.py', 11, 8)\n", - " if x > z:\n", - " sflkitlib.lib.add_line_event('middle.py', 12, 9)\n", - " m = x\n", - " sflkitlib.lib.add_line_event('middle.py', 13, 10)\n", - " return m\n", - "\n" - ] - } - ], "source": [ "instrument()" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -783,7 +620,6 @@ "execution_count": 32, "id": "a5daf879-9158-402f-8b5f-bab67f4736da", "metadata": {}, - "outputs": [], "source": [ "def test_tmp(x, y, z, expected): \n", " import tmp\n", @@ -794,7 +630,8 @@ " finally:\n", " tmp.sflkitlib.lib.dump_events()\n", " del tmp" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -809,10 +646,10 @@ "execution_count": 33, "id": "823303be-b13f-4405-9186-857625aec1b1", "metadata": {}, - "outputs": [], "source": [ "event_files = 'event-files'" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -827,7 +664,6 @@ "execution_count": 34, "id": "e084ac5b-b15e-47d0-8cda-4dc14adbb2e9", "metadata": {}, - "outputs": [], "source": [ "def run_tests():\n", " if os.path.exists(event_files):\n", @@ -839,7 +675,8 @@ " test_tmp(3, 1, 2, expected=2)\n", " os.environ['EVENTS_PATH'] = os.path.join(event_files, '2')\n", " test_tmp(2, 1, 3, expected=2)" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -854,12 +691,12 @@ "execution_count": 35, "id": "d922df2e-39a9-4aea-a926-b9275bdd9197", "metadata": {}, - "outputs": [], "source": [ "def analyze():\n", " run_tests()\n", " return analyze_config(get_config())" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -874,10 +711,10 @@ "execution_count": 36, "id": "f52db0b7-4423-49a2-b79c-3bff82e9f084", "metadata": {}, - "outputs": [], "source": [ "results = analyze()" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -892,24 +729,10 @@ "execution_count": 37, "id": "cd538827-c2b6-45fe-a3bf-1bae6e213223", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'LINE': {'Tarantula': [[middle.py:7]:1.0,\n", - " [middle.py:4, middle.py:6]:0.6666666666666666,\n", - " [middle.py:3, middle.py:13, middle.py:2]:0.5,\n", - " [middle.py:9, middle.py:10]:0.0]}}" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "results" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -932,60 +755,24 @@ "execution_count": 38, "id": "d2e2b4ed-5c28-45c9-bb12-bd746e7bc966", "metadata": {}, - "outputs": [], "source": [ "def sfl():\n", " instrument(out=False)\n", " results = analyze()\n", " code = ColorCode(results[predicates.upper()][metrics])\n", " return HTML(code.code(middle_py, source, color=True, suspiciousness=True))" - ] + ], + "outputs": [] }, { "cell_type": "code", "execution_count": 39, "id": "a7a490d9-7622-4e46-968e-aeb0d7b368b0", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
   1      def middle(x, y, z):
\n", - "
   2  50%     m = z
\n", - "
   3  50%     if y < z:
\n", - "
   4  66%         if x < y:
\n", - "
   5                  m = y
\n", - "
   6  66%         elif x < z:
\n", - "
   7 100%             m = y  # bug
\n", - "
   8          else:
\n", - "
   9   0%         if x > y:
\n", - "
  10   0%             m = y
\n", - "
  11              elif x > z:
\n", - "
  12                  m = x
\n", - "
  13  50%     return m
\n", - "
  14       
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 39, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "sfl()" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -1026,48 +813,11 @@ "execution_count": 40, "id": "bf3f66c0-1131-4017-bbd2-a4d68eec4c22", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
   1 100% def middle(x, y, z):
\n", - "
   2  66%     m = z
\n", - "
   3  50%     if y < z:
\n", - "
   4  66%         if x < y:
\n", - "
   5                  m = y
\n", - "
   6  66%         elif x < z:
\n", - "
   7 100%             m = y  # bug
\n", - "
   8          else:
\n", - "
   9   0%         if x > y:
\n", - "
  10   0%             m = y
\n", - "
  11              elif x > z:
\n", - "
  12                  m = x
\n", - "
  13 100%     return m
\n", - "
  14       
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "predicates='def_use'\n", "sfl()" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -1098,48 +848,11 @@ "execution_count": 41, "id": "416d8d9f-2636-4e79-8dd4-83d5c3a3e68f", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
   1 100% def middle(x, y, z):
\n", - "
   2  50%     m = z
\n", - "
   3  33%     if y < z:
\n", - "
   4  50%         if x < y:
\n", - "
   5                  m = y
\n", - "
   6  50%         elif x < z:
\n", - "
   7 100%             m = y  # bug
\n", - "
   8          else:
\n", - "
   9   0%         if x > y:
\n", - "
  10   0%             m = y
\n", - "
  11              elif x > z:
\n", - "
  12                  m = x
\n", - "
  13 100%     return m
\n", - "
  14       
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 41, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "metrics='Jaccard'\n", "sfl()" - ] + ], + "outputs": [] }, { "cell_type": "markdown", @@ -1170,49 +883,12 @@ "execution_count": 42, "id": "0c9dcfc0-98db-4151-a0bd-44862985a3b4", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
   1      def middle(x, y, z):
\n", - "
   2          m = z
\n", - "
   3  16%     if y < z:
\n", - "
   4  16%         if x < y:
\n", - "
   5  16%             m = y
\n", - "
   6  50%         elif x < z:
\n", - "
   7  50%             m = y  # bug
\n", - "
   8          else:
\n", - "
   9   0%         if x > y:
\n", - "
  10   0%             m = y
\n", - "
  11   0%         elif x > z:
\n", - "
  12   0%             m = x
\n", - "
  13          return m
\n", - "
  14       
\n", - "
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 42, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ "predicates='branch'\n", "metrics='IncreaseTrue'\n", "sfl()" - ] + ], + "outputs": [] }, { "cell_type": "markdown", diff --git a/src/sflkit/analysis/analysis_type.py b/src/sflkit/analysis/analysis_type.py index 80a4183..64a5c01 100644 --- a/src/sflkit/analysis/analysis_type.py +++ b/src/sflkit/analysis/analysis_type.py @@ -57,6 +57,7 @@ def set_finder(function_finder, loop_finder, branch_finder): def __init__(self, event): self.suspiciousness: float = 0 self.last_evaluation: EvaluationResult = EvaluationResult.UNOBSERVED + self.hits = dict() def get_last_evaluation(self, id_: int) -> EvaluationResult: return self.last_evaluation diff --git a/src/sflkit/analysis/analyzer.py b/src/sflkit/analysis/analyzer.py index 28263ba..e7bef92 100644 --- a/src/sflkit/analysis/analyzer.py +++ b/src/sflkit/analysis/analyzer.py @@ -1,6 +1,7 @@ -from typing import List, Callable +import os +from typing import List, Callable, Set, Dict -from sflkit.analysis.analysis_type import AnalysisType +from sflkit.analysis.analysis_type import AnalysisType, AnalysisObject from sflkit.analysis.factory import AnalysisFactory from sflkit.analysis.suggestion import Suggestion from sflkit.model.event_file import EventFile @@ -17,6 +18,7 @@ def __init__( self.relevant_event_files = relevant_event_files self.irrelevant_event_files = irrelevant_event_files self.model = Model(factory) + self.paths: Dict[int, os.PathLike] = dict() def _analyze(self, event_file): self.model.prepare(event_file) @@ -29,16 +31,17 @@ def _finalize(self): def analyze(self): for event_file in self.relevant_event_files + self.irrelevant_event_files: + self.paths[event_file.run_id] = event_file.path self._analyze(event_file) self._finalize() def dump(self, path): pass - def get_analysis(self): + def get_analysis(self) -> Set[AnalysisObject]: return list(self.model.get_analysis()) - def get_analysis_by_type(self, type_: AnalysisType): + def get_analysis_by_type(self, type_: AnalysisType) -> Set[AnalysisObject]: return list( filter(lambda p: p.analysis_type() == type_, self.model.get_analysis()) ) @@ -66,3 +69,23 @@ def get_sorted_suggestions( ], reverse=True, )[:] + + def get_coverage_per_run( + self, type_: AnalysisType = None + ) -> Dict[EventFile, Set[AnalysisObject]]: + if type_: + objects = self.get_analysis_by_type(type_) + else: + objects = self.get_analysis() + coverage = dict() + for obj in objects: + for run_id in obj.hits: + if run_id not in coverage: + coverage[run_id] = {obj} + else: + coverage[run_id].add(obj) + return coverage + + def get_coverage(self, type_: AnalysisType = None) -> Set[AnalysisObject]: + coverage = self.get_coverage_per_run(type_) + return set.union(*coverage.values()) diff --git a/src/sflkit/analysis/spectra.py b/src/sflkit/analysis/spectra.py index 5feb5f1..d46e5d6 100644 --- a/src/sflkit/analysis/spectra.py +++ b/src/sflkit/analysis/spectra.py @@ -39,7 +39,6 @@ def __init__( self.failed = failed_observed + failed_not_observed self.failed_observed = failed_observed self.failed_not_observed = failed_not_observed - self.hits = dict() self.last_evaluation: EvaluationResult = EvaluationResult.FALSE def __str__(self): diff --git a/src/sflkit/model/event_file.py b/src/sflkit/model/event_file.py index 165835b..3178ecd 100644 --- a/src/sflkit/model/event_file.py +++ b/src/sflkit/model/event_file.py @@ -1,3 +1,4 @@ +import os from pickle import PickleError from sflkitlib.events import event @@ -7,7 +8,11 @@ class EventFile(object): def __init__( - self, path: str, run_id: int, mapping: EventMapping, failing: bool = False + self, + path: os.PathLike, + run_id: int, + mapping: EventMapping, + failing: bool = False, ): self.path = path self.run_id = run_id diff --git a/src/sflkit/model/model.py b/src/sflkit/model/model.py index 5d0fb62..11a596a 100644 --- a/src/sflkit/model/model.py +++ b/src/sflkit/model/model.py @@ -1,4 +1,4 @@ -from typing import List +from typing import Set from sflkit.model.scope import Scope @@ -68,7 +68,8 @@ def enter_scope(self): def exit_scope(self): self.variables = self.variables.exit() - def get_analysis(self) -> List: + # noinspection PyUnresolvedReferences + def get_analysis(self) -> Set["AnalysisObject"]: return self.factory.get_all() def finalize(self, passed, failed): diff --git a/tests/test_coverage.py b/tests/test_coverage.py new file mode 100644 index 0000000..02dbfd2 --- /dev/null +++ b/tests/test_coverage.py @@ -0,0 +1,19 @@ +from typing import List + +from sflkit.analysis.analysis_type import AnalysisType +from sflkit.analysis.spectra import Line +from utils import BaseTest + + +class TestCoverage(BaseTest): + def test_coverage(self): + analyzer = self.run_analysis( + self.TEST_SUGGESTIONS, + "line", + "line", + relevant=[["2", "1", "3"]], + irrelevant=[["3", "2", "1"], ["3", "1", "2"]], + ) + coverage: List[Line] = analyzer.get_coverage(AnalysisType.LINE) + coverage = {line.line for line in coverage} + self.assertEqual(coverage, {1, 5, 6, 7, 9, 10, 12, 13, 16, 19, 20})