From 5e2a03720d1b15f0a52aed82625e08da503369c6 Mon Sep 17 00:00:00 2001 From: David Chang Date: Wed, 10 Jan 2024 22:33:33 +0800 Subject: [PATCH 1/7] ver Jan10thv4 updated /home/david to /home/user --- .../0cecd4f3-74de-457b-ba94-29ad6b5dafb6.json | 6 +++--- .../1334ca3e-f9e3-4db8-9ca7-b4c653be7d17.json | 6 +++--- .../21df9241-f8d7-4509-b7f1-37e501a823f7.json | 6 +++--- .../2bd59342-0664-4ccb-ba87-79379096cc08.json | 6 +++--- .../347ef137-7eeb-4c80-a3bb-0951f26a8aff.json | 6 +++--- .../37608790-6147-45d0-9f20-1137bb35703d.json | 6 +++--- .../4188d3a4-077d-46b7-9c86-23e1a036f6c1.json | 6 +++--- .../4f07fbe9-70de-4927-a4d5-bb28bc12c52c.json | 6 +++--- .../a01fbce3-2793-461f-ab86-43680ccbae25.json | 4 ++-- .../aa3a8974-2e85-438b-b29e-a64df44deb4b.json | 6 +++--- .../f9584479-3d0d-4c79-affa-9ad7afdd8850.json | 6 +++--- 11 files changed, 32 insertions(+), 32 deletions(-) diff --git a/evaluation_examples/examples/libreoffice_calc/0cecd4f3-74de-457b-ba94-29ad6b5dafb6.json b/evaluation_examples/examples/libreoffice_calc/0cecd4f3-74de-457b-ba94-29ad6b5dafb6.json index c10de54..a37eeb3 100644 --- a/evaluation_examples/examples/libreoffice_calc/0cecd4f3-74de-457b-ba94-29ad6b5dafb6.json +++ b/evaluation_examples/examples/libreoffice_calc/0cecd4f3-74de-457b-ba94-29ad6b5dafb6.json @@ -10,7 +10,7 @@ "files": [ { "url": "https://drive.usercontent.google.com/download?id=1ejNXBNOZtn64ugmvXot21pOEjx5xa-I5&export=download&authuser=0&confirm=t&uuid=61aa93e2-03f7-4b28-8e4a-cdff16a642f7&at=APZUnTVgPAHHfXaEjfKau5CDY1_K:1703509323791", - "path": "/home/david/copy_sheet_insert.xlsx" + "path": "/home/user/copy_sheet_insert.xlsx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "/home/david/copy_sheet_insert.xlsx" + "path": "/home/user/copy_sheet_insert.xlsx" } } ], @@ -30,7 +30,7 @@ "func": "check_sheet_list", "result": { "type": "vm_file", - "path": "/home/david/copy_sheet_insert.xlsx", + "path": "/home/user/copy_sheet_insert.xlsx", "dest": "copy_sheet_insert.xlsx" }, "expected": { diff --git a/evaluation_examples/examples/libreoffice_calc/1334ca3e-f9e3-4db8-9ca7-b4c653be7d17.json b/evaluation_examples/examples/libreoffice_calc/1334ca3e-f9e3-4db8-9ca7-b4c653be7d17.json index 9d6c8ec..5ed7c1a 100644 --- a/evaluation_examples/examples/libreoffice_calc/1334ca3e-f9e3-4db8-9ca7-b4c653be7d17.json +++ b/evaluation_examples/examples/libreoffice_calc/1334ca3e-f9e3-4db8-9ca7-b4c653be7d17.json @@ -10,7 +10,7 @@ "file": [ { "url": "https://drive.usercontent.google.com/download?id=1Wkepf_vic9o7CZFiosZ4jZT_Hy2WbRPZ&export=download&authuser=0&confirm=t&uuid=bc2ce901-a6bb-433f-bcce-cbe42d813f18&at=APZUnTVQcGTcXjwqenmtSH6IMFkM:1703858853235", - "path": "/home/david/Zoom_Out_Oversized_Cells.xlsx" + "path": "/home/user/Zoom_Out_Oversized_Cells.xlsx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "/home/david/Zoom_Out_Oversized_Cells.xlsx" + "path": "/home/user/Zoom_Out_Oversized_Cells.xlsx" } } ], @@ -30,7 +30,7 @@ "func": "check_xlsx_zoom", "result": { "type": "vm_file", - "path": "/home/david/Zoom_Out_Oversized_Cells.xlsx", + "path": "/home/user/Zoom_Out_Oversized_Cells.xlsx", "dest": "Zoom_Out_Oversized_Cells.xlsx" }, "expected": { diff --git a/evaluation_examples/examples/libreoffice_calc/21df9241-f8d7-4509-b7f1-37e501a823f7.json b/evaluation_examples/examples/libreoffice_calc/21df9241-f8d7-4509-b7f1-37e501a823f7.json index f960d3f..cd545b0 100644 --- a/evaluation_examples/examples/libreoffice_calc/21df9241-f8d7-4509-b7f1-37e501a823f7.json +++ b/evaluation_examples/examples/libreoffice_calc/21df9241-f8d7-4509-b7f1-37e501a823f7.json @@ -10,7 +10,7 @@ "file": [ { "url": "https://drive.usercontent.google.com/download?id=16PowrQA4E71xUoJmpXPHy0dr9HBcTRmo&export=download&authuser=0&confirm=t&uuid=9a6265f7-585c-4cf8-b321-3b859aec1e68&at=APZUnTWzzOw85wws0ojXNPsIwnjE:1703858126178", - "path": "/home/david/Represent_in_millions_billions.xlsx" + "path": "/home/user/Represent_in_millions_billions.xlsx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "/home/david/Represent_in_millions_billions.xlsx" + "path": "/home/user/Represent_in_millions_billions.xlsx" } } ], @@ -30,7 +30,7 @@ "func": "compare_table", "result": { "type": "vm_file", - "path": "/home/david/Represent_in_millions_billions.xlsx", + "path": "/home/user/Represent_in_millions_billions.xlsx", "dest": "Represent_in_millions_billions.xlsx" }, "expected": { diff --git a/evaluation_examples/examples/libreoffice_calc/2bd59342-0664-4ccb-ba87-79379096cc08.json b/evaluation_examples/examples/libreoffice_calc/2bd59342-0664-4ccb-ba87-79379096cc08.json index 4974fcf..cf37625 100644 --- a/evaluation_examples/examples/libreoffice_calc/2bd59342-0664-4ccb-ba87-79379096cc08.json +++ b/evaluation_examples/examples/libreoffice_calc/2bd59342-0664-4ccb-ba87-79379096cc08.json @@ -10,7 +10,7 @@ "files": [ { "url": "https://drive.usercontent.google.com/download?id=1uywX5XWMvesnb4-8LPKEzr2HFU7HmoIu&export=download&authuser=0&confirm=t&uuid=267bfe49-a861-4272-ae7c-39c95df35e84&at=APZUnTUbs-FF06hSMv3yWfdXc02l:1703508870351", - "path": "/home/david/OrderId_Month_Chart.xlsx" + "path": "/home/user/OrderId_Month_Chart.xlsx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "/home/david/OrderId_Month_Chart.xlsx" + "path": "/home/user/OrderId_Month_Chart.xlsx" ] }, "trajectory": "trajectories/2bd59342-0664-4ccb-ba87-79379096cc08", @@ -34,7 +34,7 @@ }, "result": { "type": "vm_file", - "path": "/home/david/OrderId_Month_Chart.xlsx", + "path": "/home/user/OrderId_Month_Chart.xlsx", "dest": "OrderId_Month_Chart.xlsx" }, "options": { diff --git a/evaluation_examples/examples/libreoffice_calc/347ef137-7eeb-4c80-a3bb-0951f26a8aff.json b/evaluation_examples/examples/libreoffice_calc/347ef137-7eeb-4c80-a3bb-0951f26a8aff.json index 329c4f0..e8ba626 100644 --- a/evaluation_examples/examples/libreoffice_calc/347ef137-7eeb-4c80-a3bb-0951f26a8aff.json +++ b/evaluation_examples/examples/libreoffice_calc/347ef137-7eeb-4c80-a3bb-0951f26a8aff.json @@ -10,7 +10,7 @@ "files": [ { "url": "https://drive.usercontent.google.com/download?id=1GOEacGTLP4EfGS8YwO9aGmmPgud5EavT&export=download&authuser=0&confirm=t&uuid=3971675c-3a76-4f89-863f-7f8afa59c3c5&at=APZUnTWaQ4_l1IiXsAR8VbjKf4uZ:1703595929357", - "path": "/home/david/Create_column_charts_using_statistics.xlsx" + "path": "/home/user/Create_column_charts_using_statistics.xlsx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "/home/david/Create_column_charts_using_statistics.xlsx" + "path": "/home/user/Create_column_charts_using_statistics.xlsx" } } ], @@ -30,7 +30,7 @@ "func": "compare_table", "result": { "type": "vm_file", - "path": "/home/david/Create_column_charts_using_statistics.xlsx", + "path": "/home/user/Create_column_charts_using_statistics.xlsx", "dest": "Create_column_charts_using_statistics.xlsx" }, "expected": { diff --git a/evaluation_examples/examples/libreoffice_calc/37608790-6147-45d0-9f20-1137bb35703d.json b/evaluation_examples/examples/libreoffice_calc/37608790-6147-45d0-9f20-1137bb35703d.json index b34683a..b7c65d6 100644 --- a/evaluation_examples/examples/libreoffice_calc/37608790-6147-45d0-9f20-1137bb35703d.json +++ b/evaluation_examples/examples/libreoffice_calc/37608790-6147-45d0-9f20-1137bb35703d.json @@ -10,7 +10,7 @@ "files": [ { "url": "https://101.43.24.67/s/FBip5fXoR4KEJaa", - "path": "/home/david/Employee_Roles_and_Ranks.xlsx" + "path": "/home/user/Employee_Roles_and_Ranks.xlsx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "/home/david/Employee_Roles_and_Ranks.xlsx" + "path": "/home/user/Employee_Roles_and_Ranks.xlsx" } } ], @@ -35,7 +35,7 @@ }, "result": { "type": "vm_file", - "path": "/home/david/Employee_Roles_and_Ranks.xlsx", + "path": "/home/user/Employee_Roles_and_Ranks.xlsx", "dest": "Employee_Roles_and_Ranks.xlsx" } } diff --git a/evaluation_examples/examples/libreoffice_calc/4188d3a4-077d-46b7-9c86-23e1a036f6c1.json b/evaluation_examples/examples/libreoffice_calc/4188d3a4-077d-46b7-9c86-23e1a036f6c1.json index 8fbc5e8..6a9d412 100644 --- a/evaluation_examples/examples/libreoffice_calc/4188d3a4-077d-46b7-9c86-23e1a036f6c1.json +++ b/evaluation_examples/examples/libreoffice_calc/4188d3a4-077d-46b7-9c86-23e1a036f6c1.json @@ -10,7 +10,7 @@ "files": [ { "url": "https://drive.usercontent.google.com/download?id=1ZhGLDKOden_oxzuN2xN9-jNQSHtCX6GE&export=download&authuser=0&confirm=t&uuid=2c097276-a610-4a9f-b6e4-5b54296c1555&at=APZUnTWc7zKPY_ykygn0mO1SAs4s:1703580957447", - "path": "/home/david/Freeze_row_column.xlsx" + "path": "/home/user/Freeze_row_column.xlsx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "/home/david/Freeze_row_column.xlsx" + "path": "/home/user/Freeze_row_column.xlsx" } } ], @@ -30,7 +30,7 @@ "func": "check_xlsx_freeze", "result": { "type": "vm_file", - "path": "/home/david/Freeze_row_column.xlsx", + "path": "/home/user/Freeze_row_column.xlsx", "dest": "Freeze_row_column.xlsx" }, "expected": { diff --git a/evaluation_examples/examples/libreoffice_calc/4f07fbe9-70de-4927-a4d5-bb28bc12c52c.json b/evaluation_examples/examples/libreoffice_calc/4f07fbe9-70de-4927-a4d5-bb28bc12c52c.json index 14251e2..f45c50c 100644 --- a/evaluation_examples/examples/libreoffice_calc/4f07fbe9-70de-4927-a4d5-bb28bc12c52c.json +++ b/evaluation_examples/examples/libreoffice_calc/4f07fbe9-70de-4927-a4d5-bb28bc12c52c.json @@ -10,7 +10,7 @@ "file": [ { "url": "https://drive.usercontent.google.com/download?id=1LHxVvEpLI7kp0Iiy8K74gwkoGiwcLeYP&export=download&authuser=0&confirm=t&uuid=690287ee-d413-46e7-9b01-c56c12e445ff&at=APZUnTVCSd_ajhMGWpEgLHiExfbf:1704199487820", - "path": "/home/david/Padding_Decimals_In_Formular.xlsx" + "path": "/home/user/Padding_Decimals_In_Formular.xlsx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "/home/david/Padding_Decimals_In_Formular.xlsx" + "path": "/home/user/Padding_Decimals_In_Formular.xlsx" } } ], @@ -30,7 +30,7 @@ "func": "compare_table", "result": { "type": "vm_file", - "path": "/home/david/Padding_Decimals_In_Formular_gold.xlsx", + "path": "/home/user/Padding_Decimals_In_Formular_gold.xlsx", "dest": "Padding_Decimals_In_Formular.xlsx" }, "expected": { diff --git a/evaluation_examples/examples/libreoffice_calc/a01fbce3-2793-461f-ab86-43680ccbae25.json b/evaluation_examples/examples/libreoffice_calc/a01fbce3-2793-461f-ab86-43680ccbae25.json index d99f170..6ed124f 100644 --- a/evaluation_examples/examples/libreoffice_calc/a01fbce3-2793-461f-ab86-43680ccbae25.json +++ b/evaluation_examples/examples/libreoffice_calc/a01fbce3-2793-461f-ab86-43680ccbae25.json @@ -10,7 +10,7 @@ "file": [ { "url": "https://drive.usercontent.google.com/download?id=1uT0axjo9lwkKu6hYVnsAL2FCrdH0DLUv&export=download&authuser=0&confirm=t&uuid=e7da6304-9c7a-4862-8a30-9f2284b843da&at=APZUnTVNHThpAZJmF6IuPckFvslw:1704187618838", - "path": "/home/david/Set_Decimal_Separator_Dot.xlsx" + "path": "/home/user/Set_Decimal_Separator_Dot.xlsx" } ] } @@ -24,7 +24,7 @@ "func": "check_libre_locale", "result": { "type": "vm_file", - "path": "/home/david/.config/libreoffice/4/user/registrymodifications.xcu", + "path": "/home/user/.config/libreoffice/4/user/registrymodifications.xcu", "dest": "registrymodifications.xcu" }, "expected": { diff --git a/evaluation_examples/examples/libreoffice_calc/aa3a8974-2e85-438b-b29e-a64df44deb4b.json b/evaluation_examples/examples/libreoffice_calc/aa3a8974-2e85-438b-b29e-a64df44deb4b.json index ff3d191..3704a7b 100644 --- a/evaluation_examples/examples/libreoffice_calc/aa3a8974-2e85-438b-b29e-a64df44deb4b.json +++ b/evaluation_examples/examples/libreoffice_calc/aa3a8974-2e85-438b-b29e-a64df44deb4b.json @@ -10,7 +10,7 @@ "file": [ { "url": "https://drive.usercontent.google.com/download?id=1O4bw7jEsVdFGeGeSX8hDjsvIbozV38sd&export=download&authuser=0&confirm=t&uuid=b6ceade0-e9c3-47bf-8c40-fef77b5ea1f1&at=APZUnTUUYaEx0Y_lAESeK1DfQZw6:1704179724348", - "path": "/home/david/Resize_Cells_Fit_Page.xlsx" + "path": "/home/user/Resize_Cells_Fit_Page.xlsx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "/home/david/Resize_Cells_Fit_Page.xlsx" + "path": "/home/user/Resize_Cells_Fit_Page.xlsx" } } ], @@ -30,7 +30,7 @@ "func": "check_pdf_pages", "result": { "type": "vm_file", - "path": "/home/david/Resize_Cells_Fit_Page.xlsx", + "path": "/home/user/Resize_Cells_Fit_Page.xlsx", "dest": "Resize_Cells_Fit_Page.xlsx" }, "expected": { diff --git a/evaluation_examples/examples/libreoffice_calc/f9584479-3d0d-4c79-affa-9ad7afdd8850.json b/evaluation_examples/examples/libreoffice_calc/f9584479-3d0d-4c79-affa-9ad7afdd8850.json index e1aae5f..8d96854 100644 --- a/evaluation_examples/examples/libreoffice_calc/f9584479-3d0d-4c79-affa-9ad7afdd8850.json +++ b/evaluation_examples/examples/libreoffice_calc/f9584479-3d0d-4c79-affa-9ad7afdd8850.json @@ -10,7 +10,7 @@ "files": [ { "url": "https://drive.usercontent.google.com/download?id=1rwhniaClEkF8XFzdfaNUA6GmAiy4syMZ&export=download&authuser=0&confirm=t&uuid=6fdd5b04-85f4-45e1-ad74-368f8f2a82ab&at=APZUnTUP-JxPxLfNls6jXWghblQ5:1701766091851", - "path": "/home/david/Quarterly_Product_Sales_by_Zone.xlsx" + "path": "/home/user/Quarterly_Product_Sales_by_Zone.xlsx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "/home/david/Quarterly_Product_Sales_by_Zone.xlsx" + "path": "/home/user/Quarterly_Product_Sales_by_Zone.xlsx" } } ], @@ -35,7 +35,7 @@ }, "result": { "type": "vm_file", - "path": "/home/david/Quarterly_Product_Sales_by_Zone.xlsx", + "path": "/home/user/Quarterly_Product_Sales_by_Zone.xlsx", "dest": "Quarterly_Product_Sales_by_Zone.xlsx" } } From 27eaf2f5d5823895f84b6a20b4ac0443884659b6 Mon Sep 17 00:00:00 2001 From: David Chang Date: Thu, 11 Jan 2024 20:03:33 +0800 Subject: [PATCH 2/7] ver Jan11th finally set up a simple task, or which should be simple --- desktop_env/controllers/setup.py | 76 +++++++---- desktop_env/evaluators/metrics/__init__.py | 1 + desktop_env/evaluators/metrics/general.py | 2 +- desktop_env/evaluators/metrics/thunderbird.py | 120 ++++++++++++------ desktop_env/server/main.py | 3 +- .../06fe7178-4491-4589-810f-2e2bc9502122.json | 2 +- .../6766f2b8-8a72-417f-a9e5-56fcaa735837.json | 75 +++++++++++ ...8-8a72-417f-a9e5-56fcaa735837.json.nosetup | 53 ++++++++ main.py | 6 +- 9 files changed, 272 insertions(+), 66 deletions(-) create mode 100644 evaluation_examples/examples/thunderbird/6766f2b8-8a72-417f-a9e5-56fcaa735837.json create mode 100644 evaluation_examples/examples/thunderbird/6766f2b8-8a72-417f-a9e5-56fcaa735837.json.nosetup diff --git a/desktop_env/controllers/setup.py b/desktop_env/controllers/setup.py index 6067c6b..614ac48 100644 --- a/desktop_env/controllers/setup.py +++ b/desktop_env/controllers/setup.py @@ -6,12 +6,13 @@ import uuid import os.path from typing import Dict, List -from typing import Any, Union +from typing import Any, Union, Optional import logging logger = logging.getLogger("desktopenv.setup") import traceback +import time class SetupController: def __init__(self, http_server: str, cache_dir: str): @@ -45,6 +46,8 @@ class SetupController: assert hasattr(self, setup_function) getattr(self, setup_function)(**parameters) + logger.info("SETUP: %s(%s)", setup_function, str(parameters)) + # self._download_setup(config) # self._change_wallpaper(config) # self._tidy_desktop(config) todo: implement this @@ -219,35 +222,60 @@ class SetupController: except requests.exceptions.RequestException as e: logger.error("An error occurred while trying to send the request: %s", e) - def _execute_setup(self, command: List[str], stdout: str = "", stderr: str = ""): + def _execute_setup( self, command: List[str] + , stdout: str = "", stderr: str = "" + , shell: bool = False, until: Optional[Dict[str, Any]] = None): if not command: raise Exception("Empty comman to launch.") - payload = json.dumps({"command": command}) + until: Dict[str, Any] = until or {} + terminates: bool = False + nb_failings = 0 + + payload = json.dumps({"command": command, "shell": shell}) headers = {"Content-Type": "application/json"} - try: - response = requests.post(self.http_server_setup_root + "/execute", headers=headers, data=payload) - if response.status_code == 200: - results: Dict[str, str] = response.json() - if stdout: - with open(os.path.join(self.cache_dir, stdout), "w") as f: - f.write(results["output"]) - if stderr: - with open(os.path.join(self.cache_dir, stderr), "w") as f: - f.write(results["error"]) - logger.info( "Command executed successfully: %s -> %s" - , " ".join(command) - , response.text - ) - else: - logger.error("Failed to launch application. Status code: %s", response.text) - except requests.exceptions.RequestException as e: - logger.error("An error occurred while trying to send the request: %s", e) - traceback.print_exc() + while not terminates: + try: + response = requests.post(self.http_server_setup_root + "/execute", headers=headers, data=payload) + if response.status_code == 200: + results: Dict[str, str] = response.json() + if stdout: + with open(os.path.join(self.cache_dir, stdout), "w") as f: + f.write(results["output"]) + if stderr: + with open(os.path.join(self.cache_dir, stderr), "w") as f: + f.write(results["error"]) + logger.info( "Command executed successfully: %s -> %s" + , " ".join(command) + , response.text + ) + else: + logger.error("Failed to launch application. Status code: %s", response.text) + results = None + nb_failings += 1 + except requests.exceptions.RequestException as e: + logger.error("An error occurred while trying to send the request: %s", e) + traceback.print_exc() - def _command_setup(self, command: List[str], stdout: str = "", stderr: str = ""): - self._execute_setup(command, stdout, stderr) + results = None + nb_failings += 1 + + if len(until)==0: + terminates = True + elif results is not None: + terminates = "returncode" in until and results["returncode"]==until["returncode"]\ + or "stdout" in until and until["stdout"] in results["output"]\ + or "stderr" in until and until["stderr"] in results["error"] + terminates = terminates or nb_failings>=5 + if not terminates: + time.sleep(0.3) + + def _command_setup(self, command: List[str], **kwargs): + self._execute_setup(command, **kwargs) + + def _sleep_setup(self, seconds: float): + time.sleep(seconds) def _act_setup(self, action_seq: List[Union[Dict[str, Any], str]]): # TODO diff --git a/desktop_env/evaluators/metrics/__init__.py b/desktop_env/evaluators/metrics/__init__.py index 743c360..7428eb2 100644 --- a/desktop_env/evaluators/metrics/__init__.py +++ b/desktop_env/evaluators/metrics/__init__.py @@ -7,3 +7,4 @@ from .pdf import check_pdf_pages from .libreoffice import check_libre_locale from .vlc import is_vlc_playing, is_vlc_recordings_folder from .general import check_csv, check_accessibility_tree, check_list +from .thunderbird import check_thunderbird_prefs diff --git a/desktop_env/evaluators/metrics/general.py b/desktop_env/evaluators/metrics/general.py index 427198c..6f44d83 100644 --- a/desktop_env/evaluators/metrics/general.py +++ b/desktop_env/evaluators/metrics/general.py @@ -13,7 +13,7 @@ from rapidfuzz import fuzz import functools import re -def _match_record(pattern: Dict[str, str], item: Dict[str, str]) -> float: +def _match_record(pattern: Dict[str, str], item: Dict[str, str]) -> bool: return all(k in item and item[k]==val for k, val in pattern.items()) def check_csv(result: str, rules: Dict[str, List[Dict[str, str]]]) -> float: diff --git a/desktop_env/evaluators/metrics/thunderbird.py b/desktop_env/evaluators/metrics/thunderbird.py index 581b8d1..b386243 100644 --- a/desktop_env/evaluators/metrics/thunderbird.py +++ b/desktop_env/evaluators/metrics/thunderbird.py @@ -1,43 +1,91 @@ -#from playwright.sync_api import sync_playwright, Browser -#from marionette_driver.marionette import Marionette -#import marionette -#import pyatspi +from typing import List, Pattern, Dict, Match +from typing import Union, Any, Optional, Iterable, TypeVar -import lxml.etree -from lxml.cssselect import CSSSelector -from lxml.etree import _Element +import re +import functools +import operator +import json -from typing import List +import logging +logger = logging.getLogger("desktopenv.metric.thunderbird") + +V = TypeVar("Value") + +def _match_pref(value: Any, rule: Dict[str, Union[str, Any]]) -> bool: + # function _match_pref {{{ # + if rule["method"].startswith("re"): + flags: List[str] = rule["method"].split(".")[1:] + flags: Iterable[re.RegexFlag] = (getattr(re, fl) for fl in flags) + flag: re.RegexFlag = functools.reduce(operator.or_, flags, re.RegexFlag(0)) + logger.debug("REFLAG: %s", repr(flag)) + + match_: Optional[Match[str]] = re.search(rule["ref"], value, flag) + return match_ is not None + if rule["method"] in { "eq", "ne" + , "le", "lt" + , "ge", "gt" + }: + return getattr(operator, rule["method"])(value, rule["ref"]) + raise NotImplementedError() + # }}} function _match_pref # + +_pref_pattern: Pattern[str] = re.compile(r'^user_pref\("(?P(?:[^"]|\\")+)\", (?P.+)\);$'); +def check_thunderbird_prefs(result: str, rule: Dict[str, Dict[str, Dict[str, Any]]]): + """ + Args: + result (str): path to result file + rule (Dict[str, Dict[str, Dict[str, Any]]]): dict like + { + "expect": { + str: { + "method": str + "ref": something + } + } + "unexpect": { + str: { + "method": str + "ref": something + } + } + } + + Returns: + float + """ + + if result is None: + return 0. + + expect_rules = rule.get("expect", {}) + unexpect_rules = rule.get("unexpect", {}) + + expect_metrics = {k: False for k in expect_rules} + unexpect_metric = True + with open(result) as f: + for l in f: + match_: Match[str] = _pref_pattern.match(l.strip()) + if match_ is None: + continue + + key: str = match_.group("key") + #value: str = match_.group("val") + #if value in {"true", "false"}: + #value = value.title() + #value: V = eval(value) + value = json.loads(match_.group("val")) + if key in expect_rules: + logger.debug("K: %s, V: %s", key, repr(value)) + expect_metrics[key] = _match_pref(value, expect_rules[key]) + elif key in unexpect_rules: + unexpect_metric = unexpect_metric and not _match_pref(value, unexpect_rules[key]) + + return float(all(expect_metrics.values()) and unexpect_metric) if __name__ == "__main__": - #with sync_playwright() as plwr: - #while True: - ##try: - #thunderbird: Browser = plwr.firefox.connect("http://127.0.0.1:6000", timeout=60) - #break - ##except: - ##pass - #for ctx in thunderbird.contexts: - #for p in ctx.pages: - #print(p.url) - - #thunderbird = Marionette() - #print(thunderbird.start_session()) - #print(thunderbird.chrome_window_handles) - #print(thunderbird.window_handles) - #print(thunderbird.current_chrome_window_handle) - #thunderbird.set_context(Marionette.CONTEXT_CONTENT) - #print(thunderbird.current_window_handle) - #thunderbird.switch_to_window(thunderbird.chrome_window_handles[0]) - #thunderbird.switch_to_default_content() - #thunderbird.switch_to_frame() - #print(thunderbird.get_url()) - #print(thunderbird.get_window_type()) - #thunderbird.fullscreen() - #print(thunderbird.close()) - - #registry = pyatspi.Registry.get_default() - #registry + import lxml.etree + from lxml.cssselect import CSSSelector + from lxml.etree import _Element #xml = "../../任务数据/Thunderbird/vertical-card-view.xml" xml = "../../任务数据/Thunderbird/vertical-table-view.xml" diff --git a/desktop_env/server/main.py b/desktop_env/server/main.py index ef23312..b1f1dc2 100644 --- a/desktop_env/server/main.py +++ b/desktop_env/server/main.py @@ -48,7 +48,8 @@ def execute_command(): return jsonify({ 'status': 'success', 'output': result.stdout, - 'error': result.stderr + 'error': result.stderr, + 'returncode': result.returncode }) except Exception as e: return jsonify({ diff --git a/evaluation_examples/examples/thunderbird/06fe7178-4491-4589-810f-2e2bc9502122.json b/evaluation_examples/examples/thunderbird/06fe7178-4491-4589-810f-2e2bc9502122.json index 969b193..2dc8b0b 100644 --- a/evaluation_examples/examples/thunderbird/06fe7178-4491-4589-810f-2e2bc9502122.json +++ b/evaluation_examples/examples/thunderbird/06fe7178-4491-4589-810f-2e2bc9502122.json @@ -1,7 +1,7 @@ { "id": "06fe7178-4491-4589-810f-2e2bc9502122", "snapshot": "thunderbird", - "instruction": "Could you help me back up all the email files in my profile to ~/email.bak? Please save them in eml format.", + "instruction": "Could you help me back up all the email files in my profile to ~/email.bak? Please save them separately in eml format.", "source": "https://www.quora.com/How-do-I-backup-email-files-in-Mozilla-Thunderbird", "config": [ { diff --git a/evaluation_examples/examples/thunderbird/6766f2b8-8a72-417f-a9e5-56fcaa735837.json b/evaluation_examples/examples/thunderbird/6766f2b8-8a72-417f-a9e5-56fcaa735837.json new file mode 100644 index 0000000..4e01ff5 --- /dev/null +++ b/evaluation_examples/examples/thunderbird/6766f2b8-8a72-417f-a9e5-56fcaa735837.json @@ -0,0 +1,75 @@ +{ + "id": "6766f2b8-8a72-417f-a9e5-56fcaa735837", + "snapshot": "thunderbird", + "instruction": "Set up a signature using my name and affiliation. My name is Anonym and my affiliation is XYZ Lab.", + "source": "https://www.adsigner.com/user-manual/signatures/setup-email-client-thunderbird/#:~:text=is%20probably%20hidden.-,Right%20click%20on%20the%20empty%20space%20at%20the%20top%20of,signature%20from%20a%20file%20instead.", + "config": [ + { + "type": "download", + "parameters": { + "files": [ + { + "url": "https://drive.usercontent.google.com/download?id=1EHLRWzBCOsyERkSMUnTF2pnsR0n6ZvtR&export=download&authuser=0&confirm=t&uuid=de09bd5e-bef8-499a-b599-c642af190e10&at=APZUnTXqOsQkxl0zMSX6R1Sgp_v3:1704362491712", + "path": "/home/user/thunderbird-profile.tar.gz" + } + ] + } + }, + { + "type": "execute", + "parameters": { + "command": [ + "tar", + "-xzv", + "--recursive-unlink", + "-f", + "/home/user/thunderbird-profile.tar.gz", + "-C", + "/home/user/" + ] + } + }, + { + "type": "launch", + "parameters": { + "command": [ + "/usr/bin/thunderbird" + ] + } + } + ], + "trajectory": "trajectories/6766f2b8-8a72-417f-a9e5-56fcaa735837", + "related_apps": [ + "thunderbird" + ], + "evaluator": { + "postconfig": [ + { + "type": "command", + "parameters": { + "command": ["wmctrl", "-xFc", "Mail.thunderbird"], + "until": { + "returncode": 1 + } + } + } + ], + "result": { + "type": "vm_file", + "path": "/home/user/.thunderbird/t5q2a5hp.default-release/prefs.js", + "dest": "thunder-prefs.js" + }, + "expected": { + "type": "rule", + "rules": { + "expect": { + "mail.identity.id1.htmlSigText": { + "method": "re.S", + "ref": "Anonym.+XYZ Lab" + } + } + } + }, + "func": "check_thunderbird_prefs" + } +} diff --git a/evaluation_examples/examples/thunderbird/6766f2b8-8a72-417f-a9e5-56fcaa735837.json.nosetup b/evaluation_examples/examples/thunderbird/6766f2b8-8a72-417f-a9e5-56fcaa735837.json.nosetup new file mode 100644 index 0000000..f0a416a --- /dev/null +++ b/evaluation_examples/examples/thunderbird/6766f2b8-8a72-417f-a9e5-56fcaa735837.json.nosetup @@ -0,0 +1,53 @@ +{ + "id": "6766f2b8-8a72-417f-a9e5-56fcaa735837", + "snapshot": "thunderbird", + "instruction": "Set up a signature using my name and affiliation. My name is Anonym and my affiliation is XYZ Lab.", + "source": "https://www.adsigner.com/user-manual/signatures/setup-email-client-thunderbird/#:~:text=is%20probably%20hidden.-,Right%20click%20on%20the%20empty%20space%20at%20the%20top%20of,signature%20from%20a%20file%20instead.", + "config": [ + { + "type": "download", + "parameters": { + "files": [ + { + "url": "https://drive.usercontent.google.com/download?id=1EHLRWzBCOsyERkSMUnTF2pnsR0n6ZvtR&export=download&authuser=0&confirm=t&uuid=de09bd5e-bef8-499a-b599-c642af190e10&at=APZUnTXqOsQkxl0zMSX6R1Sgp_v3:1704362491712", + "path": "/home/user/thunderbird-profile.tar.gz" + } + ] + } + } + ], + "trajectory": "trajectories/6766f2b8-8a72-417f-a9e5-56fcaa735837", + "related_apps": [ + "thunderbird" + ], + "evaluator": { + "postconfig": [ + { + "type": "command", + "parameters": { + "command": ["wmctrl", "-xFc", "Mail.thunderbird"], + "until": { + "returncode": 1 + } + } + } + ], + "result": { + "type": "vm_file", + "path": "/home/user/.thunderbird/t5q2a5hp.default-release/prefs.js", + "dest": "thunder-prefs.js" + }, + "expected": { + "type": "rule", + "rules": { + "expect": { + "mail.identity.id1.htmlSigText": { + "method": "re.S", + "ref": "Anonym.+XYZ Lab" + } + } + } + }, + "func": "check_thunderbird_prefs" + } +} diff --git a/main.py b/main.py index b128766..b4d1ef8 100644 --- a/main.py +++ b/main.py @@ -44,9 +44,9 @@ def human_agent(): Runs the Gym environment with human input. """ - with open("evaluation_examples/examples/thunderbird/06fe7178-4491-4589-810f-2e2bc9502122.json", "r") as f: + with open("evaluation_examples/examples/thunderbird/6766f2b8-8a72-417f-a9e5-56fcaa735837.json.nosetup", "r") as f: example = json.load(f) - example["snapshot"] = "Snapshot 11" + example["snapshot"] = "Snapshot 17" env = DesktopEnv( path_to_vm="../../../../大文件/镜像/Ubuntu-1218/Ubuntu/Ubuntu.vmx" , action_space="computer_13" @@ -92,7 +92,7 @@ def human_agent(): #input("PAUSING") - env.close() + #env.close() logger.info("Environment closed.") From 96d2e090542d0d76bcc1f483ab31e7a15875aeec Mon Sep 17 00:00:00 2001 From: tsuky_chen <3107760494@qq.com> Date: Thu, 11 Jan 2024 21:28:11 +0800 Subject: [PATCH 3/7] update writer examples 9-15 --- .../0b17a146-2934-46c7-8727-73ff6b6483e8.json | 16 ++++++++-------- .../0e47de2a-32e0-456c-a366-8c607ef7a9d2.json | 2 +- .../0e763496-b6bb-4508-a427-fad0b6c3e195.json | 8 ++++---- .../3ef2b351-8a84-4ff2-8724-d86eae9b842e.json | 12 ++++++------ .../45d61a06-6545-4422-97b7-bc76cfa964c1.json | 18 +++++++++--------- .../4bcb1253-a636-4df4-8cb0-a35c04dfef31.json | 2 +- .../663876c7-3471-43db-ba51-f410b13d9d7d.json | 16 ++++++++-------- .../66399b0d-8fda-4618-95c4-bfc6191617e9.json | 2 +- .../6ada715d-3aae-4a32-a6a7-429b2e43fb93.json | 4 ++-- .../936321ce-5236-426a-9a20-e0e3c5dc536f.json | 2 +- .../adf5e2c3-64c7-4644-b7b6-d2f0167927e7.json | 16 ++++++++-------- .../ecc2413d-8a48-416e-a3a2-d30106ca36cb.json | 4 ++-- .../f178a4a9-d090-4b56-bc4c-4b72a61a035d.json | 6 +++--- 13 files changed, 54 insertions(+), 54 deletions(-) diff --git a/evaluation_examples/examples/libreoffice_writer/0b17a146-2934-46c7-8727-73ff6b6483e8.json b/evaluation_examples/examples/libreoffice_writer/0b17a146-2934-46c7-8727-73ff6b6483e8.json index 9c7edd3..5b4ad99 100644 --- a/evaluation_examples/examples/libreoffice_writer/0b17a146-2934-46c7-8727-73ff6b6483e8.json +++ b/evaluation_examples/examples/libreoffice_writer/0b17a146-2934-46c7-8727-73ff6b6483e8.json @@ -1,7 +1,7 @@ { "id": "0b17a146-2934-46c7-8727-73ff6b6483e8", "snapshot": "libreoffice_writer", - "instruction": "Change the 2 in H2O to a subscript.", + "instruction": "Help me change the 2 in \"H2O\" to a subscript.", "source": "https://askubuntu.com/questions/245695/how-do-you-insert-subscripts-and-superscripts-into-ordinary-non-formula-text-i", "config": [ { @@ -9,8 +9,8 @@ "parameters": { "files": [ { - "url": "https://drive.usercontent.google.com/download?id=1Nx5AoKNM7tcDRE6y_qjNIDrPOKqhNyfm&export=download&authuser=0&confirm=t&uuid=bb4de348-3bbf-46a2-95b2-e2719c67547a&at=APZUnTUeA-BW7mkQsEw7NGm272zx:1704172916742", - "path": "Desktop/Enter_Subscript.docx" + "url": "https://drive.usercontent.google.com/download?id=1FkorQBeTJ5L2jLuvu4YxHSlBMK4VEEG6&export=download&authuser=0&confirm=t&uuid=cc63dc0b-bae7-4ef6-a40d-e2da721976ef&at=APZUnTWyPZlZPFlqGTWAWXWmS04c:1704976667765", + "path": "Desktop/H2O_Factsheet_WA.docx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "Desktop/Enter_Subscript.docx" + "path": "Desktop/H2O_Factsheet_WA.docx" } } ], @@ -30,13 +30,13 @@ "func": "compare_docx_files", "result": { "type": "vm_file", - "path": "Desktop/Enter_Subscript.docx", - "dest": "Enter_Subscript.docx" + "path": "Desktop/H2O_Factsheet_WA.docx", + "dest": "H2O_Factsheet_WA.docx" }, "expected": { "type": "cloud_file", - "path": "https://drive.usercontent.google.com/download?id=1AaKXeD9ZgfMykgijZ4G8MEzUjmMJElkq&export=download&authuser=0&confirm=t&uuid=5e347f0d-4efc-4478-878e-d89455d1593b&at=APZUnTWCYWfsD4eCeG52VJiK8-xB:1704172886196", - "dest": "Enter_Subscript_Gold.docx" + "path": "https://drive.usercontent.google.com/download?id=1dM_FSTGDWxSW64VEth_wKMYNkvw0y_tq&export=download&authuser=0&confirm=t&uuid=342f41e2-f48f-41ff-8942-f7dfe5de1dba&at=APZUnTXHfskcX3tvmrSbzCOyQIgb:1704976694506", + "dest": "H2O_Factsheet_WA_Gold.docx" } } } \ No newline at end of file diff --git a/evaluation_examples/examples/libreoffice_writer/0e47de2a-32e0-456c-a366-8c607ef7a9d2.json b/evaluation_examples/examples/libreoffice_writer/0e47de2a-32e0-456c-a366-8c607ef7a9d2.json index e187d9c..f5cc925 100644 --- a/evaluation_examples/examples/libreoffice_writer/0e47de2a-32e0-456c-a366-8c607ef7a9d2.json +++ b/evaluation_examples/examples/libreoffice_writer/0e47de2a-32e0-456c-a366-8c607ef7a9d2.json @@ -34,4 +34,4 @@ "dest": "LibreOffice_Open_Source_Word_Processing.docx" } } -} +} \ No newline at end of file diff --git a/evaluation_examples/examples/libreoffice_writer/0e763496-b6bb-4508-a427-fad0b6c3e195.json b/evaluation_examples/examples/libreoffice_writer/0e763496-b6bb-4508-a427-fad0b6c3e195.json index 265f566..6d886c8 100644 --- a/evaluation_examples/examples/libreoffice_writer/0e763496-b6bb-4508-a427-fad0b6c3e195.json +++ b/evaluation_examples/examples/libreoffice_writer/0e763496-b6bb-4508-a427-fad0b6c3e195.json @@ -10,7 +10,7 @@ "files": [ { "url": "https://drive.usercontent.google.com/download?id=1fIHNzFm8JabWoLKOnxrFM722fQ1d_huK&export=download&authuser=0&confirm=t&uuid=d11a8dda-1e4e-4dc9-b05c-e6b47624dbf0&at=APZUnTVG0ViFnKJa00314wVr3uP9:1704185871014", - "path": "Desktop/Change_Font_Through_File.docx" + "path": "Desktop/Dublin_Zoo_Intro.docx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "Desktop/Change_Font_Through_File.docx" + "path": "Desktop/Dublin_Zoo_Intro.docx" } } ], @@ -36,8 +36,8 @@ }, "result": { "type": "vm_file", - "path": "Desktop/Change_Font_Through_File.docx", - "dest": "Change_Font_Through_File.docx" + "path": "Desktop/Dublin_Zoo_Intro.docx", + "dest": "Dublin_Zoo_Intro.docx" } } } \ No newline at end of file diff --git a/evaluation_examples/examples/libreoffice_writer/3ef2b351-8a84-4ff2-8724-d86eae9b842e.json b/evaluation_examples/examples/libreoffice_writer/3ef2b351-8a84-4ff2-8724-d86eae9b842e.json index d9d1129..17196f6 100644 --- a/evaluation_examples/examples/libreoffice_writer/3ef2b351-8a84-4ff2-8724-d86eae9b842e.json +++ b/evaluation_examples/examples/libreoffice_writer/3ef2b351-8a84-4ff2-8724-d86eae9b842e.json @@ -1,7 +1,7 @@ { "id": "3ef2b351-8a84-4ff2-8724-d86eae9b842e", "snapshot": "libreoffice_writer", - "instruction": "center-justify the first line", + "instruction": "Help me center align the heading in LibreOffice.", "source": "https://askubuntu.com/questions/1066351/how-do-you-center-align-in-libreoffice#:~:text=Ctrl%20%2B%20e%20will%20Center%20align%20the%20cursor%20for%20you.", "config": [ { @@ -9,8 +9,8 @@ "parameters": { "files": [ { - "url": "https://drive.usercontent.google.com/download?id=1IQ4rKyHMOui71YlyL7huggpLYFYtj923&export=download&authuser=0&confirm=t&uuid=014c2335-c0c6-4712-9d5a-ca8d3217e07f&at=APZUnTVrM698NQgSh4hqYXR8cjDc:1704185072996", - "path": "Desktop/Centering_First_Line.docx" + "url": "https://drive.usercontent.google.com/download?id=1P8QodvDF-3S50rx6UmW4M2D4Kr-p_Q-h&export=download&authuser=0&confirm=t&uuid=eea70a33-4c3f-4e90-885d-dd3df0d605bc&at=APZUnTX7ISvBhOICNrPLoqK0m3G-:1704971931660", + "path": "Desktop/Constitution_Template_With_Guidelines.docx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "Desktop/Centering_First_Line.docx" + "path": "Desktop/Constitution_Template_With_Guidelines.docx" } } ], @@ -30,8 +30,8 @@ "func": "is_first_line_centered", "result": { "type": "vm_file", - "path": "Desktop/Centering_First_Line.docx", - "dest": "Centering_First_Line.docx" + "path": "Desktop/Constitution_Template_With_Guidelines.docx", + "dest": "Constitution_Template_With_Guidelines.docx" } } } \ No newline at end of file diff --git a/evaluation_examples/examples/libreoffice_writer/45d61a06-6545-4422-97b7-bc76cfa964c1.json b/evaluation_examples/examples/libreoffice_writer/45d61a06-6545-4422-97b7-bc76cfa964c1.json index c892edf..99a960c 100644 --- a/evaluation_examples/examples/libreoffice_writer/45d61a06-6545-4422-97b7-bc76cfa964c1.json +++ b/evaluation_examples/examples/libreoffice_writer/45d61a06-6545-4422-97b7-bc76cfa964c1.json @@ -1,7 +1,7 @@ { "id": "45d61a06-6545-4422-97b7-bc76cfa964c1", "snapshot": "libreoffice_writer", - "instruction": "Replace all newlines with paragraph marks in LibreOffice Write", + "instruction": "Replace all newlines with paragraph marks in LibreOffice Writer", "source": "https://stackoverflow.com/questions/71685737/how-to-replace-all-newlines-with-paragraph-marks-in-libreoffice-write", "config": [ { @@ -9,8 +9,8 @@ "parameters": { "files": [ { - "url": "https://drive.usercontent.google.com/download?id=18XFjPVUnLG_-KOM5sn-Sk74HP_JHivMy&export=download&authuser=0&confirm=t&uuid=d23041bc-2ddd-42c4-84ae-481b953f021c&at=APZUnTVYh0AK0245qsDOCol7SdMB:1704185512767", - "path": "Desktop/Replace_Newlines_with_Paragraph_Marks.docx" + "url": "https://drive.usercontent.google.com/download?id=16lQcSkw-JQ_v8Sg0HkCtnOzyK-4cok8N&export=download&authuser=0&confirm=t&uuid=a3f833ae-2572-4cf3-8a21-6d250e689415&at=APZUnTUfn24NGMtXEzz2Nf7cFLjt:1704975857398", + "path": "Desktop/NOVEL_Submission_Guidelines.docx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "Desktop/Replace_Newlines_with_Paragraph_Marks.docx" + "path": "Desktop/NOVEL_Submission_Guidelines.docx" } } ], @@ -30,13 +30,13 @@ "func": "compare_line_spacing", "expected": { "type": "cloud_file", - "path": "https://drive.usercontent.google.com/download?id=1bP_noic02MuzrM8CdJIQN7F1gN4N8sel&export=download&authuser=0&confirm=t&uuid=657e0e4f-7b96-4d7e-83f4-99b79c68708f&at=APZUnTX7HsmefsMlzQaCGK2fg5Em:1704185514197", - "dest": "Replace_Newlines_with_Paragraph_Marks_Gold.docx" + "path": "https://drive.usercontent.google.com/download?id=1LaS5ObaOsbyKX1M17vi8ZseZwawgvNmf&export=download&authuser=0&confirm=t&uuid=db523e81-fa22-4002-97ff-e5dff92106a7&at=APZUnTVnT3ZYOGW7ZQdeW4SZP7mX:1704975993684", + "dest": "NOVEL_Submission_Guidelines_Gold.docx" }, "result": { "type": "vm_file", - "path": "Desktop/Double_Line_Spacing.docx", - "dest": "Replace_Newlines_with_Paragraph_Marks.docx" + "path": "Desktop/NOVEL_Submission_Guidelines.docx", + "dest": "NOVEL_Submission_Guidelines.docx" } } -} +} \ No newline at end of file diff --git a/evaluation_examples/examples/libreoffice_writer/4bcb1253-a636-4df4-8cb0-a35c04dfef31.json b/evaluation_examples/examples/libreoffice_writer/4bcb1253-a636-4df4-8cb0-a35c04dfef31.json index 8ed9bd2..ba1cb2c 100644 --- a/evaluation_examples/examples/libreoffice_writer/4bcb1253-a636-4df4-8cb0-a35c04dfef31.json +++ b/evaluation_examples/examples/libreoffice_writer/4bcb1253-a636-4df4-8cb0-a35c04dfef31.json @@ -31,4 +31,4 @@ "file_name": "View_Person_Organizational_Summary.pdf", "directory": "/home/user/Downloads/" } -} +} \ No newline at end of file diff --git a/evaluation_examples/examples/libreoffice_writer/663876c7-3471-43db-ba51-f410b13d9d7d.json b/evaluation_examples/examples/libreoffice_writer/663876c7-3471-43db-ba51-f410b13d9d7d.json index 37af3d2..d04915a 100644 --- a/evaluation_examples/examples/libreoffice_writer/663876c7-3471-43db-ba51-f410b13d9d7d.json +++ b/evaluation_examples/examples/libreoffice_writer/663876c7-3471-43db-ba51-f410b13d9d7d.json @@ -1,7 +1,7 @@ { "id": "663876c7-3471-43db-ba51-f410b13d9d7d", "snapshot": "libreoffice_writer", - "instruction": "Insert the equation \"(a + b)^2 = a^2 + 2 a b + b^2\"", + "instruction": "Insert the equation \"(a + b)^2 = a^2 + 2 a b + b^2\" at the position of the cursor.", "source": "https://askubuntu.com/questions/319593/how-to-type-science-equations-in-libre-office", "config": [ { @@ -9,8 +9,8 @@ "parameters": { "files": [ { - "url": "https://drive.usercontent.google.com/download?id=1FgMp7Ny63eXzeF23qHYhqQux31djlkah&export=download&authuser=0&confirm=t&uuid=d6b5208d-3b3a-4972-a641-ed738a419fdb&at=APZUnTX16Fz8Qg-B0NWpWgC-3Dyu:1704184410221", - "path": "Desktop/Insert_Equation.docx" + "url": "https://drive.usercontent.google.com/download?id=1J3--srr-Fmt2z-wOAyPDmO5GoiJMkUvZ&export=download&authuser=0&confirm=t&uuid=5f275f3d-ab7d-4d27-848a-8012af4bcf7f&at=APZUnTVe5ucwe1Q0oVi9jwiY5PF7:1704971494071", + "path": "Desktop/Factoring_Perfect_Square_Trinomials.docx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "Desktop/Insert_Equation.docx" + "path": "Desktop/Factoring_Perfect_Square_Trinomials.docx" } } ], @@ -30,13 +30,13 @@ "func": "compare_insert_equation", "expected": { "type": "cloud_file", - "path": "https://drive.usercontent.google.com/download?id=1hMFJnwHs7Iaexz3b9O2LJQUfsJ2wiwZ9&export=download&authuser=0&confirm=t&uuid=2abb49fb-d9c7-46cf-bc21-e69ecb9cefc6&at=APZUnTVzEZjChcUb4MIoxuq4cGea:1704184411805", - "dest": "Insert_Equation_Gold.docx" + "path": "https://drive.usercontent.google.com/download?id=1QGfyQUPEjOX8osycnjR8E5yHeIEGccKI&export=download&authuser=0&confirm=t&uuid=174491d6-7855-4323-9fa5-5146fde48c4a&at=APZUnTXA8bIcIbtw9mUN-K-IU9bT:1704971524974", + "dest": "Factoring_Perfect_Square_Trinomials_Gold.docx" }, "result": { "type": "vm_file", - "path": "Desktop/Insert_Equation.docx", - "dest": "Insert_Equation.docx" + "path": "Desktop/Factoring_Perfect_Square_Trinomials.docx", + "dest": "Factoring_Perfect_Square_Trinomials.docx" } } } \ No newline at end of file diff --git a/evaluation_examples/examples/libreoffice_writer/66399b0d-8fda-4618-95c4-bfc6191617e9.json b/evaluation_examples/examples/libreoffice_writer/66399b0d-8fda-4618-95c4-bfc6191617e9.json index b86f61d..a45e7fd 100644 --- a/evaluation_examples/examples/libreoffice_writer/66399b0d-8fda-4618-95c4-bfc6191617e9.json +++ b/evaluation_examples/examples/libreoffice_writer/66399b0d-8fda-4618-95c4-bfc6191617e9.json @@ -1,7 +1,7 @@ { "id": "66399b0d-8fda-4618-95c4-bfc6191617e9", "snapshot": "libreoffice_writer", - "instruction": "Insert a 7*5 empty table", + "instruction": "Could you help me insert a 7*5 empty table at the point of cursor?", "source": "https://www.youtube.com/watch?v=l25Evu4ohKg", "config": [ { diff --git a/evaluation_examples/examples/libreoffice_writer/6ada715d-3aae-4a32-a6a7-429b2e43fb93.json b/evaluation_examples/examples/libreoffice_writer/6ada715d-3aae-4a32-a6a7-429b2e43fb93.json index 75eb050..ff6fa76 100644 --- a/evaluation_examples/examples/libreoffice_writer/6ada715d-3aae-4a32-a6a7-429b2e43fb93.json +++ b/evaluation_examples/examples/libreoffice_writer/6ada715d-3aae-4a32-a6a7-429b2e43fb93.json @@ -1,7 +1,7 @@ { "id": "6ada715d-3aae-4a32-a6a7-429b2e43fb93", "snapshot": "libreoffice_writer", - "instruction": "Copy the screenshot 1.png from the desktop to where my cursor is locatedInsert the image which is in IMAGE_PATH where my cursor is", + "instruction": "Copy the screenshot 1.png from the desktop to where my cursor is located", "source": "https://www.quora.com/How-do-you-insert-images-into-a-LibreOffice-Writer-document", "config": [ { @@ -50,4 +50,4 @@ "dest": "Viewing_Your_Class_Schedule_and_Textbooks_Gold.docx" } } -} +} \ No newline at end of file diff --git a/evaluation_examples/examples/libreoffice_writer/936321ce-5236-426a-9a20-e0e3c5dc536f.json b/evaluation_examples/examples/libreoffice_writer/936321ce-5236-426a-9a20-e0e3c5dc536f.json index db0e119..92591f0 100644 --- a/evaluation_examples/examples/libreoffice_writer/936321ce-5236-426a-9a20-e0e3c5dc536f.json +++ b/evaluation_examples/examples/libreoffice_writer/936321ce-5236-426a-9a20-e0e3c5dc536f.json @@ -1,7 +1,7 @@ { "id": "936321ce-5236-426a-9a20-e0e3c5dc536f", "snapshot": "libreoffice_writer", - "instruction": "Convert the content seperated by commas to a table", + "instruction": "Could you help me convert the text seperated by commas to a table?", "source": "https://www.youtube.com/watch?v=l25Evu4ohKg", "config": [ { diff --git a/evaluation_examples/examples/libreoffice_writer/adf5e2c3-64c7-4644-b7b6-d2f0167927e7.json b/evaluation_examples/examples/libreoffice_writer/adf5e2c3-64c7-4644-b7b6-d2f0167927e7.json index 6b1ce4e..a932884 100644 --- a/evaluation_examples/examples/libreoffice_writer/adf5e2c3-64c7-4644-b7b6-d2f0167927e7.json +++ b/evaluation_examples/examples/libreoffice_writer/adf5e2c3-64c7-4644-b7b6-d2f0167927e7.json @@ -1,7 +1,7 @@ { "id": "adf5e2c3-64c7-4644-b7b6-d2f0167927e7", "snapshot": "libreoffice_writer", - "instruction": "Helping me adding \"C. Luo and M. J. Carey, \"LSM-based storage techniques: a survey,\" The VLDB Journal, vol. 29, no. 1, pp. 393–418, 2020.\" to my reference list, and add a cross reference at the end of the first paragraph", + "instruction": "Help me adding \"Steinberg, F. M., Bearden, M. M., & Keen, C. L. (2003). Cocoa and chocolate flavonoids: Implications for cardiovascular health. Journal of the American Dietetic Association, 103(2), 215-223. doi: 10.1053/jada.2003.50028\" to my reference list, and add a cross reference where my cursor is located (in the fourth paragraph).", "source": "https://seekstar.github.io/2022/04/11/libreoffice%E5%BC%95%E7%94%A8%E6%96%87%E7%8C%AE/", "config": [ { @@ -9,8 +9,8 @@ "parameters": { "files": [ { - "url": "https://drive.usercontent.google.com/download?id=1xOfwImgkPzdmjQomj-MCFd8nQS75OjaH&export=download&authuser=0&confirm=t&uuid=7eb91c26-dad5-4480-b1ec-35e506cde1e4&at=APZUnTW01MvBI_gkC8yoiyAVs7yi:1704188254979", - "path": "Desktop/Add_Citation_Cross_Reference.docx" + "url": "https://drive.usercontent.google.com/download?id=1ShGL4gWSV7nzamAb0V2KqjoCOhyodcKU&export=download&authuser=0&confirm=t&uuid=5f67edb8-cbbf-4a83-b46e-f193ad55e1e8&at=APZUnTVRJenYCM--vETagQ5ACTT5:1704979226579", + "path": "Desktop/Essay_Writing_English_for_uni.docx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "Desktop/Add_Citation_Cross_Reference.docx" + "path": "Desktop/Essay_Writing_English_for_uni.docx" } } ], @@ -30,13 +30,13 @@ "func": "compare_docx_files", "expected": { "type": "cloud_file", - "path": "https://drive.usercontent.google.com/download?id=1wFQU7hkAT2wmSHTgM22F9Ep4WXmymEMW&export=download&authuser=0&confirm=t&uuid=a7ea1eec-678b-4407-b023-df13cc6f8c54&at=APZUnTW3WoqOfS9A1BW79XfV8jKh:1704188260410", - "dest": "Add_Citation_Cross_Reference_Gold.docx" + "path": "https://drive.usercontent.google.com/download?id=1bf7IKjjxGAQfbOlq9rLPzjTtkOZ3dREj&export=download&authuser=0&confirm=t&uuid=0420cfa5-7e51-4688-8c93-74748914ce52&at=APZUnTWIShIleccvgVBIr6ZsSnOw:1704979256798", + "dest": "Essay_Writing_English_for_uni_Gold.docx" }, "result": { "type": "vm_file", - "path": "Desktop/Add_Citation_Cross_Reference.docx", - "dest": "Add_Citation_Cross_Reference.docx" + "path": "Desktop/Essay_Writing_English_for_uni.docx", + "dest": "Essay_Writing_English_for_uni.docx" } } } \ No newline at end of file diff --git a/evaluation_examples/examples/libreoffice_writer/ecc2413d-8a48-416e-a3a2-d30106ca36cb.json b/evaluation_examples/examples/libreoffice_writer/ecc2413d-8a48-416e-a3a2-d30106ca36cb.json index c8867b7..25a9d38 100644 --- a/evaluation_examples/examples/libreoffice_writer/ecc2413d-8a48-416e-a3a2-d30106ca36cb.json +++ b/evaluation_examples/examples/libreoffice_writer/ecc2413d-8a48-416e-a3a2-d30106ca36cb.json @@ -1,7 +1,7 @@ { "id": "ecc2413d-8a48-416e-a3a2-d30106ca36cb", "snapshot": "libreoffice_writer", - "instruction": "Insert a blank page", + "instruction": "Help me insert a blank page where my cursor is located.", "source": "https://www.quora.com/How-can-I-insert-a-blank-page-on-libreoffice", "config": [ { @@ -34,4 +34,4 @@ "dest": "Sample_Statutory_Declaration.docx" } } -} +} \ No newline at end of file diff --git a/evaluation_examples/examples/libreoffice_writer/f178a4a9-d090-4b56-bc4c-4b72a61a035d.json b/evaluation_examples/examples/libreoffice_writer/f178a4a9-d090-4b56-bc4c-4b72a61a035d.json index 1d710c3..315ea4d 100644 --- a/evaluation_examples/examples/libreoffice_writer/f178a4a9-d090-4b56-bc4c-4b72a61a035d.json +++ b/evaluation_examples/examples/libreoffice_writer/f178a4a9-d090-4b56-bc4c-4b72a61a035d.json @@ -9,8 +9,8 @@ "parameters": { "files": [ { - "url": "https://drive.usercontent.google.com/download?id=1X2XTU2ZFuMXOhm7T400e6AOe6eBYxWzD&export=download&authuser=0&confirm=t&uuid=1318923f-6d54-4148-aa80-a454b9963cec&at=APZUnTU-h1nmcjBO_ytWVxXuh8l9:1704187013730", - "path": "Desktop/Set_Default_Font.docx" + "url": "https://drive.usercontent.google.com/download?id=1xREbNAu_2wLTs8EQT0NnHLpIkAVAfpyk&export=download&authuser=0&confirm=t&uuid=dd5cb525-ff4b-41a2-8123-d488f2f21fad&at=APZUnTXaYBqLT9fRtGYZHOedq-PG:1704977194647", + "path": "Desktop/loa-one-time-submission-sealand.docx" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "Desktop/Set_Default_Font.docx" + "path": "Desktop/loa-one-time-submission-sealand.docx" } } ], From 3c04872dcf2d110a1c7a7ed461ca53bf8ca5a6b6 Mon Sep 17 00:00:00 2001 From: David Chang Date: Thu, 11 Jan 2024 22:43:38 +0800 Subject: [PATCH 4/7] ver Jan11thv2 a new Thunderbird example w.r.t. email filter --- desktop_env/evaluators/metrics/__init__.py | 2 +- desktop_env/evaluators/metrics/general.py | 12 +- desktop_env/evaluators/metrics/thunderbird.py | 125 ++++++++++++++++-- desktop_env/evaluators/metrics/utils.py | 3 + .../e1e75309-3ddb-4d09-92ec-de869c928143.json | 77 +++++++++++ ...9-3ddb-4d09-92ec-de869c928143.json.nosetup | 55 ++++++++ main.py | 4 +- 7 files changed, 265 insertions(+), 13 deletions(-) create mode 100644 evaluation_examples/examples/thunderbird/e1e75309-3ddb-4d09-92ec-de869c928143.json create mode 100644 evaluation_examples/examples/thunderbird/e1e75309-3ddb-4d09-92ec-de869c928143.json.nosetup diff --git a/desktop_env/evaluators/metrics/__init__.py b/desktop_env/evaluators/metrics/__init__.py index 7428eb2..7a44195 100644 --- a/desktop_env/evaluators/metrics/__init__.py +++ b/desktop_env/evaluators/metrics/__init__.py @@ -7,4 +7,4 @@ from .pdf import check_pdf_pages from .libreoffice import check_libre_locale from .vlc import is_vlc_playing, is_vlc_recordings_folder from .general import check_csv, check_accessibility_tree, check_list -from .thunderbird import check_thunderbird_prefs +from .thunderbird import check_thunderbird_prefs, check_thunderbird_filter diff --git a/desktop_env/evaluators/metrics/general.py b/desktop_env/evaluators/metrics/general.py index 6f44d83..7acf23f 100644 --- a/desktop_env/evaluators/metrics/general.py +++ b/desktop_env/evaluators/metrics/general.py @@ -13,8 +13,10 @@ from rapidfuzz import fuzz import functools import re -def _match_record(pattern: Dict[str, str], item: Dict[str, str]) -> bool: - return all(k in item and item[k]==val for k, val in pattern.items()) +from .utils import _match_record + +#def _match_record(pattern: Dict[str, str], item: Dict[str, str]) -> bool: + #return all(k in item and item[k]==val for k, val in pattern.items()) def check_csv(result: str, rules: Dict[str, List[Dict[str, str]]]) -> float: """ @@ -30,6 +32,9 @@ def check_csv(result: str, rules: Dict[str, List[Dict[str, str]]]) -> float: float """ + if result is None: + return 0. + expect_metrics = [False] * len(rules.get("expect", [])) unexpect_metric = True with open(result) as f: @@ -55,6 +60,9 @@ def check_list(result: str, rules: Dict[str, List[str]]) -> float: float """ + if result is None: + return 0. + expect_patterns: List[Pattern[str]] = [re.compile(ptt) for ptt in rules.get("expect", [])] unexpect_patterns: List[Pattern[str]] = [re.compile(ptt) for ptt in rules.get("unexpect", [])] diff --git a/desktop_env/evaluators/metrics/thunderbird.py b/desktop_env/evaluators/metrics/thunderbird.py index b386243..b202d94 100644 --- a/desktop_env/evaluators/metrics/thunderbird.py +++ b/desktop_env/evaluators/metrics/thunderbird.py @@ -1,10 +1,11 @@ -from typing import List, Pattern, Dict, Match -from typing import Union, Any, Optional, Iterable, TypeVar +from typing import List, Pattern, Dict, Match, Tuple +from typing import Union, Any, Optional, Iterable, TypeVar, Callable import re import functools import operator import json +from .utils import _match_record import logging logger = logging.getLogger("desktopenv.metric.thunderbird") @@ -82,20 +83,128 @@ def check_thunderbird_prefs(result: str, rule: Dict[str, Dict[str, Dict[str, Any return float(all(expect_metrics.values()) and unexpect_metric) +_value_processor: Callable[[str], str] = lambda val: val.replace("\\\"", "\"").replace("\\\\", "\\") +#_condition_pattern: Pattern[str] = re.compile(r'(?PAND|OR) \((?P[\w ]+),(?P[\w ' + '\'' + r']+),(?:"(?P(?:[^"]|\")+)"|(?P[^)]+))\)') +_condition_pattern: Pattern[str] = re.compile(r'(?:AND|OR) \((?:[\w ]+),(?:[\w ' + '\'' + r']+),(?:"(?:(?:[^"]|\")+)"|(?:[^)]+))\)') +def check_thunderbird_filter(result: str, rules: Dict[str, List[Dict[str, str]]]) -> float: + """ + Args: + result (str): path to filter def file + rules (Dict[str, List[Dict[str, str]]]): dict like + { + "expect": [{key: value}] + "unexpect": [{key: value}] + } + + Returns: + float + """ + + if result is None: + return 0. + + # read filter def file + # a filter: + # { + # "name": "Name", + # "enabled": "yes" | "no", + # "type": "17", + # "action": "Move to folder" | ..., + # "actionValue": ..., + # "condition": [...] + # } + filters: List[Dict[str, Union[str, List[str]]]] = [] + with open(result) as f: + for l in f: + if l.startswith("name="): + filter_: Dict[str, Union[str, List[str]]] = {} + filter_["name"] = _value_processor(l[6:-2]) + elif l.startswith("enabled="): + filter_["enabled"] = _value_processor(l[9:-2]) + elif l.startswith("type="): + filter_["type"] = _value_processor(l[6:-2]) + elif l.startswith("action="): + filter_["action"] = _value_processor(l[8:-2]) + elif l.startswith("actionValue="): + filter_["actionValue"] = _value_processor(l[13:-2]) + elif l.startswith("condition="): + condition_str: str = _value_processor(l[11:-2]) + logger.debug("FILTER CONDITION: %s", condition_str) + + conditions: List[str] =\ + _condition_pattern.findall(condition_str) + logger.debug("FILTER CONDITIONS: %s", repr(conditions)) + + filter_["condition"] = conditions + logger.debug("FILTER %s", repr(filter_)) + filters.append(filter_) + + expect_metrics = [False] * len(rules.get("expect", [])) + unexpect_metric = True + for flt in filters: + for i, r in enumerate(rules.get("expect", [])): + expect_metrics[i] = expect_metrics[i] or _match_record(r, flt) + unexpect_metric = unexpect_metric and not any(_match_record(r, flt) for r in rules.get("unexpect", [])) + return float(all(expect_metrics) and unexpect_metric) + if __name__ == "__main__": import lxml.etree from lxml.cssselect import CSSSelector from lxml.etree import _Element #xml = "../../任务数据/Thunderbird/vertical-card-view.xml" - xml = "../../任务数据/Thunderbird/vertical-table-view.xml" - at: _Element = lxml.etree.parse(xml) + #xml = "../../任务数据/Thunderbird/vertical-table-view.xml" + #at: _Element = lxml.etree.parse(xml) #elements: List[_Element] = CSSSelector('application[name=Thunderbird] page-tab-list')(at) # page tab tags #elements: List[_Element] = CSSSelector('application[name=Thunderbird] panel>scroll-pane>internal-frame>panel[name$="anonym-x2024@outlook.com"]')(at) # email tag page #elements: List[_Element] = CSSSelector('application[name=Thunderbird] panel>scroll-pane>internal-frame>panel[name$="anonym-x2024@outlook.com"]>section:nth-child(3)')(at) # email tag page #elements: List[_Element] = CSSSelector('application[name=Thunderbird] panel>scroll-pane>internal-frame>panel[name$="anonym-x2024@outlook.com"]>section[attr|id=threadPane]>section[attr|id="threadTree"]>table[attr|class="tree-table"]>section[attr|class~="tree-table-header"]>table-row>column-header[name=Subject]>push-button', namespaces={"attr": "uri:deskat:attributes.at-spi.gnome.org"})(at) # table view, column header - elements: List[_Element] = CSSSelector('application[name=Thunderbird] panel>scroll-pane>internal-frame>panel[name$="anonym-x2024@outlook.com"]>section[attr|id=threadPane]>section[attr|id="threadTree"]>table[attr|class="tree-table"]>tree>tree-item>section[name="Subject"]>section>section', namespaces={"attr": "uri:deskat:attributes.at-spi.gnome.org"})(at) # table view, column header - print(len(elements)) - for elm in elements: - print(lxml.etree.tostring(elm, encoding="unicode", pretty_print=True)) + #elements: List[_Element] = CSSSelector('application[name=Thunderbird] panel>scroll-pane>internal-frame>panel[name$="anonym-x2024@outlook.com"]>section[attr|id=threadPane]>section[attr|id="threadTree"]>table[attr|class="tree-table"]>tree>tree-item>section[name="Subject"]>section>section', namespaces={"attr": "uri:deskat:attributes.at-spi.gnome.org"})(at) # table view, column header + #print(len(elements)) + #for elm in elements: + #print(lxml.etree.tostring(elm, encoding="unicode", pretty_print=True)) + + import datetime + import os + import sys + + logger = logging.getLogger() + logger.setLevel(logging.DEBUG) + + datetime_str: str = datetime.datetime.now().strftime("%Y%m%d@%H%M%S") + + file_handler = logging.FileHandler(os.path.join("logs", "normal-{:}.log".format(datetime_str))) + debug_handler = logging.FileHandler(os.path.join("logs", "debug-{:}.log".format(datetime_str))) + stdout_handler = logging.StreamHandler(sys.stdout) + sdebug_handler = logging.FileHandler(os.path.join("logs", "sdebug-{:}.log".format(datetime_str))) + + file_handler.setLevel(logging.INFO) + debug_handler.setLevel(logging.DEBUG) + stdout_handler.setLevel(logging.INFO) + sdebug_handler.setLevel(logging.DEBUG) + + formatter = logging.Formatter(fmt="\x1b[1;33m[%(asctime)s \x1b[31m%(levelname)s \x1b[32m%(module)s/%(lineno)d-%(processName)s\x1b[1;33m] \x1b[0m%(message)s") + file_handler.setFormatter(formatter) + debug_handler.setFormatter(formatter) + stdout_handler.setFormatter(formatter) + sdebug_handler.setFormatter(formatter) + + stdout_handler.addFilter(logging.Filter("desktopenv")) + sdebug_handler.addFilter(logging.Filter("desktopenv")) + + logger.addHandler(file_handler) + logger.addHandler(debug_handler) + logger.addHandler(stdout_handler) + logger.addHandler(sdebug_handler) + + print( check_thunderbird_filter( "../../任务数据/Thunderbird/msgFilterRules.dat" + , { "expect": [ { "enabled": "yes" + , "action": "Move to folder" + , "actionValue": "mailbox://nobody@Local%20Folders/Promotions" + , "condition": ["AND (subject,contains,discount)"] + } + ] + } + ) + ) diff --git a/desktop_env/evaluators/metrics/utils.py b/desktop_env/evaluators/metrics/utils.py index 93bc778..6f20d30 100644 --- a/desktop_env/evaluators/metrics/utils.py +++ b/desktop_env/evaluators/metrics/utils.py @@ -125,6 +125,9 @@ def load_charts(xlsx_file: Workbook, **options) -> Dict[str, Any]: chart_set[series] = info return chart_set +def _match_record(pattern: Dict[str, Any], item: Dict[str, Any]) -> bool: + return all(k in item and item[k]==val for k, val in pattern.items()) + if __name__ == "__main__": path1 = "../../../../../任务数据/LibreOffice Calc/Create_column_charts_using_statistics_gold_line_scatter.xlsx" workbook1: Workbook = openpyxl.load_workbook(filename=path1) diff --git a/evaluation_examples/examples/thunderbird/e1e75309-3ddb-4d09-92ec-de869c928143.json b/evaluation_examples/examples/thunderbird/e1e75309-3ddb-4d09-92ec-de869c928143.json new file mode 100644 index 0000000..3dd986a --- /dev/null +++ b/evaluation_examples/examples/thunderbird/e1e75309-3ddb-4d09-92ec-de869c928143.json @@ -0,0 +1,77 @@ +{ + "id": "e1e75309-3ddb-4d09-92ec-de869c928143", + "snapshot": "thunderbird", + "instruction": "Create a local folder called \"Promotions\" and create a filter to auto move the inbox emails whose subject contains “discount” to the new folder", + "source": "https://support.mozilla.org/en-US/kb/organize-your-messages-using-filters", + "config": [ + { + "type": "download", + "parameters": { + "files": [ + { + "url": "https://drive.usercontent.google.com/download?id=1EHLRWzBCOsyERkSMUnTF2pnsR0n6ZvtR&export=download&authuser=0&confirm=t&uuid=de09bd5e-bef8-499a-b599-c642af190e10&at=APZUnTXqOsQkxl0zMSX6R1Sgp_v3:1704362491712", + "path": "/home/user/thunderbird-profile.tar.gz" + } + ] + } + }, + { + "type": "execute", + "parameters": { + "command": [ + "tar", + "-xzv", + "--recursive-unlink", + "-f", + "/home/user/thunderbird-profile.tar.gz", + "-C", + "/home/user/" + ] + } + }, + { + "type": "launch", + "parameters": { + "command": [ + "/usr/bin/thunderbird" + ] + } + } + ], + "trajectory": "trajectories/e1e75309-3ddb-4d09-92ec-de869c928143", + "related_apps": [ + "thunderbird" + ], + "evaluator": { + "postconfig": [ + { + "type": "command", + "parameters": { + "command": ["wmctrl", "-Fc", "Message Filters"], + "until": { + "returncode": 1 + } + } + } + ], + "func": "check_thunderbird_filter", + "result": { + "type": "vm_file", + "path": "/home/user/.thunderbird/t5q2a5hp.default-release/ImapMail/outlook.office365.com/msgFilterRules.dat", + "dest": "msgFilterRules.dat" + }, + "expected": { + "type": "rule", + "rules": { + "expect": [ + { + "enabled": "yes", + "action": "Move to folder", + "actionValue": "mailbox://nobody@Local%20Folders/Promotions", + "condition": ["AND (subject,contains,discount)"] + } + ] + } + } + } +} diff --git a/evaluation_examples/examples/thunderbird/e1e75309-3ddb-4d09-92ec-de869c928143.json.nosetup b/evaluation_examples/examples/thunderbird/e1e75309-3ddb-4d09-92ec-de869c928143.json.nosetup new file mode 100644 index 0000000..66af75d --- /dev/null +++ b/evaluation_examples/examples/thunderbird/e1e75309-3ddb-4d09-92ec-de869c928143.json.nosetup @@ -0,0 +1,55 @@ +{ + "id": "e1e75309-3ddb-4d09-92ec-de869c928143", + "snapshot": "thunderbird", + "instruction": "Create a local folder called \"Promotions\" and create a filter to auto move the inbox emails whose subject contains “discount” to the new folder", + "source": "https://support.mozilla.org/en-US/kb/organize-your-messages-using-filters", + "config": [ + { + "type": "download", + "parameters": { + "files": [ + { + "url": "https://drive.usercontent.google.com/download?id=1EHLRWzBCOsyERkSMUnTF2pnsR0n6ZvtR&export=download&authuser=0&confirm=t&uuid=de09bd5e-bef8-499a-b599-c642af190e10&at=APZUnTXqOsQkxl0zMSX6R1Sgp_v3:1704362491712", + "path": "/home/user/thunderbird-profile.tar.gz" + } + ] + } + } + ], + "trajectory": "trajectories/e1e75309-3ddb-4d09-92ec-de869c928143", + "related_apps": [ + "thunderbird" + ], + "evaluator": { + "postconfig": [ + { + "type": "command", + "parameters": { + "command": ["wmctrl", "-Fc", "Message Filters"], + "until": { + "returncode": 1 + } + } + } + ], + "func": "check_thunderbird_filter", + "result": { + "type": "vm_file", + "path": "/home/user/.thunderbird/t5q2a5hp.default-release/ImapMail/outlook.office365.com/msgFilterRules.dat", + "dest": "msgFilterRules.dat" + }, + "expected": { + "type": "rule", + "rules": { + "expect": [ + { + "enabled": "yes", + "action": "Move to folder", + "actionValue": "mailbox://nobody@Local%20Folders/Promotions", + "condition": ["AND (subject,contains,discount)"] + } + ] + } + } + } +} diff --git a/main.py b/main.py index b4d1ef8..5da8091 100644 --- a/main.py +++ b/main.py @@ -44,9 +44,9 @@ def human_agent(): Runs the Gym environment with human input. """ - with open("evaluation_examples/examples/thunderbird/6766f2b8-8a72-417f-a9e5-56fcaa735837.json.nosetup", "r") as f: + with open("evaluation_examples/examples/thunderbird/e1e75309-3ddb-4d09-92ec-de869c928143.json.nosetup", "r") as f: example = json.load(f) - example["snapshot"] = "Snapshot 17" + example["snapshot"] = "Snapshot 18" env = DesktopEnv( path_to_vm="../../../../大文件/镜像/Ubuntu-1218/Ubuntu/Ubuntu.vmx" , action_space="computer_13" From e79235f568187b41e0f2af393ce4eda3feaa49c0 Mon Sep 17 00:00:00 2001 From: tsuky_chen <3107760494@qq.com> Date: Fri, 12 Jan 2024 16:07:55 +0800 Subject: [PATCH 5/7] 2 init gimp example --- desktop_env/evaluators/metrics/__init__.py | 1 + desktop_env/evaluators/metrics/gimp.py | 54 +++++++++++++++++++ .../gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 | 42 +++++++++++++++ .../7a4deb26-d57d-4ea9-9a73-630f66a7b568 copy | 42 +++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 create mode 100644 evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 copy diff --git a/desktop_env/evaluators/metrics/__init__.py b/desktop_env/evaluators/metrics/__init__.py index f520afb..6f7759d 100644 --- a/desktop_env/evaluators/metrics/__init__.py +++ b/desktop_env/evaluators/metrics/__init__.py @@ -9,3 +9,4 @@ from .table import check_sheet_list, check_xlsx_freeze, check_xlsx_zoom from .table import compare_table from .vlc import is_vlc_playing, is_vlc_recordings_folder, is_vlc_fullscreen, compare_images, compare_audios, \ compare_videos +from .gimp import increase_saturation, decrease_brightness diff --git a/desktop_env/evaluators/metrics/gimp.py b/desktop_env/evaluators/metrics/gimp.py index fbc328c..9607ba6 100644 --- a/desktop_env/evaluators/metrics/gimp.py +++ b/desktop_env/evaluators/metrics/gimp.py @@ -20,3 +20,57 @@ def get_gimp_export_path(): # Handle the case where the configuration file is not found print("GIMP configuration file not found") return False + +from PIL import Image, ImageChops, ImageStat + +def calculate_saturation(image): + # convert the image to HSV mode + hsv_image = image.convert("HSV") + + saturation_channel = hsv_image.split()[1] + + # calculate the mean saturation level + stat = ImageStat.Stat(saturation_channel) + mean_saturation = stat.mean[0] + + return mean_saturation + +def increase_saturation(image1_path, image2_path): + image1 = Image.open(image1_path) + image2 = Image.open(image2_path) + + # calculate the saturation level of each image + saturation1 = calculate_saturation(image1) + saturation2 = calculate_saturation(image2) + + return 1 if saturation1 < saturation2 else 0 + +def calculate_brightness(image): + # Convert the image to grayscale mode + grayscale_image = image.convert("L") + + # Get the image data + pixels = list(grayscale_image.getdata()) + + brightness = sum(pixels) / len(pixels) + return brightness + +def decrease_brightness(image1_path, image2_path): + image1 = Image.open(image1_path) + image2 = Image.open(image2_path) + + brightness1 = calculate_brightness(image1) + brightness2 = calculate_brightness(image2) + + return 1 if brightness1 > brightness2 else 0 + +if __name__ == "__main__": + # 输入两张图片的路径 + image1_path = "../Downloads/1.png" + image2_path = "../Downloads/edited_darker.png" + + # 比较图片亮度 + decrease_brightness(image1_path, image2_path) + + # 比较图片饱和度 + increase_saturation(image1_path, image2_path) diff --git a/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 b/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 new file mode 100644 index 0000000..ab644b2 --- /dev/null +++ b/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 @@ -0,0 +1,42 @@ +{ + "id": "7a4deb26-d57d-4ea9-9a73-630f66a7b568", + "snapshot": "gimp", + "instruction": "Make my picture less bright, please.", + "source": "https://www.quora.com/How-do-I-edit-a-photo-in-GIMP", + "config": [ + { + "type": "download", + "parameters": { + "files": [ + { + "url": "https://drive.usercontent.google.com/download?id=1SIvX9Wimyw6i2UvnoLTNDHIObvDLAsIM&export=download&authuser=0&confirm=t&uuid=a48447ab-13a2-421f-9662-6ffff8f6f6d5&at=APZUnTVRxofs822XxgEv33WwYCkb:1705046264363", + "path": "Desktop/1.png" + } + ] + } + }, + { + "type": "open", + "parameters": { + "path": "Desktop/View_Person_Organizational_Summary.docx" + } + } + ], + "trajectory": "trajectories/", + "related_apps": [ + "gimp" + ], + "evaluator": { + "func": "decrease_brightness", + "result": { + "type": "vm_file", + "path": "Desktop/1.png", + "dest": "1.png" + }, + "expected": { + "type": "vm_file", + "path": "Desktop/edited_darker.png", + "dest": "edited_darker.png" + } + } +} \ No newline at end of file diff --git a/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 copy b/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 copy new file mode 100644 index 0000000..eb8862a --- /dev/null +++ b/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 copy @@ -0,0 +1,42 @@ +{ + "id": "554785e9-4523-4e7a-b8e1-8016f565f56a", + "snapshot": "gimp", + "instruction": "Could you help me increase the saturation of my photo to make it more colorful?", + "source": "https://www.quora.com/How-do-I-edit-a-photo-in-GIMP", + "config": [ + { + "type": "download", + "parameters": { + "files": [ + { + "url": "https://drive.usercontent.google.com/download?id=1SIvX9Wimyw6i2UvnoLTNDHIObvDLAsIM&export=download&authuser=0&confirm=t&uuid=a48447ab-13a2-421f-9662-6ffff8f6f6d5&at=APZUnTVRxofs822XxgEv33WwYCkb:1705046264363", + "path": "Desktop/1.png" + } + ] + } + }, + { + "type": "open", + "parameters": { + "path": "Desktop/View_Person_Organizational_Summary.docx" + } + } + ], + "trajectory": "trajectories/", + "related_apps": [ + "gimp" + ], + "evaluator": { + "func": "increase_saturation", + "result": { + "type": "vm_file", + "path": "Desktop/1.png", + "dest": "1.png" + }, + "expected": { + "type": "vm_file", + "path": "Desktop/edited_colorful.png", + "dest": "edited_colorful.png" + } + } +} \ No newline at end of file From b3109bf856ae9df78a3d034ef214450a540b829f Mon Sep 17 00:00:00 2001 From: Siheng Zhao <1730625285@qq.com> Date: Fri, 12 Jan 2024 16:14:41 +0800 Subject: [PATCH 6/7] update vscode eval extension: eval-0.0.1.vsix --- vscodeEvalExtension/README.md | 71 -- vscodeEvalExtension/eval-0.0.1.vsix | Bin 0 -> 60906 bytes .../node_modules/.package-lock.json | 58 +- .../node_modules/@types/fs-extra/LICENSE | 21 + .../node_modules/@types/fs-extra/README.md | 15 + .../node_modules/@types/fs-extra/esm.d.mts | 111 ++ .../node_modules/@types/fs-extra/index.d.ts | 996 ++++++++++++++++++ .../node_modules/@types/fs-extra/package.json | 84 ++ .../node_modules/@types/jsonfile/LICENSE | 21 + .../node_modules/@types/jsonfile/README.md | 15 + .../node_modules/@types/jsonfile/index.d.ts | 71 ++ .../node_modules/@types/jsonfile/package.json | 37 + .../node_modules/@types/jsonfile/utils.d.ts | 9 + .../node_modules/fs-extra/LICENSE | 15 + .../node_modules/fs-extra/README.md | 292 +++++ .../node_modules/fs-extra/package.json | 71 ++ .../node_modules/graceful-fs/LICENSE | 15 + .../node_modules/graceful-fs/README.md | 143 +++ .../node_modules/graceful-fs/clone.js | 23 + .../node_modules/graceful-fs/graceful-fs.js | 448 ++++++++ .../graceful-fs/legacy-streams.js | 118 +++ .../node_modules/graceful-fs/package.json | 53 + .../node_modules/graceful-fs/polyfills.js | 355 +++++++ .../node_modules/jsonfile/CHANGELOG.md | 171 +++ .../node_modules/jsonfile/LICENSE | 15 + .../node_modules/jsonfile/README.md | 230 ++++ .../node_modules/jsonfile/index.js | 88 ++ .../node_modules/jsonfile/package.json | 40 + .../node_modules/jsonfile/utils.js | 14 + .../node_modules/universalify/LICENSE | 20 + .../node_modules/universalify/README.md | 76 ++ .../node_modules/universalify/index.js | 24 + .../node_modules/universalify/package.json | 34 + vscodeEvalExtension/out/extension.js | 15 +- vscodeEvalExtension/out/extension.js.map | 2 +- vscodeEvalExtension/package-lock.json | 62 +- vscodeEvalExtension/package.json | 12 +- vscodeEvalExtension/src/extension.ts | 17 +- 38 files changed, 3758 insertions(+), 104 deletions(-) create mode 100644 vscodeEvalExtension/eval-0.0.1.vsix create mode 100644 vscodeEvalExtension/node_modules/@types/fs-extra/LICENSE create mode 100644 vscodeEvalExtension/node_modules/@types/fs-extra/README.md create mode 100644 vscodeEvalExtension/node_modules/@types/fs-extra/esm.d.mts create mode 100644 vscodeEvalExtension/node_modules/@types/fs-extra/index.d.ts create mode 100644 vscodeEvalExtension/node_modules/@types/fs-extra/package.json create mode 100644 vscodeEvalExtension/node_modules/@types/jsonfile/LICENSE create mode 100644 vscodeEvalExtension/node_modules/@types/jsonfile/README.md create mode 100644 vscodeEvalExtension/node_modules/@types/jsonfile/index.d.ts create mode 100644 vscodeEvalExtension/node_modules/@types/jsonfile/package.json create mode 100644 vscodeEvalExtension/node_modules/@types/jsonfile/utils.d.ts create mode 100644 vscodeEvalExtension/node_modules/fs-extra/LICENSE create mode 100644 vscodeEvalExtension/node_modules/fs-extra/README.md create mode 100644 vscodeEvalExtension/node_modules/fs-extra/package.json create mode 100644 vscodeEvalExtension/node_modules/graceful-fs/LICENSE create mode 100644 vscodeEvalExtension/node_modules/graceful-fs/README.md create mode 100644 vscodeEvalExtension/node_modules/graceful-fs/clone.js create mode 100644 vscodeEvalExtension/node_modules/graceful-fs/graceful-fs.js create mode 100644 vscodeEvalExtension/node_modules/graceful-fs/legacy-streams.js create mode 100644 vscodeEvalExtension/node_modules/graceful-fs/package.json create mode 100644 vscodeEvalExtension/node_modules/graceful-fs/polyfills.js create mode 100644 vscodeEvalExtension/node_modules/jsonfile/CHANGELOG.md create mode 100644 vscodeEvalExtension/node_modules/jsonfile/LICENSE create mode 100644 vscodeEvalExtension/node_modules/jsonfile/README.md create mode 100644 vscodeEvalExtension/node_modules/jsonfile/index.js create mode 100644 vscodeEvalExtension/node_modules/jsonfile/package.json create mode 100644 vscodeEvalExtension/node_modules/jsonfile/utils.js create mode 100644 vscodeEvalExtension/node_modules/universalify/LICENSE create mode 100644 vscodeEvalExtension/node_modules/universalify/README.md create mode 100644 vscodeEvalExtension/node_modules/universalify/index.js create mode 100644 vscodeEvalExtension/node_modules/universalify/package.json diff --git a/vscodeEvalExtension/README.md b/vscodeEvalExtension/README.md index acfb4db..e69de29 100644 --- a/vscodeEvalExtension/README.md +++ b/vscodeEvalExtension/README.md @@ -1,71 +0,0 @@ -# eval README - -This is the README for your extension "eval". After writing up a brief description, we recommend including the following sections. - -## Features - -Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file. - -For example if there is an image subfolder under your extension project workspace: - -\!\[feature X\]\(images/feature-x.png\) - -> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow. - -## Requirements - -If you have any requirements or dependencies, add a section describing those and how to install and configure them. - -## Extension Settings - -Include if your extension adds any VS Code settings through the `contributes.configuration` extension point. - -For example: - -This extension contributes the following settings: - -* `myExtension.enable`: Enable/disable this extension. -* `myExtension.thing`: Set to `blah` to do something. - -## Known Issues - -Calling out known issues can help limit users opening duplicate issues against your extension. - -## Release Notes - -Users appreciate release notes as you update your extension. - -### 1.0.0 - -Initial release of ... - -### 1.0.1 - -Fixed issue #. - -### 1.1.0 - -Added features X, Y, and Z. - ---- - -## Following extension guidelines - -Ensure that you've read through the extensions guidelines and follow the best practices for creating your extension. - -* [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines) - -## Working with Markdown - -You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: - -* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux). -* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux). -* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets. - -## For more information - -* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) -* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) - -**Enjoy!** diff --git a/vscodeEvalExtension/eval-0.0.1.vsix b/vscodeEvalExtension/eval-0.0.1.vsix new file mode 100644 index 0000000000000000000000000000000000000000..334318804ba43d7d85efa440213a113e295d03c1 GIT binary patch literal 60906 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 6" } }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/mocha": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", @@ -260,7 +277,6 @@ "version": "18.19.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.4.tgz", "integrity": "sha512-xNzlUhzoHotIsnFoXmJB+yWmBvFZgKCI9TtPIEdYIMM1KWfwuY8zh7wvc1u1OAXlC7dlf6mZVx/s+Y5KfFz19A==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -1234,6 +1250,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1332,6 +1361,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -1580,6 +1614,17 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -2538,8 +2583,15 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } }, "node_modules/uri-js": { "version": "4.4.1", diff --git a/vscodeEvalExtension/node_modules/@types/fs-extra/LICENSE b/vscodeEvalExtension/node_modules/@types/fs-extra/LICENSE new file mode 100644 index 0000000..9e841e7 --- /dev/null +++ b/vscodeEvalExtension/node_modules/@types/fs-extra/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/vscodeEvalExtension/node_modules/@types/fs-extra/README.md b/vscodeEvalExtension/node_modules/@types/fs-extra/README.md new file mode 100644 index 0000000..49da0d6 --- /dev/null +++ b/vscodeEvalExtension/node_modules/@types/fs-extra/README.md @@ -0,0 +1,15 @@ +# Installation +> `npm install --save @types/fs-extra` + +# Summary +This package contains type definitions for fs-extra (https://github.com/jprichardson/node-fs-extra). + +# Details +Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/fs-extra. + +### Additional Details + * Last updated: Tue, 07 Nov 2023 20:08:00 GMT + * Dependencies: [@types/jsonfile](https://npmjs.com/package/@types/jsonfile), [@types/node](https://npmjs.com/package/@types/node) + +# Credits +These definitions were written by [Alan Agius](https://github.com/alan-agius4), [midknight41](https://github.com/midknight41), [Brendan Forster](https://github.com/shiftkey), [Mees van Dijk](https://github.com/mees-), [Justin Rockwood](https://github.com/jrockwood), [Sang Dang](https://github.com/sangdth), [Florian Keller](https://github.com/ffflorian), [Piotr Błażejewicz](https://github.com/peterblazejewicz), [Tiger Oakes](https://github.com/NotWoods), and [BendingBender](https://github.com/BendingBender). diff --git a/vscodeEvalExtension/node_modules/@types/fs-extra/esm.d.mts b/vscodeEvalExtension/node_modules/@types/fs-extra/esm.d.mts new file mode 100644 index 0000000..d1498ca --- /dev/null +++ b/vscodeEvalExtension/node_modules/@types/fs-extra/esm.d.mts @@ -0,0 +1,111 @@ +import * as fse from "./index.js"; + +export { + copy, + CopyFilterAsync, + CopyFilterSync, + CopyOptions, + CopyOptionsSync, + copySync, + createFile, + createFileSync, + createLink, + createLinkSync, + createSymlink, + createSymlinkSync, + emptyDir, + emptydir, + emptyDirSync, + emptydirSync, + ensureDir, + EnsureDirOptions, + ensureDirSync, + ensureFile, + ensureFileSync, + ensureLink, + ensureLinkSync, + ensureSymlink, + ensureSymlinkSync, + JsonOutputOptions, + JsonReadOptions, + JsonWriteOptions, + mkdirp, + mkdirpSync, + mkdirs, + mkdirsSync, + move, + MoveOptions, + moveSync, + NoParamCallback, + NoParamCallbackWithUndefined, + outputFile, + outputFileSync, + outputJSON, + outputJson, + outputJSONSync, + outputJsonSync, + pathExists, + pathExistsSync, + PathLike, + readJSON, + readJson, + readJSONSync, + readJsonSync, + remove, + removeSync, + SymlinkType, + WriteFileOptions, + writeJSON, + writeJson, + writeJSONSync, + writeJsonSync, +} from "./index.js"; + +declare const fsExtra: { + copy: typeof fse.copy; + copySync: typeof fse.copySync; + emptyDirSync: typeof fse.emptyDirSync; + emptydirSync: typeof fse.emptydirSync; + emptyDir: typeof fse.emptyDir; + emptydir: typeof fse.emptydir; + createFile: typeof fse.createFile; + createFileSync: typeof fse.createFileSync; + ensureFile: typeof fse.ensureFile; + ensureFileSync: typeof fse.ensureFileSync; + createLink: typeof fse.createLink; + createLinkSync: typeof fse.createLinkSync; + ensureLink: typeof fse.ensureLink; + ensureLinkSync: typeof fse.ensureLinkSync; + createSymlink: typeof fse.createSymlink; + createSymlinkSync: typeof fse.createSymlinkSync; + ensureSymlink: typeof fse.ensureSymlink; + ensureSymlinkSync: typeof fse.ensureSymlinkSync; + readJson: typeof fse.readJson; + readJSON: typeof fse.readJSON; + readJsonSync: typeof fse.readJsonSync; + readJSONSync: typeof fse.readJSONSync; + writeJson: typeof fse.writeJson; + writeJSON: typeof fse.writeJSON; + writeJsonSync: typeof fse.writeJsonSync; + writeJSONSync: typeof fse.writeJSONSync; + outputJson: typeof fse.outputJson; + outputJSON: typeof fse.outputJSON; + outputJsonSync: typeof fse.outputJsonSync; + outputJSONSync: typeof fse.outputJSONSync; + mkdirs: typeof fse.mkdirs; + mkdirsSync: typeof fse.mkdirsSync; + mkdirp: typeof fse.mkdirp; + mkdirpSync: typeof fse.mkdirpSync; + ensureDir: typeof fse.ensureDir; + ensureDirSync: typeof fse.ensureDirSync; + move: typeof fse.move; + moveSync: typeof fse.moveSync; + outputFile: typeof fse.outputFile; + outputFileSync: typeof fse.outputFileSync; + pathExists: typeof fse.pathExists; + pathExistsSync: typeof fse.pathExistsSync; + remove: typeof fse.remove; + removeSync: typeof fse.removeSync; +}; + +export default fsExtra; diff --git a/vscodeEvalExtension/node_modules/@types/fs-extra/index.d.ts b/vscodeEvalExtension/node_modules/@types/fs-extra/index.d.ts new file mode 100644 index 0000000..566b75f --- /dev/null +++ b/vscodeEvalExtension/node_modules/@types/fs-extra/index.d.ts @@ -0,0 +1,996 @@ +/// + +import * as fs from "fs"; +import * as jsonfile from "jsonfile"; +import { StringifyOptions } from "jsonfile/utils"; + +export * from "fs"; + +/** + * Copy a file or directory. The directory can have contents. + * + * @param src Note that if `src` is a directory it will copy everything inside of this directory, + * not the entire directory itself (see [issue #537](https://github.com/jprichardson/node-fs-extra/issues/537)). + * @param dest Note that if `src` is a file, `dest` cannot be a directory + * (see [issue #323](https://github.com/jprichardson/node-fs-extra/issues/323)). + * + * @example + * import * as fs from 'fs-extra' + * + * // With a callback: + * fs.copy('/tmp/myfile', '/tmp/mynewfile', err => { + * if (err) return console.error(err) + * console.log('success!') + * }) // copies file + * + * fs.copy('/tmp/mydir', '/tmp/mynewdir', err => { + * if (err) return console.error(err) + * console.log('success!') + * }) // copies directory, even if it has subdirectories or files + * + * // With Promises: + * fs.copy('/tmp/myfile', '/tmp/mynewfile') + * .then(() => { + * console.log('success!') + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * await fs.copy('/tmp/myfile', '/tmp/mynewfile') + * console.log('success!') + * } catch (err) { + * console.error(err) + * } + * } + * + * asyncAwait() + * + * // Using filter function + * fs.copy( + * '/tmp/mydir', + * '/tmp/mynewdir', + * { + * filter(src, dest) { + * // your logic here + * // it will be copied if return true + * } + * }, + * err => { + * if (err) return console.error(err) + * console.log('success!') + * } + * ) + */ +export function copy(src: string, dest: string, options?: CopyOptions): Promise; +export function copy(src: string, dest: string, callback: NoParamCallbackWithUndefined): void; +export function copy(src: string, dest: string, options: CopyOptions, callback: NoParamCallbackWithUndefined): void; +/** + * Copy a file or directory. The directory can have contents. + * + * @param src Note that if `src` is a directory it will copy everything inside of this directory, + * not the entire directory itself (see [issue #537](https://github.com/jprichardson/node-fs-extra/issues/537)). + * @param dest Note that if `src` is a file, `dest` cannot be a directory + * (see [issue #323](https://github.com/jprichardson/node-fs-extra/issues/323)). + * + * @example + * import * as fs from 'fs-extra' + * + * // copy file + * fs.copySync('/tmp/myfile', '/tmp/mynewfile') + * + * // copy directory, even if it has subdirectories or files + * fs.copySync('/tmp/mydir', '/tmp/mynewdir') + * + * // Using filter function + * fs.copySync('/tmp/mydir', '/tmp/mynewdir', { + * filter(src, dest) { + * // your logic here + * // it will be copied if return true + * } + * }) + */ +export function copySync(src: string, dest: string, options?: CopyOptionsSync): void; + +/** + * Moves a file or directory, even across devices. + * + * @param dest Note: When `src` is a file, `dest` must be a file and when `src` is a directory, `dest` must be a directory. + * + * @example + * import * as fs from 'fs-extra' + * + * const src = '/tmp/file.txt' + * const dest = '/tmp/this/path/does/not/exist/file.txt' + * + * // With a callback: + * fs.move(src, dest, err => { + * if (err) return console.error(err) + * console.log('success!') + * }) + * + * // With Promises: + * fs.move(src, dest) + * .then(() => { + * console.log('success!') + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * await fs.move(src, dest) + * console.log('success!') + * } catch (err) { + * console.error(err) + * } + * } + * + * asyncAwait() + * + * // Using `overwrite` option + * fs.move('/tmp/somedir', '/tmp/may/already/exist/somedir', { overwrite: true }, err => { + * if (err) return console.error(err) + * console.log('success!') + * }) + */ +export function move(src: string, dest: string, options?: MoveOptions): Promise; +export function move(src: string, dest: string, callback: NoParamCallbackWithUndefined): void; +export function move(src: string, dest: string, options: MoveOptions, callback: NoParamCallbackWithUndefined): void; +/** + * Moves a file or directory, even across devices. + * + * @param dest Note: When `src` is a file, `dest` must be a file and when `src` is a directory, `dest` must be a directory. + * + * @example + * import * as fs from 'fs-extra' + * + * fs.moveSync('/tmp/somefile', '/tmp/does/not/exist/yet/somefile') + * + * // Using `overwrite` option + * fs.moveSync('/tmp/somedir', '/tmp/may/already/exist/somedir', { overwrite: true }) + */ +export function moveSync(src: string, dest: string, options?: MoveOptions): void; + +/** + * Ensures that the file exists. If the file that is requested to be created is in + * directories that do not exist, these directories are created. If the file already + * exists, it is **NOT MODIFIED**. + * + * @example + * import * as fs from 'fs-extra' + * + * const file = '/tmp/this/path/does/not/exist/file.txt' + * + * // With a callback: + * fs.ensureFile(file, err => { + * console.log(err) // => null + * // file has now been created, including the directory it is to be placed in + * }) + * + * // With Promises: + * fs.ensureFile(file) + * .then(() => { + * console.log('success!') + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * await fs.ensureFile(file) + * console.log('success!') + * } catch (err) { + * console.error(err) + * } + * } + * + * asyncAwait() + */ +export function ensureFile(file: string): Promise; +export function ensureFile(file: string, callback: NoParamCallbackWithUndefined): void; +/** + * @see ensureFile + */ +export const createFile: typeof ensureFile; +/** + * Ensures that the file exists. If the file that is requested to be created is in + * directories that do not exist, these directories are created. If the file already + * exists, it is **NOT MODIFIED**. + * + * @example + * import * as fs from 'fs-extra' + * + * const file = '/tmp/this/path/does/not/exist/file.txt' + * fs.ensureFileSync(file) + * // file has now been created, including the directory it is to be placed in + */ +export function ensureFileSync(file: string): void; +/** + * @see ensureFileSync + */ +export const createFileSync: typeof ensureFileSync; + +/** + * Ensures that the link exists. If the directory structure does not exist, it is created. + * + * @example + * import * as fs from 'fs-extra' + * + * const srcPath = '/tmp/file.txt' + * const destPath = '/tmp/this/path/does/not/exist/file.txt' + * + * // With a callback: + * fs.ensureLink(srcPath, destPath, err => { + * console.log(err) // => null + * // link has now been created, including the directory it is to be placed in + * }) + * + * // With Promises: + * fs.ensureLink(srcPath, destPath) + * .then(() => { + * console.log('success!') + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * await fs.ensureLink(srcPath, destPath) + * console.log('success!') + * } catch (err) { + * console.error(err) + * } + * } + * + * asyncAwait() + */ +export function ensureLink(src: string, dest: string): Promise; +export function ensureLink(src: string, dest: string, callback: fs.NoParamCallback): void; +/** + * @see ensureLink + */ +export const createLink: typeof ensureLink; +/** + * Ensures that the link exists. If the directory structure does not exist, it is created. + * + * @example + * import * as fs from 'fs-extra' + * + * const srcPath = '/tmp/file.txt' + * const destPath = '/tmp/this/path/does/not/exist/file.txt' + * fs.ensureLinkSync(srcPath, destPath) + * // link has now been created, including the directory it is to be placed in + */ +export function ensureLinkSync(src: string, dest: string): void; +/** + * @see ensureLinkSync + */ +export const createLinkSync: typeof ensureLinkSync; + +/** + * Ensures that the symlink exists. If the directory structure does not exist, it is created. + * + * @param type It is only available on Windows and ignored on other platforms. + * + * @example + * import * as fs from 'fs-extra' + * + * const srcPath = '/tmp/file.txt' + * const destPath = '/tmp/this/path/does/not/exist/file.txt' + * + * // With a callback: + * fs.ensureSymlink(srcPath, destPath, err => { + * console.log(err) // => null + * // symlink has now been created, including the directory it is to be placed in + * }) + * + * // With Promises: + * fs.ensureSymlink(srcPath, destPath) + * .then(() => { + * console.log('success!') + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * await fs.ensureSymlink(srcPath, destPath) + * console.log('success!') + * } catch (err) { + * console.error(err) + * } + * } + * + * asyncAwait() + */ +export function ensureSymlink(src: string, dest: string, type?: SymlinkType): Promise; +export function ensureSymlink(src: string, dest: string, callback: fs.NoParamCallback): void; +export function ensureSymlink(src: string, dest: string, type: SymlinkType, callback: fs.NoParamCallback): void; +/** + * @see ensureSymlink + */ +export const createSymlink: typeof ensureSymlink; +/** + * Ensures that the symlink exists. If the directory structure does not exist, it is created. + * + * @param type It is only available on Windows and ignored on other platforms. + * + * @example + * import * as fs from 'fs-extra' + * + * const srcPath = '/tmp/file.txt' + * const destPath = '/tmp/this/path/does/not/exist/file.txt' + * fs.ensureSymlinkSync(srcPath, destPath) + * // symlink has now been created, including the directory it is to be placed in + */ +export function ensureSymlinkSync(src: string, dest: string, type?: SymlinkType): void; +/** + * @see ensureSymlinkSync + */ +export const createSymlinkSync: typeof ensureSymlinkSync; + +/** + * Ensures that the directory exists. If the directory structure does not exist, it is created. + * + * @example + * import * as fs from 'fs-extra' + * + * const dir = '/tmp/this/path/does/not/exist' + * const desiredMode = 0o2775 + * const options = { + * mode: 0o2775 + * } + * + * // With a callback: + * fs.ensureDir(dir, err => { + * console.log(err) // => null + * // dir has now been created, including the directory it is to be placed in + * }) + * + * // With a callback and a mode integer + * fs.ensureDir(dir, desiredMode, err => { + * console.log(err) // => null + * // dir has now been created with mode 0o2775, including the directory it is to be placed in + * }) + * + * // With Promises: + * fs.ensureDir(dir) + * .then(() => { + * console.log('success!') + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With Promises and a mode integer: + * fs.ensureDir(dir, desiredMode) + * .then(() => { + * console.log('success!') + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * await fs.ensureDir(dir) + * console.log('success!') + * } catch (err) { + * console.error(err) + * } + * } + * asyncAwait() + * + * // With async/await and an options object, containing mode: + * async function asyncAwaitMode () { + * try { + * await fs.ensureDir(dir, options) + * console.log('success!') + * } catch (err) { + * console.error(err) + * } + * } + * asyncAwaitMode() + */ +export function ensureDir(path: string, options?: EnsureDirOptions | number): Promise; +export function ensureDir(path: string, callback: fs.NoParamCallback): void; +export function ensureDir(path: string, options: EnsureDirOptions | number, callback: fs.NoParamCallback): void; +/** + * Ensures that the directory exists. If the directory structure does not exist, it is created. + * If provided, options may specify the desired mode for the directory. + * + * @example + * import * as fs from 'fs-extra' + * + * const dir = '/tmp/this/path/does/not/exist' + * + * const desiredMode = 0o2775 + * const options = { + * mode: 0o2775 + * } + * + * fs.ensureDirSync(dir) + * // dir has now been created, including the directory it is to be placed in + * + * fs.ensureDirSync(dir, desiredMode) + * // dir has now been created, including the directory it is to be placed in with permission 0o2775 + * + * fs.ensureDirSync(dir, options) + * // dir has now been created, including the directory it is to be placed in with permission 0o2775 + */ +export function ensureDirSync(path: string, options?: EnsureDirOptions | number): void; + +/** + * @see ensureDir + */ +export const mkdirs: typeof ensureDir; +/** + * @see ensureDirSync + */ +export const mkdirsSync: typeof ensureDirSync; + +/** + * @see ensureDir + */ +export const mkdirp: typeof ensureDir; +/** + * @see ensureDirSync + */ +export const mkdirpSync: typeof ensureDirSync; + +/** + * Almost the same as `writeFile` (i.e. it overwrites), except that if the parent directory + * does not exist, it's created. + * + * @example + * import * as fs from 'fs-extra' + * + * const file = '/tmp/this/path/does/not/exist/file.txt' + * + * // With a callback: + * fs.outputFile(file, 'hello!', err => { + * console.log(err) // => null + * + * fs.readFile(file, 'utf8', (err, data) => { + * if (err) return console.error(err) + * console.log(data) // => hello! + * }) + * }) + * + * // With Promises: + * fs.outputFile(file, 'hello!') + * .then(() => fs.readFile(file, 'utf8')) + * .then(data => { + * console.log(data) // => hello! + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * await fs.outputFile(file, 'hello!') + * + * const data = await fs.readFile(file, 'utf8') + * + * console.log(data) // => hello! + * } catch (err) { + * console.error(err) + * } + * } + * + * asyncAwait() + */ +export function outputFile( + file: string, + data: string | NodeJS.ArrayBufferView, + options?: fs.WriteFileOptions, +): Promise; +export function outputFile(file: string, data: string | NodeJS.ArrayBufferView, callback: fs.NoParamCallback): void; +export function outputFile( + file: string, + data: string | NodeJS.ArrayBufferView, + options: fs.WriteFileOptions, + callback: fs.NoParamCallback, +): void; +/** + * Almost the same as `writeFileSync` (i.e. it overwrites), except that if the parent directory + * does not exist, it's created. + * + * @example + * import * as fs from 'fs-extra' + * + * const file = '/tmp/this/path/does/not/exist/file.txt' + * fs.outputFileSync(file, 'hello!') + * + * const data = fs.readFileSync(file, 'utf8') + * console.log(data) // => hello! + */ +export function outputFileSync( + file: string, + data: string | NodeJS.ArrayBufferView, + options?: fs.WriteFileOptions, +): void; + +/** + * Reads a JSON file and then parses it into an object. + * + * @example + * import * as fs from 'fs-extra' + * + * // With a callback: + * fs.readJson('./package.json', (err, packageObj) => { + * if (err) console.error(err) + * console.log(packageObj.version) // => 0.1.3 + * }) + * + * // With Promises: + * fs.readJson('./package.json') + * .then(packageObj => { + * console.log(packageObj.version) // => 0.1.3 + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * const packageObj = await fs.readJson('./package.json') + * console.log(packageObj.version) // => 0.1.3 + * } catch (err) { + * console.error(err) + * } + * } + * + * asyncAwait() + * + * // `readJsonSync()` can take a `throws` option set to `false` and it won't throw if the JSON is invalid. Example: + * const file = '/tmp/some-invalid.json' + * const data = '{not valid JSON' + * fs.writeFileSync(file, data) + * + * // With a callback: + * fs.readJson(file, { throws: false }, (err, obj) => { + * if (err) console.error(err) + * console.log(obj) // => null + * }) + * + * // With Promises: + * fs.readJson(file, { throws: false }) + * .then(obj => { + * console.log(obj) // => null + * }) + * .catch(err => { + * console.error(err) // Not called + * }) + * + * // With async/await: + * async function asyncAwaitThrows () { + * const obj = await fs.readJson(file, { throws: false }) + * console.log(obj) // => null + * } + * + * asyncAwaitThrows() + */ +export const readJson: typeof jsonfile.readFile; +/** + * @see readJson + */ +export const readJSON: typeof jsonfile.readFile; +/** + * Reads a JSON file and then parses it into an object. + * + * @example + * import * as fs from 'fs-extra' + * + * const packageObj = fs.readJsonSync('./package.json') + * console.log(packageObj.version) // => 2.0.0 + * + * // `readJsonSync()` can take a `throws` option set to `false` and it won't throw if the JSON is invalid. Example: + * const file = '/tmp/some-invalid.json' + * const data = '{not valid JSON' + * fs.writeFileSync(file, data) + * + * const obj = fs.readJsonSync(file, { throws: false }) + * console.log(obj) // => null + */ +export const readJsonSync: typeof jsonfile.readFileSync; +/** + * @see readJsonSync + */ +export const readJSONSync: typeof jsonfile.readFileSync; + +/** + * Writes an object to a JSON file. + * + * @example + * import * as fs from 'fs-extra' + * + * // With a callback: + * fs.writeJson('./package.json', {name: 'fs-extra'}, err => { + * if (err) return console.error(err) + * console.log('success!') + * }) + * + * // With Promises: + * fs.writeJson('./package.json', {name: 'fs-extra'}) + * .then(() => { + * console.log('success!') + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * await fs.writeJson('./package.json', {name: 'fs-extra'}) + * console.log('success!') + * } catch (err) { + * console.error(err) + * } + * } + * + * asyncAwait() + */ +export const writeJson: typeof jsonfile.writeFile; +/** + * @see writeJson + */ +export const writeJSON: typeof jsonfile.writeFile; +/** + * Writes an object to a JSON file. + * + * @example + * import * as fs from 'fs-extra' + * + * fs.writeJsonSync('./package.json', {name: 'fs-extra'}) + */ +export const writeJsonSync: typeof jsonfile.writeFileSync; +/** + * @see writeJsonSync + */ +export const writeJSONSync: typeof jsonfile.writeFileSync; + +/** + * Almost the same as `writeJson`, except that if the directory does not exist, it's created. + * + * @example + * import * as fs from 'fs-extra' + * + * const file = '/tmp/this/path/does/not/exist/file.json' + * + * // With a callback: + * fs.outputJson(file, {name: 'JP'}, err => { + * console.log(err) // => null + * + * fs.readJson(file, (err, data) => { + * if (err) return console.error(err) + * console.log(data.name) // => JP + * }) + * }) + * + * // With Promises: + * fs.outputJson(file, {name: 'JP'}) + * .then(() => fs.readJson(file)) + * .then(data => { + * console.log(data.name) // => JP + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * await fs.outputJson(file, {name: 'JP'}) + * + * const data = await fs.readJson(file) + * + * console.log(data.name) // => JP + * } catch (err) { + * console.error(err) + * } + * } + * + * asyncAwait() + */ +export function outputJson(file: string, data: any, options?: JsonOutputOptions): Promise; +export function outputJson(file: string, data: any, options: JsonOutputOptions, callback: fs.NoParamCallback): void; +export function outputJson(file: string, data: any, callback: fs.NoParamCallback): void; +/** + * @see outputJson + */ +export const outputJSON: typeof outputJson; +/** + * Almost the same as `writeJsonSync`, except that if the directory does not exist, it's created. + * + * @example + * import * as fs from 'fs-extra' + * + * const file = '/tmp/this/path/does/not/exist/file.json' + * fs.outputJsonSync(file, {name: 'JP'}) + * + * const data = fs.readJsonSync(file) + * console.log(data.name) // => JP + */ +export function outputJsonSync(file: string, data: any, options?: JsonOutputOptions): void; +/** + * @see outputJsonSync + */ +export const outputJSONSync: typeof outputJsonSync; + +/** + * Removes a file or directory. The directory can have contents. If the path does not exist, silently does nothing. + * + * @example + * import * as fs from 'fs-extra' + * + * // remove file + * // With a callback: + * fs.remove('/tmp/myfile', err => { + * if (err) return console.error(err) + * console.log('success!') + * }) + * + * fs.remove('/home/jprichardson', err => { + * if (err) return console.error(err) + * console.log('success!') // I just deleted my entire HOME directory. + * }) + * + * // With Promises: + * fs.remove('/tmp/myfile') + * .then(() => { + * console.log('success!') + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * await fs.remove('/tmp/myfile') + * console.log('success!') + * } catch (err) { + * console.error(err) + * } + * } + * + * asyncAwait() + */ +export function remove(dir: string): Promise; +export function remove(dir: string, callback: fs.NoParamCallback): void; +/** + * Removes a file or directory. The directory can have contents. If the path does not exist, silently does nothing. + * + * @example + * import * as fs from 'fs-extra' + * + * // remove file + * fs.removeSync('/tmp/myfile') + * + * fs.removeSync('/home/jprichardson') // I just deleted my entire HOME directory. + */ +export function removeSync(dir: string): void; + +/** + * Ensures that a directory is empty. Deletes directory contents if the directory is not empty. + * If the directory does not exist, it is created. The directory itself is not deleted. + * + * @example + * import * as fs from 'fs-extra' + * + * // assume this directory has a lot of files and folders + * // With a callback: + * fs.emptyDir('/tmp/some/dir', err => { + * if (err) return console.error(err) + * console.log('success!') + * }) + * + * // With Promises: + * fs.emptyDir('/tmp/some/dir') + * .then(() => { + * console.log('success!') + * }) + * .catch(err => { + * console.error(err) + * }) + * + * // With async/await: + * async function asyncAwait () { + * try { + * await fs.emptyDir('/tmp/some/dir') + * console.log('success!') + * } catch (err) { + * console.error(err) + * } + * } + * + * asyncAwait() + */ +export function emptyDir(path: string): Promise; +export function emptyDir(path: string, callback: fs.NoParamCallback): void; +/** + * @see emptyDir + */ +export const emptydir: typeof emptyDir; +/** + * Ensures that a directory is empty. Deletes directory contents if the directory is not empty. + * If the directory does not exist, it is created. The directory itself is not deleted. + * + * @example + * import * as fs from 'fs-extra' + * + * // assume this directory has a lot of files and folders + * fs.emptyDirSync('/tmp/some/dir') + */ +export function emptyDirSync(path: string): void; +/** + * @see emptyDirSync + */ +export const emptydirSync: typeof emptyDirSync; + +/** + * Test whether or not the given path exists by checking with the file system. Like + * [`fs.exists`](https://nodejs.org/api/fs.html#fs_fs_exists_path_callback), but with a normal + * callback signature (err, exists). Uses `fs.access` under the hood. + * + * @example + * import * as fs from 'fs-extra' + * + * const file = '/tmp/this/path/does/not/exist/file.txt' + * + * // With a callback: + * fs.pathExists(file, (err, exists) => { + * console.log(err) // => null + * console.log(exists) // => false + * }) + * + * // Promise usage: + * fs.pathExists(file) + * .then(exists => console.log(exists)) // => false + * + * // With async/await: + * async function asyncAwait () { + * const exists = await fs.pathExists(file) + * + * console.log(exists) // => false + * } + * + * asyncAwait() + */ +export function pathExists(path: string): Promise; +export function pathExists(path: string, callback: (err: NodeJS.ErrnoException | null, exists: boolean) => void): void; +/** + * An alias for [`fs.existsSync`](https://nodejs.org/api/fs.html#fs_fs_existssync_path), created for + * consistency with `pathExists`. + */ +export function pathExistsSync(path: string): boolean; + +export const access: typeof fs.access.__promisify__ & typeof fs.access; +export const appendFile: typeof fs.appendFile.__promisify__ & typeof fs.appendFile; +export const chmod: typeof fs.chmod.__promisify__ & typeof fs.chmod; +export const chown: typeof fs.chown.__promisify__ & typeof fs.chown; +export const close: typeof fs.close.__promisify__ & typeof fs.close; +export const copyFile: typeof fs.copyFile.__promisify__ & typeof fs.copyFile; +export const exists: typeof fs.exists.__promisify__ & typeof fs.exists; +export const fchmod: typeof fs.fchmod.__promisify__ & typeof fs.fchmod; +export const fchown: typeof fs.fchown.__promisify__ & typeof fs.fchown; +export const fdatasync: typeof fs.fdatasync.__promisify__ & typeof fs.fdatasync; +export const fstat: typeof fs.fstat.__promisify__ & typeof fs.fstat; +export const fsync: typeof fs.fsync.__promisify__ & typeof fs.fsync; +export const ftruncate: typeof fs.ftruncate.__promisify__ & typeof fs.ftruncate; +export const futimes: typeof fs.futimes.__promisify__ & typeof fs.futimes; +export const lchmod: typeof fs.lchmod.__promisify__ & typeof fs.lchmod; +export const lchown: typeof fs.lchown.__promisify__ & typeof fs.lchown; +export const link: typeof fs.link.__promisify__ & typeof fs.link; +export const lstat: typeof fs.lstat.__promisify__ & typeof fs.lstat; +export const mkdir: typeof fs.mkdir.__promisify__ & typeof fs.mkdir; +export const mkdtemp: typeof fs.mkdtemp.__promisify__ & typeof fs.mkdtemp; +export const open: typeof fs.open.__promisify__ & typeof fs.open; +export const opendir: typeof fs.opendir.__promisify__ & typeof fs.opendir; +export const read: typeof fs.read.__promisify__ & typeof fs.read; +export const readv: typeof fs.readv.__promisify__ & typeof fs.readv; +export const readdir: typeof fs.readdir.__promisify__ & typeof fs.readdir; +export const readFile: typeof fs.readFile.__promisify__ & typeof fs.readFile; +export const readlink: typeof fs.readlink.__promisify__ & typeof fs.readlink; +export const realpath: + & typeof fs.realpath.__promisify__ + & typeof fs.realpath + & { + native(path: fs.PathLike, options?: fs.EncodingOption): Promise; + native(path: fs.PathLike, options: fs.BufferEncodingOption): Promise; + }; +export const rename: typeof fs.rename.__promisify__ & typeof fs.rename; +export const rm: typeof fs.rm.__promisify__ & typeof fs.rm; +export const rmdir: typeof fs.rmdir.__promisify__ & typeof fs.rmdir; +export const stat: typeof fs.stat.__promisify__ & typeof fs.stat; +export const symlink: typeof fs.symlink.__promisify__ & typeof fs.symlink; +export const truncate: typeof fs.truncate.__promisify__ & typeof fs.truncate; +export const unlink: typeof fs.unlink.__promisify__ & typeof fs.unlink; +export const utimes: typeof fs.utimes.__promisify__ & typeof fs.utimes; +export const write: typeof fs.write.__promisify__ & typeof fs.write; +export const writev: typeof fs.writev.__promisify__ & typeof fs.writev; +export const writeFile: typeof fs.writeFile.__promisify__ & typeof fs.writeFile; + +export type NoParamCallbackWithUndefined = (err: NodeJS.ErrnoException | null | undefined) => void; + +export type SymlinkType = fs.symlink.Type; + +export type CopyFilterSync = (src: string, dest: string) => boolean; +export type CopyFilterAsync = (src: string, dest: string) => Promise; + +export interface CopyOptions { + /** + * Dereference symlinks. + * @default false + */ + dereference?: boolean | undefined; + /** + * Overwrite existing file or directory. + * _Note that the copy operation will silently fail if you set this to `false` and the destination exists._ + * Use the `errorOnExist` option to change this behavior. + * @default true + */ + overwrite?: boolean | undefined; + /** + * When `true`, will set last modification and access times to the ones of the original source files. + * When `false`, timestamp behavior is OS-dependent. + * @default false + */ + preserveTimestamps?: boolean | undefined; + /** + * When `overwrite` is `false` and the destination exists, throw an error. + * @default false + */ + errorOnExist?: boolean | undefined; + /** + * Function to filter copied files/directories. Return `true` to copy the item, `false` to ignore it. + * Can also return a `Promise` that resolves to `true` or `false` (or pass in an `async` function). + */ + filter?: CopyFilterSync | CopyFilterAsync | undefined; +} + +export interface CopyOptionsSync extends CopyOptions { + /** + * Function to filter copied files/directories. Return `true` to copy the item, `false` to ignore it. + */ + filter?: CopyFilterSync | undefined; +} + +export interface EnsureDirOptions { + mode?: number | undefined; +} + +export interface MoveOptions { + /** + * Overwrite existing file or directory. + * @default false + */ + overwrite?: boolean | undefined; + /** + * Dereference symlinks. + * @default false + */ + dereference?: boolean | undefined; +} + +export { JFReadOptions as JsonReadOptions, JFWriteOptions as JsonWriteOptions } from "jsonfile"; + +export type JsonOutputOptions = fs.WriteFileOptions & StringifyOptions; diff --git a/vscodeEvalExtension/node_modules/@types/fs-extra/package.json b/vscodeEvalExtension/node_modules/@types/fs-extra/package.json new file mode 100644 index 0000000..37c6682 --- /dev/null +++ b/vscodeEvalExtension/node_modules/@types/fs-extra/package.json @@ -0,0 +1,84 @@ +{ + "name": "@types/fs-extra", + "version": "11.0.4", + "description": "TypeScript definitions for fs-extra", + "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/fs-extra", + "license": "MIT", + "contributors": [ + { + "name": "Alan Agius", + "githubUsername": "alan-agius4", + "url": "https://github.com/alan-agius4" + }, + { + "name": "midknight41", + "githubUsername": "midknight41", + "url": "https://github.com/midknight41" + }, + { + "name": "Brendan Forster", + "githubUsername": "shiftkey", + "url": "https://github.com/shiftkey" + }, + { + "name": "Mees van Dijk", + "githubUsername": "mees-", + "url": "https://github.com/mees-" + }, + { + "name": "Justin Rockwood", + "githubUsername": "jrockwood", + "url": "https://github.com/jrockwood" + }, + { + "name": "Sang Dang", + "githubUsername": "sangdth", + "url": "https://github.com/sangdth" + }, + { + "name": "Florian Keller", + "githubUsername": "ffflorian", + "url": "https://github.com/ffflorian" + }, + { + "name": "Piotr Błażejewicz", + "githubUsername": "peterblazejewicz", + "url": "https://github.com/peterblazejewicz" + }, + { + "name": "Tiger Oakes", + "githubUsername": "NotWoods", + "url": "https://github.com/NotWoods" + }, + { + "name": "BendingBender", + "githubUsername": "BendingBender", + "url": "https://github.com/BendingBender" + } + ], + "main": "", + "types": "index.d.ts", + "exports": { + ".": { + "types": "./index.d.ts" + }, + "./esm": { + "types": { + "import": "./esm.d.mts" + } + }, + "./package.json": "./package.json" + }, + "repository": { + "type": "git", + "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git", + "directory": "types/fs-extra" + }, + "scripts": {}, + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + }, + "typesPublisherContentHash": "2929b595f5fdba90096984c89127b1a93f583ee50680a2ad02fad15b1f571bb0", + "typeScriptVersion": "4.5" +} \ No newline at end of file diff --git a/vscodeEvalExtension/node_modules/@types/jsonfile/LICENSE b/vscodeEvalExtension/node_modules/@types/jsonfile/LICENSE new file mode 100644 index 0000000..9e841e7 --- /dev/null +++ b/vscodeEvalExtension/node_modules/@types/jsonfile/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/vscodeEvalExtension/node_modules/@types/jsonfile/README.md b/vscodeEvalExtension/node_modules/@types/jsonfile/README.md new file mode 100644 index 0000000..a29966b --- /dev/null +++ b/vscodeEvalExtension/node_modules/@types/jsonfile/README.md @@ -0,0 +1,15 @@ +# Installation +> `npm install --save @types/jsonfile` + +# Summary +This package contains type definitions for jsonfile (https://github.com/jprichardson/node-jsonfile#readme). + +# Details +Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/jsonfile. + +### Additional Details + * Last updated: Tue, 07 Nov 2023 03:09:37 GMT + * Dependencies: [@types/node](https://npmjs.com/package/@types/node) + +# Credits +These definitions were written by [Daniel Bowring](https://github.com/dbowring), [BendingBender](https://github.com/BendingBender), and [Piotr Błażejewicz](https://github.com/peterblazejewicz). diff --git a/vscodeEvalExtension/node_modules/@types/jsonfile/index.d.ts b/vscodeEvalExtension/node_modules/@types/jsonfile/index.d.ts new file mode 100644 index 0000000..775db97 --- /dev/null +++ b/vscodeEvalExtension/node_modules/@types/jsonfile/index.d.ts @@ -0,0 +1,71 @@ +/// + +import { + PathLike, + readFile as fsReadFile, + readFileSync as fsReadFileSync, + writeFile as fsWriteFile, + writeFileSync as fsWriteFileSync, +} from "fs"; +import { Url } from "url"; + +export type Path = PathLike | Url; + +export interface FS { + readFile: typeof fsReadFile; + readFileSync: typeof fsReadFileSync; + writeFile: typeof fsWriteFile; + writeFileSync: typeof fsWriteFileSync; +} + +export type JFReadOptions = + | { + encoding?: string | null | undefined; + flag?: string | undefined; + throws?: boolean | undefined; + fs?: FS | undefined; + reviver?: ((key: any, value: any) => any) | undefined; + } + | string + | null + | undefined; + +export type JFWriteOptions = + | { + encoding?: string | null | undefined; + mode?: string | number | undefined; + flag?: string | undefined; + fs?: FS | undefined; + EOL?: string | undefined; + spaces?: string | number | undefined; + replacer?: ((key: string, value: any) => any) | undefined; + } + | string + | null; + +export type ReadCallback = (err: NodeJS.ErrnoException | null, data: any) => void; +export type WriteCallback = (err: NodeJS.ErrnoException | null) => void; + +/** + * @see {@link https://github.com/jprichardson/node-jsonfile#readfilefilename-options-callback} + */ +export function readFile(file: Path, options: JFReadOptions, callback: ReadCallback): void; +export function readFile(file: Path, callback: ReadCallback): void; +export function readFile(file: Path, options?: JFReadOptions): Promise; + +/** + * @see {@link https://github.com/jprichardson/node-jsonfile#readfilesyncfilename-options} + */ +export function readFileSync(file: Path, options?: JFReadOptions): any; + +/** + * @see {@link https://github.com/jprichardson/node-jsonfile#writefilefilename-obj-options-callback} + */ +export function writeFile(file: Path, obj: any, options: JFWriteOptions, callback: WriteCallback): void; +export function writeFile(file: Path, obj: any, callback: WriteCallback): void; +export function writeFile(file: Path, obj: any, options?: JFWriteOptions): Promise; + +/** + * @see {@link https://github.com/jprichardson/node-jsonfile#writefilesyncfilename-obj-options} + */ +export function writeFileSync(file: Path, obj: any, options?: JFWriteOptions): void; diff --git a/vscodeEvalExtension/node_modules/@types/jsonfile/package.json b/vscodeEvalExtension/node_modules/@types/jsonfile/package.json new file mode 100644 index 0000000..c91d42c --- /dev/null +++ b/vscodeEvalExtension/node_modules/@types/jsonfile/package.json @@ -0,0 +1,37 @@ +{ + "name": "@types/jsonfile", + "version": "6.1.4", + "description": "TypeScript definitions for jsonfile", + "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/jsonfile", + "license": "MIT", + "contributors": [ + { + "name": "Daniel Bowring", + "githubUsername": "dbowring", + "url": "https://github.com/dbowring" + }, + { + "name": "BendingBender", + "githubUsername": "BendingBender", + "url": "https://github.com/BendingBender" + }, + { + "name": "Piotr Błażejewicz", + "githubUsername": "peterblazejewicz", + "url": "https://github.com/peterblazejewicz" + } + ], + "main": "", + "types": "index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git", + "directory": "types/jsonfile" + }, + "scripts": {}, + "dependencies": { + "@types/node": "*" + }, + "typesPublisherContentHash": "c4c437c24ccd22e0fd74368adceefc3c6ed726b74d1cc5188deeb5b0119b9523", + "typeScriptVersion": "4.5" +} \ No newline at end of file diff --git a/vscodeEvalExtension/node_modules/@types/jsonfile/utils.d.ts b/vscodeEvalExtension/node_modules/@types/jsonfile/utils.d.ts new file mode 100644 index 0000000..901b43b --- /dev/null +++ b/vscodeEvalExtension/node_modules/@types/jsonfile/utils.d.ts @@ -0,0 +1,9 @@ +export function stringify(obj: any, options?: StringifyOptions): string; +export function stripBom(content: string): string; + +export interface StringifyOptions { + EOL?: string | undefined; + finalEOL?: boolean | undefined; + replacer?: ((key: string, value: any) => any) | undefined; + spaces?: string | number | undefined; +} diff --git a/vscodeEvalExtension/node_modules/fs-extra/LICENSE b/vscodeEvalExtension/node_modules/fs-extra/LICENSE new file mode 100644 index 0000000..93546df --- /dev/null +++ b/vscodeEvalExtension/node_modules/fs-extra/LICENSE @@ -0,0 +1,15 @@ +(The MIT License) + +Copyright (c) 2011-2017 JP Richardson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vscodeEvalExtension/node_modules/fs-extra/README.md b/vscodeEvalExtension/node_modules/fs-extra/README.md new file mode 100644 index 0000000..245de66 --- /dev/null +++ b/vscodeEvalExtension/node_modules/fs-extra/README.md @@ -0,0 +1,292 @@ +Node.js: fs-extra +================= + +`fs-extra` adds file system methods that aren't included in the native `fs` module and adds promise support to the `fs` methods. It also uses [`graceful-fs`](https://github.com/isaacs/node-graceful-fs) to prevent `EMFILE` errors. It should be a drop in replacement for `fs`. + +[![npm Package](https://img.shields.io/npm/v/fs-extra.svg)](https://www.npmjs.org/package/fs-extra) +[![License](https://img.shields.io/npm/l/fs-extra.svg)](https://github.com/jprichardson/node-fs-extra/blob/master/LICENSE) +[![build status](https://img.shields.io/github/actions/workflow/status/jprichardson/node-fs-extra/ci.yml?branch=master)](https://github.com/jprichardson/node-fs-extra/actions/workflows/ci.yml?query=branch%3Amaster) +[![downloads per month](http://img.shields.io/npm/dm/fs-extra.svg)](https://www.npmjs.org/package/fs-extra) +[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) + +Why? +---- + +I got tired of including `mkdirp`, `rimraf`, and `ncp` in most of my projects. + + + + +Installation +------------ + + npm install fs-extra + + + +Usage +----- + +### CommonJS + +`fs-extra` is a drop in replacement for native `fs`. All methods in `fs` are attached to `fs-extra`. All `fs` methods return promises if the callback isn't passed. + +You don't ever need to include the original `fs` module again: + +```js +const fs = require('fs') // this is no longer necessary +``` + +you can now do this: + +```js +const fs = require('fs-extra') +``` + +or if you prefer to make it clear that you're using `fs-extra` and not `fs`, you may want +to name your `fs` variable `fse` like so: + +```js +const fse = require('fs-extra') +``` + +you can also keep both, but it's redundant: + +```js +const fs = require('fs') +const fse = require('fs-extra') +``` + +### ESM + +There is also an `fs-extra/esm` import, that supports both default and named exports. However, note that `fs` methods are not included in `fs-extra/esm`; you still need to import `fs` and/or `fs/promises` seperately: + +```js +import { readFileSync } from 'fs' +import { readFile } from 'fs/promises' +import { outputFile, outputFileSync } from 'fs-extra/esm' +``` + +Default exports are supported: + +```js +import fs from 'fs' +import fse from 'fs-extra/esm' +// fse.readFileSync is not a function; must use fs.readFileSync +``` + +but you probably want to just use regular `fs-extra` instead of `fs-extra/esm` for default exports: + +```js +import fs from 'fs-extra' +// both fs and fs-extra methods are defined +``` + +Sync vs Async vs Async/Await +------------- +Most methods are async by default. All async methods will return a promise if the callback isn't passed. + +Sync methods on the other hand will throw if an error occurs. + +Also Async/Await will throw an error if one occurs. + +Example: + +```js +const fs = require('fs-extra') + +// Async with promises: +fs.copy('/tmp/myfile', '/tmp/mynewfile') + .then(() => console.log('success!')) + .catch(err => console.error(err)) + +// Async with callbacks: +fs.copy('/tmp/myfile', '/tmp/mynewfile', err => { + if (err) return console.error(err) + console.log('success!') +}) + +// Sync: +try { + fs.copySync('/tmp/myfile', '/tmp/mynewfile') + console.log('success!') +} catch (err) { + console.error(err) +} + +// Async/Await: +async function copyFiles () { + try { + await fs.copy('/tmp/myfile', '/tmp/mynewfile') + console.log('success!') + } catch (err) { + console.error(err) + } +} + +copyFiles() +``` + + +Methods +------- + +### Async + +- [copy](docs/copy.md) +- [emptyDir](docs/emptyDir.md) +- [ensureFile](docs/ensureFile.md) +- [ensureDir](docs/ensureDir.md) +- [ensureLink](docs/ensureLink.md) +- [ensureSymlink](docs/ensureSymlink.md) +- [mkdirp](docs/ensureDir.md) +- [mkdirs](docs/ensureDir.md) +- [move](docs/move.md) +- [outputFile](docs/outputFile.md) +- [outputJson](docs/outputJson.md) +- [pathExists](docs/pathExists.md) +- [readJson](docs/readJson.md) +- [remove](docs/remove.md) +- [writeJson](docs/writeJson.md) + +### Sync + +- [copySync](docs/copy-sync.md) +- [emptyDirSync](docs/emptyDir-sync.md) +- [ensureFileSync](docs/ensureFile-sync.md) +- [ensureDirSync](docs/ensureDir-sync.md) +- [ensureLinkSync](docs/ensureLink-sync.md) +- [ensureSymlinkSync](docs/ensureSymlink-sync.md) +- [mkdirpSync](docs/ensureDir-sync.md) +- [mkdirsSync](docs/ensureDir-sync.md) +- [moveSync](docs/move-sync.md) +- [outputFileSync](docs/outputFile-sync.md) +- [outputJsonSync](docs/outputJson-sync.md) +- [pathExistsSync](docs/pathExists-sync.md) +- [readJsonSync](docs/readJson-sync.md) +- [removeSync](docs/remove-sync.md) +- [writeJsonSync](docs/writeJson-sync.md) + + +**NOTE:** You can still use the native Node.js methods. They are promisified and copied over to `fs-extra`. See [notes on `fs.read()`, `fs.write()`, & `fs.writev()`](docs/fs-read-write-writev.md) + +### What happened to `walk()` and `walkSync()`? + +They were removed from `fs-extra` in v2.0.0. If you need the functionality, `walk` and `walkSync` are available as separate packages, [`klaw`](https://github.com/jprichardson/node-klaw) and [`klaw-sync`](https://github.com/manidlou/node-klaw-sync). + + +Third Party +----------- + +### CLI + +[fse-cli](https://www.npmjs.com/package/@atao60/fse-cli) allows you to run `fs-extra` from a console or from [npm](https://www.npmjs.com) scripts. + +### TypeScript + +If you like TypeScript, you can use `fs-extra` with it: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/fs-extra + + +### File / Directory Watching + +If you want to watch for changes to files or directories, then you should use [chokidar](https://github.com/paulmillr/chokidar). + +### Obtain Filesystem (Devices, Partitions) Information + +[fs-filesystem](https://github.com/arthurintelligence/node-fs-filesystem) allows you to read the state of the filesystem of the host on which it is run. It returns information about both the devices and the partitions (volumes) of the system. + +### Misc. + +- [fs-extra-debug](https://github.com/jdxcode/fs-extra-debug) - Send your fs-extra calls to [debug](https://npmjs.org/package/debug). +- [mfs](https://github.com/cadorn/mfs) - Monitor your fs-extra calls. + + + +Hacking on fs-extra +------------------- + +Wanna hack on `fs-extra`? Great! Your help is needed! [fs-extra is one of the most depended upon Node.js packages](http://nodei.co/npm/fs-extra.png?downloads=true&downloadRank=true&stars=true). This project +uses [JavaScript Standard Style](https://github.com/feross/standard) - if the name or style choices bother you, +you're gonna have to get over it :) If `standard` is good enough for `npm`, it's good enough for `fs-extra`. + +[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) + +What's needed? +- First, take a look at existing issues. Those are probably going to be where the priority lies. +- More tests for edge cases. Specifically on different platforms. There can never be enough tests. +- Improve test coverage. + +Note: If you make any big changes, **you should definitely file an issue for discussion first.** + +### Running the Test Suite + +fs-extra contains hundreds of tests. + +- `npm run lint`: runs the linter ([standard](http://standardjs.com/)) +- `npm run unit`: runs the unit tests +- `npm run unit-esm`: runs tests for `fs-extra/esm` exports +- `npm test`: runs the linter and all tests + +When running unit tests, set the environment variable `CROSS_DEVICE_PATH` to the absolute path of an empty directory on another device (like a thumb drive) to enable cross-device move tests. + + +### Windows + +If you run the tests on the Windows and receive a lot of symbolic link `EPERM` permission errors, it's +because on Windows you need elevated privilege to create symbolic links. You can add this to your Windows's +account by following the instructions here: http://superuser.com/questions/104845/permission-to-make-symbolic-links-in-windows-7 +However, I didn't have much luck doing this. + +Since I develop on Mac OS X, I use VMWare Fusion for Windows testing. I create a shared folder that I map to a drive on Windows. +I open the `Node.js command prompt` and run as `Administrator`. I then map the network drive running the following command: + + net use z: "\\vmware-host\Shared Folders" + +I can then navigate to my `fs-extra` directory and run the tests. + + +Naming +------ + +I put a lot of thought into the naming of these functions. Inspired by @coolaj86's request. So he deserves much of the credit for raising the issue. See discussion(s) here: + +* https://github.com/jprichardson/node-fs-extra/issues/2 +* https://github.com/flatiron/utile/issues/11 +* https://github.com/ryanmcgrath/wrench-js/issues/29 +* https://github.com/substack/node-mkdirp/issues/17 + +First, I believe that in as many cases as possible, the [Node.js naming schemes](http://nodejs.org/api/fs.html) should be chosen. However, there are problems with the Node.js own naming schemes. + +For example, `fs.readFile()` and `fs.readdir()`: the **F** is capitalized in *File* and the **d** is not capitalized in *dir*. Perhaps a bit pedantic, but they should still be consistent. Also, Node.js has chosen a lot of POSIX naming schemes, which I believe is great. See: `fs.mkdir()`, `fs.rmdir()`, `fs.chown()`, etc. + +We have a dilemma though. How do you consistently name methods that perform the following POSIX commands: `cp`, `cp -r`, `mkdir -p`, and `rm -rf`? + +My perspective: when in doubt, err on the side of simplicity. A directory is just a hierarchical grouping of directories and files. Consider that for a moment. So when you want to copy it or remove it, in most cases you'll want to copy or remove all of its contents. When you want to create a directory, if the directory that it's suppose to be contained in does not exist, then in most cases you'll want to create that too. + +So, if you want to remove a file or a directory regardless of whether it has contents, just call `fs.remove(path)`. If you want to copy a file or a directory whether it has contents, just call `fs.copy(source, destination)`. If you want to create a directory regardless of whether its parent directories exist, just call `fs.mkdirs(path)` or `fs.mkdirp(path)`. + + +Credit +------ + +`fs-extra` wouldn't be possible without using the modules from the following authors: + +- [Isaac Shlueter](https://github.com/isaacs) +- [Charlie McConnel](https://github.com/avianflu) +- [James Halliday](https://github.com/substack) +- [Andrew Kelley](https://github.com/andrewrk) + + + + +License +------- + +Licensed under MIT + +Copyright (c) 2011-2017 [JP Richardson](https://github.com/jprichardson) + +[1]: http://nodejs.org/docs/latest/api/fs.html + + +[jsonfile]: https://github.com/jprichardson/node-jsonfile diff --git a/vscodeEvalExtension/node_modules/fs-extra/package.json b/vscodeEvalExtension/node_modules/fs-extra/package.json new file mode 100644 index 0000000..f3f6ba3 --- /dev/null +++ b/vscodeEvalExtension/node_modules/fs-extra/package.json @@ -0,0 +1,71 @@ +{ + "name": "fs-extra", + "version": "11.2.0", + "description": "fs-extra contains methods that aren't included in the vanilla Node.js fs package. Such as recursive mkdir, copy, and remove.", + "engines": { + "node": ">=14.14" + }, + "homepage": "https://github.com/jprichardson/node-fs-extra", + "repository": { + "type": "git", + "url": "https://github.com/jprichardson/node-fs-extra" + }, + "keywords": [ + "fs", + "file", + "file system", + "copy", + "directory", + "extra", + "mkdirp", + "mkdir", + "mkdirs", + "recursive", + "json", + "read", + "write", + "extra", + "delete", + "remove", + "touch", + "create", + "text", + "output", + "move", + "promise" + ], + "author": "JP Richardson ", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "devDependencies": { + "klaw": "^2.1.1", + "klaw-sync": "^3.0.2", + "minimist": "^1.1.1", + "mocha": "^10.1.0", + "nyc": "^15.0.0", + "proxyquire": "^2.0.1", + "read-dir-files": "^0.1.1", + "standard": "^17.0.0" + }, + "main": "./lib/index.js", + "exports": { + ".": "./lib/index.js", + "./esm": "./lib/esm.mjs" + }, + "files": [ + "lib/", + "!lib/**/__tests__/" + ], + "scripts": { + "lint": "standard", + "test-find": "find ./lib/**/__tests__ -name *.test.js | xargs mocha", + "test": "npm run lint && npm run unit && npm run unit-esm", + "unit": "nyc node test.js", + "unit-esm": "node test.mjs" + }, + "sideEffects": false +} diff --git a/vscodeEvalExtension/node_modules/graceful-fs/LICENSE b/vscodeEvalExtension/node_modules/graceful-fs/LICENSE new file mode 100644 index 0000000..e906a25 --- /dev/null +++ b/vscodeEvalExtension/node_modules/graceful-fs/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vscodeEvalExtension/node_modules/graceful-fs/README.md b/vscodeEvalExtension/node_modules/graceful-fs/README.md new file mode 100644 index 0000000..82d6e4d --- /dev/null +++ b/vscodeEvalExtension/node_modules/graceful-fs/README.md @@ -0,0 +1,143 @@ +# graceful-fs + +graceful-fs functions as a drop-in replacement for the fs module, +making various improvements. + +The improvements are meant to normalize behavior across different +platforms and environments, and to make filesystem access more +resilient to errors. + +## Improvements over [fs module](https://nodejs.org/api/fs.html) + +* Queues up `open` and `readdir` calls, and retries them once + something closes if there is an EMFILE error from too many file + descriptors. +* fixes `lchmod` for Node versions prior to 0.6.2. +* implements `fs.lutimes` if possible. Otherwise it becomes a noop. +* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or + `lchown` if the user isn't root. +* makes `lchmod` and `lchown` become noops, if not available. +* retries reading a file if `read` results in EAGAIN error. + +On Windows, it retries renaming a file for up to one second if `EACCESS` +or `EPERM` error occurs, likely because antivirus software has locked +the directory. + +## USAGE + +```javascript +// use just like fs +var fs = require('graceful-fs') + +// now go and do stuff with it... +fs.readFile('some-file-or-whatever', (err, data) => { + // Do stuff here. +}) +``` + +## Sync methods + +This module cannot intercept or handle `EMFILE` or `ENFILE` errors from sync +methods. If you use sync methods which open file descriptors then you are +responsible for dealing with any errors. + +This is a known limitation, not a bug. + +## Global Patching + +If you want to patch the global fs module (or any other fs-like +module) you can do this: + +```javascript +// Make sure to read the caveat below. +var realFs = require('fs') +var gracefulFs = require('graceful-fs') +gracefulFs.gracefulify(realFs) +``` + +This should only ever be done at the top-level application layer, in +order to delay on EMFILE errors from any fs-using dependencies. You +should **not** do this in a library, because it can cause unexpected +delays in other parts of the program. + +## Changes + +This module is fairly stable at this point, and used by a lot of +things. That being said, because it implements a subtle behavior +change in a core part of the node API, even modest changes can be +extremely breaking, and the versioning is thus biased towards +bumping the major when in doubt. + +The main change between major versions has been switching between +providing a fully-patched `fs` module vs monkey-patching the node core +builtin, and the approach by which a non-monkey-patched `fs` was +created. + +The goal is to trade `EMFILE` errors for slower fs operations. So, if +you try to open a zillion files, rather than crashing, `open` +operations will be queued up and wait for something else to `close`. + +There are advantages to each approach. Monkey-patching the fs means +that no `EMFILE` errors can possibly occur anywhere in your +application, because everything is using the same core `fs` module, +which is patched. However, it can also obviously cause undesirable +side-effects, especially if the module is loaded multiple times. + +Implementing a separate-but-identical patched `fs` module is more +surgical (and doesn't run the risk of patching multiple times), but +also imposes the challenge of keeping in sync with the core module. + +The current approach loads the `fs` module, and then creates a +lookalike object that has all the same methods, except a few that are +patched. It is safe to use in all versions of Node from 0.8 through +7.0. + +### v4 + +* Do not monkey-patch the fs module. This module may now be used as a + drop-in dep, and users can opt into monkey-patching the fs builtin + if their app requires it. + +### v3 + +* Monkey-patch fs, because the eval approach no longer works on recent + node. +* fixed possible type-error throw if rename fails on windows +* verify that we *never* get EMFILE errors +* Ignore ENOSYS from chmod/chown +* clarify that graceful-fs must be used as a drop-in + +### v2.1.0 + +* Use eval rather than monkey-patching fs. +* readdir: Always sort the results +* win32: requeue a file if error has an OK status + +### v2.0 + +* A return to monkey patching +* wrap process.cwd + +### v1.1 + +* wrap readFile +* Wrap fs.writeFile. +* readdir protection +* Don't clobber the fs builtin +* Handle fs.read EAGAIN errors by trying again +* Expose the curOpen counter +* No-op lchown/lchmod if not implemented +* fs.rename patch only for win32 +* Patch fs.rename to handle AV software on Windows +* Close #4 Chown should not fail on einval or eperm if non-root +* Fix isaacs/fstream#1 Only wrap fs one time +* Fix #3 Start at 1024 max files, then back off on EMFILE +* lutimes that doens't blow up on Linux +* A full on-rewrite using a queue instead of just swallowing the EMFILE error +* Wrap Read/Write streams as well + +### 1.0 + +* Update engines for node 0.6 +* Be lstat-graceful on Windows +* first diff --git a/vscodeEvalExtension/node_modules/graceful-fs/clone.js b/vscodeEvalExtension/node_modules/graceful-fs/clone.js new file mode 100644 index 0000000..dff3cc8 --- /dev/null +++ b/vscodeEvalExtension/node_modules/graceful-fs/clone.js @@ -0,0 +1,23 @@ +'use strict' + +module.exports = clone + +var getPrototypeOf = Object.getPrototypeOf || function (obj) { + return obj.__proto__ +} + +function clone (obj) { + if (obj === null || typeof obj !== 'object') + return obj + + if (obj instanceof Object) + var copy = { __proto__: getPrototypeOf(obj) } + else + var copy = Object.create(null) + + Object.getOwnPropertyNames(obj).forEach(function (key) { + Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key)) + }) + + return copy +} diff --git a/vscodeEvalExtension/node_modules/graceful-fs/graceful-fs.js b/vscodeEvalExtension/node_modules/graceful-fs/graceful-fs.js new file mode 100644 index 0000000..8d5b89e --- /dev/null +++ b/vscodeEvalExtension/node_modules/graceful-fs/graceful-fs.js @@ -0,0 +1,448 @@ +var fs = require('fs') +var polyfills = require('./polyfills.js') +var legacy = require('./legacy-streams.js') +var clone = require('./clone.js') + +var util = require('util') + +/* istanbul ignore next - node 0.x polyfill */ +var gracefulQueue +var previousSymbol + +/* istanbul ignore else - node 0.x polyfill */ +if (typeof Symbol === 'function' && typeof Symbol.for === 'function') { + gracefulQueue = Symbol.for('graceful-fs.queue') + // This is used in testing by future versions + previousSymbol = Symbol.for('graceful-fs.previous') +} else { + gracefulQueue = '___graceful-fs.queue' + previousSymbol = '___graceful-fs.previous' +} + +function noop () {} + +function publishQueue(context, queue) { + Object.defineProperty(context, gracefulQueue, { + get: function() { + return queue + } + }) +} + +var debug = noop +if (util.debuglog) + debug = util.debuglog('gfs4') +else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) + debug = function() { + var m = util.format.apply(util, arguments) + m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ') + console.error(m) + } + +// Once time initialization +if (!fs[gracefulQueue]) { + // This queue can be shared by multiple loaded instances + var queue = global[gracefulQueue] || [] + publishQueue(fs, queue) + + // Patch fs.close/closeSync to shared queue version, because we need + // to retry() whenever a close happens *anywhere* in the program. + // This is essential when multiple graceful-fs instances are + // in play at the same time. + fs.close = (function (fs$close) { + function close (fd, cb) { + return fs$close.call(fs, fd, function (err) { + // This function uses the graceful-fs shared queue + if (!err) { + resetQueue() + } + + if (typeof cb === 'function') + cb.apply(this, arguments) + }) + } + + Object.defineProperty(close, previousSymbol, { + value: fs$close + }) + return close + })(fs.close) + + fs.closeSync = (function (fs$closeSync) { + function closeSync (fd) { + // This function uses the graceful-fs shared queue + fs$closeSync.apply(fs, arguments) + resetQueue() + } + + Object.defineProperty(closeSync, previousSymbol, { + value: fs$closeSync + }) + return closeSync + })(fs.closeSync) + + if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) { + process.on('exit', function() { + debug(fs[gracefulQueue]) + require('assert').equal(fs[gracefulQueue].length, 0) + }) + } +} + +if (!global[gracefulQueue]) { + publishQueue(global, fs[gracefulQueue]); +} + +module.exports = patch(clone(fs)) +if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) { + module.exports = patch(fs) + fs.__patched = true; +} + +function patch (fs) { + // Everything that references the open() function needs to be in here + polyfills(fs) + fs.gracefulify = patch + + fs.createReadStream = createReadStream + fs.createWriteStream = createWriteStream + var fs$readFile = fs.readFile + fs.readFile = readFile + function readFile (path, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$readFile(path, options, cb) + + function go$readFile (path, options, cb, startTime) { + return fs$readFile(path, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$readFile, [path, options, cb], err, startTime || Date.now(), Date.now()]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + } + }) + } + } + + var fs$writeFile = fs.writeFile + fs.writeFile = writeFile + function writeFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$writeFile(path, data, options, cb) + + function go$writeFile (path, data, options, cb, startTime) { + return fs$writeFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$writeFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + } + }) + } + } + + var fs$appendFile = fs.appendFile + if (fs$appendFile) + fs.appendFile = appendFile + function appendFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$appendFile(path, data, options, cb) + + function go$appendFile (path, data, options, cb, startTime) { + return fs$appendFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$appendFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + } + }) + } + } + + var fs$copyFile = fs.copyFile + if (fs$copyFile) + fs.copyFile = copyFile + function copyFile (src, dest, flags, cb) { + if (typeof flags === 'function') { + cb = flags + flags = 0 + } + return go$copyFile(src, dest, flags, cb) + + function go$copyFile (src, dest, flags, cb, startTime) { + return fs$copyFile(src, dest, flags, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$copyFile, [src, dest, flags, cb], err, startTime || Date.now(), Date.now()]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + } + }) + } + } + + var fs$readdir = fs.readdir + fs.readdir = readdir + var noReaddirOptionVersions = /^v[0-5]\./ + function readdir (path, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + var go$readdir = noReaddirOptionVersions.test(process.version) + ? function go$readdir (path, options, cb, startTime) { + return fs$readdir(path, fs$readdirCallback( + path, options, cb, startTime + )) + } + : function go$readdir (path, options, cb, startTime) { + return fs$readdir(path, options, fs$readdirCallback( + path, options, cb, startTime + )) + } + + return go$readdir(path, options, cb) + + function fs$readdirCallback (path, options, cb, startTime) { + return function (err, files) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([ + go$readdir, + [path, options, cb], + err, + startTime || Date.now(), + Date.now() + ]) + else { + if (files && files.sort) + files.sort() + + if (typeof cb === 'function') + cb.call(this, err, files) + } + } + } + } + + if (process.version.substr(0, 4) === 'v0.8') { + var legStreams = legacy(fs) + ReadStream = legStreams.ReadStream + WriteStream = legStreams.WriteStream + } + + var fs$ReadStream = fs.ReadStream + if (fs$ReadStream) { + ReadStream.prototype = Object.create(fs$ReadStream.prototype) + ReadStream.prototype.open = ReadStream$open + } + + var fs$WriteStream = fs.WriteStream + if (fs$WriteStream) { + WriteStream.prototype = Object.create(fs$WriteStream.prototype) + WriteStream.prototype.open = WriteStream$open + } + + Object.defineProperty(fs, 'ReadStream', { + get: function () { + return ReadStream + }, + set: function (val) { + ReadStream = val + }, + enumerable: true, + configurable: true + }) + Object.defineProperty(fs, 'WriteStream', { + get: function () { + return WriteStream + }, + set: function (val) { + WriteStream = val + }, + enumerable: true, + configurable: true + }) + + // legacy names + var FileReadStream = ReadStream + Object.defineProperty(fs, 'FileReadStream', { + get: function () { + return FileReadStream + }, + set: function (val) { + FileReadStream = val + }, + enumerable: true, + configurable: true + }) + var FileWriteStream = WriteStream + Object.defineProperty(fs, 'FileWriteStream', { + get: function () { + return FileWriteStream + }, + set: function (val) { + FileWriteStream = val + }, + enumerable: true, + configurable: true + }) + + function ReadStream (path, options) { + if (this instanceof ReadStream) + return fs$ReadStream.apply(this, arguments), this + else + return ReadStream.apply(Object.create(ReadStream.prototype), arguments) + } + + function ReadStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + if (that.autoClose) + that.destroy() + + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + that.read() + } + }) + } + + function WriteStream (path, options) { + if (this instanceof WriteStream) + return fs$WriteStream.apply(this, arguments), this + else + return WriteStream.apply(Object.create(WriteStream.prototype), arguments) + } + + function WriteStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + that.destroy() + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + } + }) + } + + function createReadStream (path, options) { + return new fs.ReadStream(path, options) + } + + function createWriteStream (path, options) { + return new fs.WriteStream(path, options) + } + + var fs$open = fs.open + fs.open = open + function open (path, flags, mode, cb) { + if (typeof mode === 'function') + cb = mode, mode = null + + return go$open(path, flags, mode, cb) + + function go$open (path, flags, mode, cb, startTime) { + return fs$open(path, flags, mode, function (err, fd) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$open, [path, flags, mode, cb], err, startTime || Date.now(), Date.now()]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + } + }) + } + } + + return fs +} + +function enqueue (elem) { + debug('ENQUEUE', elem[0].name, elem[1]) + fs[gracefulQueue].push(elem) + retry() +} + +// keep track of the timeout between retry() calls +var retryTimer + +// reset the startTime and lastTime to now +// this resets the start of the 60 second overall timeout as well as the +// delay between attempts so that we'll retry these jobs sooner +function resetQueue () { + var now = Date.now() + for (var i = 0; i < fs[gracefulQueue].length; ++i) { + // entries that are only a length of 2 are from an older version, don't + // bother modifying those since they'll be retried anyway. + if (fs[gracefulQueue][i].length > 2) { + fs[gracefulQueue][i][3] = now // startTime + fs[gracefulQueue][i][4] = now // lastTime + } + } + // call retry to make sure we're actively processing the queue + retry() +} + +function retry () { + // clear the timer and remove it to help prevent unintended concurrency + clearTimeout(retryTimer) + retryTimer = undefined + + if (fs[gracefulQueue].length === 0) + return + + var elem = fs[gracefulQueue].shift() + var fn = elem[0] + var args = elem[1] + // these items may be unset if they were added by an older graceful-fs + var err = elem[2] + var startTime = elem[3] + var lastTime = elem[4] + + // if we don't have a startTime we have no way of knowing if we've waited + // long enough, so go ahead and retry this item now + if (startTime === undefined) { + debug('RETRY', fn.name, args) + fn.apply(null, args) + } else if (Date.now() - startTime >= 60000) { + // it's been more than 60 seconds total, bail now + debug('TIMEOUT', fn.name, args) + var cb = args.pop() + if (typeof cb === 'function') + cb.call(null, err) + } else { + // the amount of time between the last attempt and right now + var sinceAttempt = Date.now() - lastTime + // the amount of time between when we first tried, and when we last tried + // rounded up to at least 1 + var sinceStart = Math.max(lastTime - startTime, 1) + // backoff. wait longer than the total time we've been retrying, but only + // up to a maximum of 100ms + var desiredDelay = Math.min(sinceStart * 1.2, 100) + // it's been long enough since the last retry, do it again + if (sinceAttempt >= desiredDelay) { + debug('RETRY', fn.name, args) + fn.apply(null, args.concat([startTime])) + } else { + // if we can't do this job yet, push it to the end of the queue + // and let the next iteration check again + fs[gracefulQueue].push(elem) + } + } + + // schedule our next run if one isn't already scheduled + if (retryTimer === undefined) { + retryTimer = setTimeout(retry, 0) + } +} diff --git a/vscodeEvalExtension/node_modules/graceful-fs/legacy-streams.js b/vscodeEvalExtension/node_modules/graceful-fs/legacy-streams.js new file mode 100644 index 0000000..d617b50 --- /dev/null +++ b/vscodeEvalExtension/node_modules/graceful-fs/legacy-streams.js @@ -0,0 +1,118 @@ +var Stream = require('stream').Stream + +module.exports = legacy + +function legacy (fs) { + return { + ReadStream: ReadStream, + WriteStream: WriteStream + } + + function ReadStream (path, options) { + if (!(this instanceof ReadStream)) return new ReadStream(path, options); + + Stream.call(this); + + var self = this; + + this.path = path; + this.fd = null; + this.readable = true; + this.paused = false; + + this.flags = 'r'; + this.mode = 438; /*=0666*/ + this.bufferSize = 64 * 1024; + + options = options || {}; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } + + if (this.encoding) this.setEncoding(this.encoding); + + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.end === undefined) { + this.end = Infinity; + } else if ('number' !== typeof this.end) { + throw TypeError('end must be a Number'); + } + + if (this.start > this.end) { + throw new Error('start must be <= end'); + } + + this.pos = this.start; + } + + if (this.fd !== null) { + process.nextTick(function() { + self._read(); + }); + return; + } + + fs.open(this.path, this.flags, this.mode, function (err, fd) { + if (err) { + self.emit('error', err); + self.readable = false; + return; + } + + self.fd = fd; + self.emit('open', fd); + self._read(); + }) + } + + function WriteStream (path, options) { + if (!(this instanceof WriteStream)) return new WriteStream(path, options); + + Stream.call(this); + + this.path = path; + this.fd = null; + this.writable = true; + + this.flags = 'w'; + this.encoding = 'binary'; + this.mode = 438; /*=0666*/ + this.bytesWritten = 0; + + options = options || {}; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } + + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.start < 0) { + throw new Error('start must be >= zero'); + } + + this.pos = this.start; + } + + this.busy = false; + this._queue = []; + + if (this.fd === null) { + this._open = fs.open; + this._queue.push([this._open, this.path, this.flags, this.mode, undefined]); + this.flush(); + } + } +} diff --git a/vscodeEvalExtension/node_modules/graceful-fs/package.json b/vscodeEvalExtension/node_modules/graceful-fs/package.json new file mode 100644 index 0000000..87babf0 --- /dev/null +++ b/vscodeEvalExtension/node_modules/graceful-fs/package.json @@ -0,0 +1,53 @@ +{ + "name": "graceful-fs", + "description": "A drop-in replacement for fs, making various improvements.", + "version": "4.2.11", + "repository": { + "type": "git", + "url": "https://github.com/isaacs/node-graceful-fs" + }, + "main": "graceful-fs.js", + "directories": { + "test": "test" + }, + "scripts": { + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --follow-tags", + "test": "nyc --silent node test.js | tap -c -", + "posttest": "nyc report" + }, + "keywords": [ + "fs", + "module", + "reading", + "retry", + "retries", + "queue", + "error", + "errors", + "handling", + "EMFILE", + "EAGAIN", + "EINVAL", + "EPERM", + "EACCESS" + ], + "license": "ISC", + "devDependencies": { + "import-fresh": "^2.0.0", + "mkdirp": "^0.5.0", + "rimraf": "^2.2.8", + "tap": "^16.3.4" + }, + "files": [ + "fs.js", + "graceful-fs.js", + "legacy-streams.js", + "polyfills.js", + "clone.js" + ], + "tap": { + "reporter": "classic" + } +} diff --git a/vscodeEvalExtension/node_modules/graceful-fs/polyfills.js b/vscodeEvalExtension/node_modules/graceful-fs/polyfills.js new file mode 100644 index 0000000..453f1a9 --- /dev/null +++ b/vscodeEvalExtension/node_modules/graceful-fs/polyfills.js @@ -0,0 +1,355 @@ +var constants = require('constants') + +var origCwd = process.cwd +var cwd = null + +var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform + +process.cwd = function() { + if (!cwd) + cwd = origCwd.call(process) + return cwd +} +try { + process.cwd() +} catch (er) {} + +// This check is needed until node.js 12 is required +if (typeof process.chdir === 'function') { + var chdir = process.chdir + process.chdir = function (d) { + cwd = null + chdir.call(process, d) + } + if (Object.setPrototypeOf) Object.setPrototypeOf(process.chdir, chdir) +} + +module.exports = patch + +function patch (fs) { + // (re-)implement some things that are known busted or missing. + + // lchmod, broken prior to 0.6.2 + // back-port the fix here. + if (constants.hasOwnProperty('O_SYMLINK') && + process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { + patchLchmod(fs) + } + + // lutimes implementation, or no-op + if (!fs.lutimes) { + patchLutimes(fs) + } + + // https://github.com/isaacs/node-graceful-fs/issues/4 + // Chown should not fail on einval or eperm if non-root. + // It should not fail on enosys ever, as this just indicates + // that a fs doesn't support the intended operation. + + fs.chown = chownFix(fs.chown) + fs.fchown = chownFix(fs.fchown) + fs.lchown = chownFix(fs.lchown) + + fs.chmod = chmodFix(fs.chmod) + fs.fchmod = chmodFix(fs.fchmod) + fs.lchmod = chmodFix(fs.lchmod) + + fs.chownSync = chownFixSync(fs.chownSync) + fs.fchownSync = chownFixSync(fs.fchownSync) + fs.lchownSync = chownFixSync(fs.lchownSync) + + fs.chmodSync = chmodFixSync(fs.chmodSync) + fs.fchmodSync = chmodFixSync(fs.fchmodSync) + fs.lchmodSync = chmodFixSync(fs.lchmodSync) + + fs.stat = statFix(fs.stat) + fs.fstat = statFix(fs.fstat) + fs.lstat = statFix(fs.lstat) + + fs.statSync = statFixSync(fs.statSync) + fs.fstatSync = statFixSync(fs.fstatSync) + fs.lstatSync = statFixSync(fs.lstatSync) + + // if lchmod/lchown do not exist, then make them no-ops + if (fs.chmod && !fs.lchmod) { + fs.lchmod = function (path, mode, cb) { + if (cb) process.nextTick(cb) + } + fs.lchmodSync = function () {} + } + if (fs.chown && !fs.lchown) { + fs.lchown = function (path, uid, gid, cb) { + if (cb) process.nextTick(cb) + } + fs.lchownSync = function () {} + } + + // on Windows, A/V software can lock the directory, causing this + // to fail with an EACCES or EPERM if the directory contains newly + // created files. Try again on failure, for up to 60 seconds. + + // Set the timeout this long because some Windows Anti-Virus, such as Parity + // bit9, may lock files for up to a minute, causing npm package install + // failures. Also, take care to yield the scheduler. Windows scheduling gives + // CPU to a busy looping process, which can cause the program causing the lock + // contention to be starved of CPU by node, so the contention doesn't resolve. + if (platform === "win32") { + fs.rename = typeof fs.rename !== 'function' ? fs.rename + : (function (fs$rename) { + function rename (from, to, cb) { + var start = Date.now() + var backoff = 0; + fs$rename(from, to, function CB (er) { + if (er + && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY") + && Date.now() - start < 60000) { + setTimeout(function() { + fs.stat(to, function (stater, st) { + if (stater && stater.code === "ENOENT") + fs$rename(from, to, CB); + else + cb(er) + }) + }, backoff) + if (backoff < 100) + backoff += 10; + return; + } + if (cb) cb(er) + }) + } + if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename) + return rename + })(fs.rename) + } + + // if read() returns EAGAIN, then just try it again. + fs.read = typeof fs.read !== 'function' ? fs.read + : (function (fs$read) { + function read (fd, buffer, offset, length, position, callback_) { + var callback + if (callback_ && typeof callback_ === 'function') { + var eagCounter = 0 + callback = function (er, _, __) { + if (er && er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + } + callback_.apply(this, arguments) + } + } + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + } + + // This ensures `util.promisify` works as it does for native `fs.read`. + if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read) + return read + })(fs.read) + + fs.readSync = typeof fs.readSync !== 'function' ? fs.readSync + : (function (fs$readSync) { return function (fd, buffer, offset, length, position) { + var eagCounter = 0 + while (true) { + try { + return fs$readSync.call(fs, fd, buffer, offset, length, position) + } catch (er) { + if (er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + continue + } + throw er + } + } + }})(fs.readSync) + + function patchLchmod (fs) { + fs.lchmod = function (path, mode, callback) { + fs.open( path + , constants.O_WRONLY | constants.O_SYMLINK + , mode + , function (err, fd) { + if (err) { + if (callback) callback(err) + return + } + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + fs.fchmod(fd, mode, function (err) { + fs.close(fd, function(err2) { + if (callback) callback(err || err2) + }) + }) + }) + } + + fs.lchmodSync = function (path, mode) { + var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode) + + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + var threw = true + var ret + try { + ret = fs.fchmodSync(fd, mode) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } + } + + function patchLutimes (fs) { + if (constants.hasOwnProperty("O_SYMLINK") && fs.futimes) { + fs.lutimes = function (path, at, mt, cb) { + fs.open(path, constants.O_SYMLINK, function (er, fd) { + if (er) { + if (cb) cb(er) + return + } + fs.futimes(fd, at, mt, function (er) { + fs.close(fd, function (er2) { + if (cb) cb(er || er2) + }) + }) + }) + } + + fs.lutimesSync = function (path, at, mt) { + var fd = fs.openSync(path, constants.O_SYMLINK) + var ret + var threw = true + try { + ret = fs.futimesSync(fd, at, mt) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } + + } else if (fs.futimes) { + fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) } + fs.lutimesSync = function () {} + } + } + + function chmodFix (orig) { + if (!orig) return orig + return function (target, mode, cb) { + return orig.call(fs, target, mode, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } + } + + function chmodFixSync (orig) { + if (!orig) return orig + return function (target, mode) { + try { + return orig.call(fs, target, mode) + } catch (er) { + if (!chownErOk(er)) throw er + } + } + } + + + function chownFix (orig) { + if (!orig) return orig + return function (target, uid, gid, cb) { + return orig.call(fs, target, uid, gid, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } + } + + function chownFixSync (orig) { + if (!orig) return orig + return function (target, uid, gid) { + try { + return orig.call(fs, target, uid, gid) + } catch (er) { + if (!chownErOk(er)) throw er + } + } + } + + function statFix (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target, options, cb) { + if (typeof options === 'function') { + cb = options + options = null + } + function callback (er, stats) { + if (stats) { + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + } + if (cb) cb.apply(this, arguments) + } + return options ? orig.call(fs, target, options, callback) + : orig.call(fs, target, callback) + } + } + + function statFixSync (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target, options) { + var stats = options ? orig.call(fs, target, options) + : orig.call(fs, target) + if (stats) { + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + } + return stats; + } + } + + // ENOSYS means that the fs doesn't support the op. Just ignore + // that, because it doesn't matter. + // + // if there's no getuid, or if getuid() is something other + // than 0, and the error is EINVAL or EPERM, then just ignore + // it. + // + // This specific case is a silent failure in cp, install, tar, + // and most other unix tools that manage permissions. + // + // When running as root, or if other types of errors are + // encountered, then it's strict. + function chownErOk (er) { + if (!er) + return true + + if (er.code === "ENOSYS") + return true + + var nonroot = !process.getuid || process.getuid() !== 0 + if (nonroot) { + if (er.code === "EINVAL" || er.code === "EPERM") + return true + } + + return false + } +} diff --git a/vscodeEvalExtension/node_modules/jsonfile/CHANGELOG.md b/vscodeEvalExtension/node_modules/jsonfile/CHANGELOG.md new file mode 100644 index 0000000..d772e43 --- /dev/null +++ b/vscodeEvalExtension/node_modules/jsonfile/CHANGELOG.md @@ -0,0 +1,171 @@ +6.1.0 / 2020-10-31 +------------------ + +- Add `finalEOL` option to disable writing final EOL ([#115](https://github.com/jprichardson/node-jsonfile/issues/115), [#137](https://github.com/jprichardson/node-jsonfile/pull/137)) +- Update dependency ([#138](https://github.com/jprichardson/node-jsonfile/pull/138)) + +6.0.1 / 2020-03-07 +------------------ + +- Update dependency ([#130](https://github.com/jprichardson/node-jsonfile/pull/130)) +- Fix code style ([#129](https://github.com/jprichardson/node-jsonfile/pull/129)) + +6.0.0 / 2020-02-24 +------------------ + +- **BREAKING:** Drop support for Node 6 & 8 ([#128](https://github.com/jprichardson/node-jsonfile/pull/128)) +- **BREAKING:** Do not allow passing `null` as options to `readFile()` or `writeFile()` ([#128](https://github.com/jprichardson/node-jsonfile/pull/128)) +- Refactor internals ([#128](https://github.com/jprichardson/node-jsonfile/pull/128)) + +5.0.0 / 2018-09-08 +------------------ + +- **BREAKING:** Drop Node 4 support +- **BREAKING:** If no callback is passed to an asynchronous method, a promise is now returned ([#109](https://github.com/jprichardson/node-jsonfile/pull/109)) +- Cleanup docs + +4.0.0 / 2017-07-12 +------------------ + +- **BREAKING:** Remove global `spaces` option. +- **BREAKING:** Drop support for Node 0.10, 0.12, and io.js. +- Remove undocumented `passParsingErrors` option. +- Added `EOL` override option to `writeFile` when using `spaces`. [#89] + +3.0.1 / 2017-07-05 +------------------ + +- Fixed bug in `writeFile` when there was a serialization error & no callback was passed. In previous versions, an empty file would be written; now no file is written. + +3.0.0 / 2017-04-25 +------------------ + +- Changed behavior of `throws` option for `readFileSync`; now does not throw filesystem errors when `throws` is `false` + +2.4.0 / 2016-09-15 +------------------ +### Changed +- added optional support for `graceful-fs` [#62] + +2.3.1 / 2016-05-13 +------------------ +- fix to support BOM. [#45][#45] + +2.3.0 / 2016-04-16 +------------------ +- add `throws` to `readFile()`. See [#39][#39] +- add support for any arbitrary `fs` module. Useful with [mock-fs](https://www.npmjs.com/package/mock-fs) + +2.2.3 / 2015-10-14 +------------------ +- include file name in parse error. See: https://github.com/jprichardson/node-jsonfile/pull/34 + +2.2.2 / 2015-09-16 +------------------ +- split out tests into separate files +- fixed `throws` when set to `true` in `readFileSync()`. See: https://github.com/jprichardson/node-jsonfile/pull/33 + +2.2.1 / 2015-06-25 +------------------ +- fixed regression when passing in string as encoding for options in `writeFile()` and `writeFileSync()`. See: https://github.com/jprichardson/node-jsonfile/issues/28 + +2.2.0 / 2015-06-25 +------------------ +- added `options.spaces` to `writeFile()` and `writeFileSync()` + +2.1.2 / 2015-06-22 +------------------ +- fixed if passed `readFileSync(file, 'utf8')`. See: https://github.com/jprichardson/node-jsonfile/issues/25 + +2.1.1 / 2015-06-19 +------------------ +- fixed regressions if `null` is passed for options. See: https://github.com/jprichardson/node-jsonfile/issues/24 + +2.1.0 / 2015-06-19 +------------------ +- cleanup: JavaScript Standard Style, rename files, dropped terst for assert +- methods now support JSON revivers/replacers + +2.0.1 / 2015-05-24 +------------------ +- update license attribute https://github.com/jprichardson/node-jsonfile/pull/21 + +2.0.0 / 2014-07-28 +------------------ +* added `\n` to end of file on write. [#14](https://github.com/jprichardson/node-jsonfile/pull/14) +* added `options.throws` to `readFileSync()` +* dropped support for Node v0.8 + +1.2.0 / 2014-06-29 +------------------ +* removed semicolons +* bugfix: passed `options` to `fs.readFile` and `fs.readFileSync`. This technically changes behavior, but +changes it according to docs. [#12][#12] + +1.1.1 / 2013-11-11 +------------------ +* fixed catching of callback bug (ffissore / #5) + +1.1.0 / 2013-10-11 +------------------ +* added `options` param to methods, (seanodell / #4) + +1.0.1 / 2013-09-05 +------------------ +* removed `homepage` field from package.json to remove NPM warning + +1.0.0 / 2013-06-28 +------------------ +* added `.npmignore`, #1 +* changed spacing default from `4` to `2` to follow Node conventions + +0.0.1 / 2012-09-10 +------------------ +* Initial release. + +[#89]: https://github.com/jprichardson/node-jsonfile/pull/89 +[#45]: https://github.com/jprichardson/node-jsonfile/issues/45 "Reading of UTF8-encoded (w/ BOM) files fails" +[#44]: https://github.com/jprichardson/node-jsonfile/issues/44 "Extra characters in written file" +[#43]: https://github.com/jprichardson/node-jsonfile/issues/43 "Prettyfy json when written to file" +[#42]: https://github.com/jprichardson/node-jsonfile/pull/42 "Moved fs.readFileSync within the try/catch" +[#41]: https://github.com/jprichardson/node-jsonfile/issues/41 "Linux: Hidden file not working" +[#40]: https://github.com/jprichardson/node-jsonfile/issues/40 "autocreate folder doesn't work from Path-value" +[#39]: https://github.com/jprichardson/node-jsonfile/pull/39 "Add `throws` option for readFile (async)" +[#38]: https://github.com/jprichardson/node-jsonfile/pull/38 "Update README.md writeFile[Sync] signature" +[#37]: https://github.com/jprichardson/node-jsonfile/pull/37 "support append file" +[#36]: https://github.com/jprichardson/node-jsonfile/pull/36 "Add typescript definition file." +[#35]: https://github.com/jprichardson/node-jsonfile/pull/35 "Add typescript definition file." +[#34]: https://github.com/jprichardson/node-jsonfile/pull/34 "readFile JSON parse error includes filename" +[#33]: https://github.com/jprichardson/node-jsonfile/pull/33 "fix throw->throws typo in readFileSync()" +[#32]: https://github.com/jprichardson/node-jsonfile/issues/32 "readFile & readFileSync can possible have strip-comments as an option?" +[#31]: https://github.com/jprichardson/node-jsonfile/pull/31 "[Modify] Support string include is unicode escape string" +[#30]: https://github.com/jprichardson/node-jsonfile/issues/30 "How to use Jsonfile package in Meteor.js App?" +[#29]: https://github.com/jprichardson/node-jsonfile/issues/29 "writefile callback if no error?" +[#28]: https://github.com/jprichardson/node-jsonfile/issues/28 "writeFile options argument broken " +[#27]: https://github.com/jprichardson/node-jsonfile/pull/27 "Use svg instead of png to get better image quality" +[#26]: https://github.com/jprichardson/node-jsonfile/issues/26 "Breaking change to fs-extra" +[#25]: https://github.com/jprichardson/node-jsonfile/issues/25 "support string encoding param for read methods" +[#24]: https://github.com/jprichardson/node-jsonfile/issues/24 "readFile: Passing in null options with a callback throws an error" +[#23]: https://github.com/jprichardson/node-jsonfile/pull/23 "Add appendFile and appendFileSync" +[#22]: https://github.com/jprichardson/node-jsonfile/issues/22 "Default value for spaces in readme.md is outdated" +[#21]: https://github.com/jprichardson/node-jsonfile/pull/21 "Update license attribute" +[#20]: https://github.com/jprichardson/node-jsonfile/issues/20 "Add simple caching functionallity" +[#19]: https://github.com/jprichardson/node-jsonfile/pull/19 "Add appendFileSync method" +[#18]: https://github.com/jprichardson/node-jsonfile/issues/18 "Add updateFile and updateFileSync methods" +[#17]: https://github.com/jprichardson/node-jsonfile/issues/17 "seem read & write sync has sequentially problem" +[#16]: https://github.com/jprichardson/node-jsonfile/pull/16 "export spaces defaulted to null" +[#15]: https://github.com/jprichardson/node-jsonfile/issues/15 "`jsonfile.spaces` should default to `null`" +[#14]: https://github.com/jprichardson/node-jsonfile/pull/14 "Add EOL at EOF" +[#13]: https://github.com/jprichardson/node-jsonfile/issues/13 "Add a final newline" +[#12]: https://github.com/jprichardson/node-jsonfile/issues/12 "readFile doesn't accept options" +[#11]: https://github.com/jprichardson/node-jsonfile/pull/11 "Added try,catch to readFileSync" +[#10]: https://github.com/jprichardson/node-jsonfile/issues/10 "No output or error from writeFile" +[#9]: https://github.com/jprichardson/node-jsonfile/pull/9 "Change 'js' to 'jf' in example." +[#8]: https://github.com/jprichardson/node-jsonfile/pull/8 "Updated forgotten module.exports to me." +[#7]: https://github.com/jprichardson/node-jsonfile/pull/7 "Add file name in error message" +[#6]: https://github.com/jprichardson/node-jsonfile/pull/6 "Use graceful-fs when possible" +[#5]: https://github.com/jprichardson/node-jsonfile/pull/5 "Jsonfile doesn't behave nicely when used inside a test suite." +[#4]: https://github.com/jprichardson/node-jsonfile/pull/4 "Added options parameter to writeFile and writeFileSync" +[#3]: https://github.com/jprichardson/node-jsonfile/issues/3 "test2" +[#2]: https://github.com/jprichardson/node-jsonfile/issues/2 "homepage field must be a string url. Deleted." +[#1]: https://github.com/jprichardson/node-jsonfile/pull/1 "adding an `.npmignore` file" diff --git a/vscodeEvalExtension/node_modules/jsonfile/LICENSE b/vscodeEvalExtension/node_modules/jsonfile/LICENSE new file mode 100644 index 0000000..cb7e807 --- /dev/null +++ b/vscodeEvalExtension/node_modules/jsonfile/LICENSE @@ -0,0 +1,15 @@ +(The MIT License) + +Copyright (c) 2012-2015, JP Richardson + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vscodeEvalExtension/node_modules/jsonfile/README.md b/vscodeEvalExtension/node_modules/jsonfile/README.md new file mode 100644 index 0000000..910cde0 --- /dev/null +++ b/vscodeEvalExtension/node_modules/jsonfile/README.md @@ -0,0 +1,230 @@ +Node.js - jsonfile +================ + +Easily read/write JSON files in Node.js. _Note: this module cannot be used in the browser._ + +[![npm Package](https://img.shields.io/npm/v/jsonfile.svg?style=flat-square)](https://www.npmjs.org/package/jsonfile) +[![build status](https://secure.travis-ci.org/jprichardson/node-jsonfile.svg)](http://travis-ci.org/jprichardson/node-jsonfile) +[![windows Build status](https://img.shields.io/appveyor/ci/jprichardson/node-jsonfile/master.svg?label=windows%20build)](https://ci.appveyor.com/project/jprichardson/node-jsonfile/branch/master) + +Standard JavaScript + +Why? +---- + +Writing `JSON.stringify()` and then `fs.writeFile()` and `JSON.parse()` with `fs.readFile()` enclosed in `try/catch` blocks became annoying. + + + +Installation +------------ + + npm install --save jsonfile + + + +API +--- + +* [`readFile(filename, [options], callback)`](#readfilefilename-options-callback) +* [`readFileSync(filename, [options])`](#readfilesyncfilename-options) +* [`writeFile(filename, obj, [options], callback)`](#writefilefilename-obj-options-callback) +* [`writeFileSync(filename, obj, [options])`](#writefilesyncfilename-obj-options) + +---- + +### readFile(filename, [options], callback) + +`options` (`object`, default `undefined`): Pass in any [`fs.readFile`](https://nodejs.org/api/fs.html#fs_fs_readfile_path_options_callback) options or set `reviver` for a [JSON reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse). + - `throws` (`boolean`, default: `true`). If `JSON.parse` throws an error, pass this error to the callback. + If `false`, returns `null` for the object. + + +```js +const jsonfile = require('jsonfile') +const file = '/tmp/data.json' +jsonfile.readFile(file, function (err, obj) { + if (err) console.error(err) + console.dir(obj) +}) +``` + +You can also use this method with promises. The `readFile` method will return a promise if you do not pass a callback function. + +```js +const jsonfile = require('jsonfile') +const file = '/tmp/data.json' +jsonfile.readFile(file) + .then(obj => console.dir(obj)) + .catch(error => console.error(error)) +``` + +---- + +### readFileSync(filename, [options]) + +`options` (`object`, default `undefined`): Pass in any [`fs.readFileSync`](https://nodejs.org/api/fs.html#fs_fs_readfilesync_path_options) options or set `reviver` for a [JSON reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse). +- `throws` (`boolean`, default: `true`). If an error is encountered reading or parsing the file, throw the error. If `false`, returns `null` for the object. + +```js +const jsonfile = require('jsonfile') +const file = '/tmp/data.json' + +console.dir(jsonfile.readFileSync(file)) +``` + +---- + +### writeFile(filename, obj, [options], callback) + +`options`: Pass in any [`fs.writeFile`](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback) options or set `replacer` for a [JSON replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). Can also pass in `spaces`, or override `EOL` string or set `finalEOL` flag as `false` to not save the file with `EOL` at the end. + + +```js +const jsonfile = require('jsonfile') + +const file = '/tmp/data.json' +const obj = { name: 'JP' } + +jsonfile.writeFile(file, obj, function (err) { + if (err) console.error(err) +}) +``` +Or use with promises as follows: + +```js +const jsonfile = require('jsonfile') + +const file = '/tmp/data.json' +const obj = { name: 'JP' } + +jsonfile.writeFile(file, obj) + .then(res => { + console.log('Write complete') + }) + .catch(error => console.error(error)) +``` + + +**formatting with spaces:** + +```js +const jsonfile = require('jsonfile') + +const file = '/tmp/data.json' +const obj = { name: 'JP' } + +jsonfile.writeFile(file, obj, { spaces: 2 }, function (err) { + if (err) console.error(err) +}) +``` + +**overriding EOL:** + +```js +const jsonfile = require('jsonfile') + +const file = '/tmp/data.json' +const obj = { name: 'JP' } + +jsonfile.writeFile(file, obj, { spaces: 2, EOL: '\r\n' }, function (err) { + if (err) console.error(err) +}) +``` + + +**disabling the EOL at the end of file:** + +```js +const jsonfile = require('jsonfile') + +const file = '/tmp/data.json' +const obj = { name: 'JP' } + +jsonfile.writeFile(file, obj, { spaces: 2, finalEOL: false }, function (err) { + if (err) console.log(err) +}) +``` + +**appending to an existing JSON file:** + +You can use `fs.writeFile` option `{ flag: 'a' }` to achieve this. + +```js +const jsonfile = require('jsonfile') + +const file = '/tmp/mayAlreadyExistedData.json' +const obj = { name: 'JP' } + +jsonfile.writeFile(file, obj, { flag: 'a' }, function (err) { + if (err) console.error(err) +}) +``` + +---- + +### writeFileSync(filename, obj, [options]) + +`options`: Pass in any [`fs.writeFileSync`](https://nodejs.org/api/fs.html#fs_fs_writefilesync_file_data_options) options or set `replacer` for a [JSON replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). Can also pass in `spaces`, or override `EOL` string or set `finalEOL` flag as `false` to not save the file with `EOL` at the end. + +```js +const jsonfile = require('jsonfile') + +const file = '/tmp/data.json' +const obj = { name: 'JP' } + +jsonfile.writeFileSync(file, obj) +``` + +**formatting with spaces:** + +```js +const jsonfile = require('jsonfile') + +const file = '/tmp/data.json' +const obj = { name: 'JP' } + +jsonfile.writeFileSync(file, obj, { spaces: 2 }) +``` + +**overriding EOL:** + +```js +const jsonfile = require('jsonfile') + +const file = '/tmp/data.json' +const obj = { name: 'JP' } + +jsonfile.writeFileSync(file, obj, { spaces: 2, EOL: '\r\n' }) +``` + +**disabling the EOL at the end of file:** + +```js +const jsonfile = require('jsonfile') + +const file = '/tmp/data.json' +const obj = { name: 'JP' } + +jsonfile.writeFileSync(file, obj, { spaces: 2, finalEOL: false }) +``` + +**appending to an existing JSON file:** + +You can use `fs.writeFileSync` option `{ flag: 'a' }` to achieve this. + +```js +const jsonfile = require('jsonfile') + +const file = '/tmp/mayAlreadyExistedData.json' +const obj = { name: 'JP' } + +jsonfile.writeFileSync(file, obj, { flag: 'a' }) +``` + +License +------- + +(MIT License) + +Copyright 2012-2016, JP Richardson diff --git a/vscodeEvalExtension/node_modules/jsonfile/index.js b/vscodeEvalExtension/node_modules/jsonfile/index.js new file mode 100644 index 0000000..0582868 --- /dev/null +++ b/vscodeEvalExtension/node_modules/jsonfile/index.js @@ -0,0 +1,88 @@ +let _fs +try { + _fs = require('graceful-fs') +} catch (_) { + _fs = require('fs') +} +const universalify = require('universalify') +const { stringify, stripBom } = require('./utils') + +async function _readFile (file, options = {}) { + if (typeof options === 'string') { + options = { encoding: options } + } + + const fs = options.fs || _fs + + const shouldThrow = 'throws' in options ? options.throws : true + + let data = await universalify.fromCallback(fs.readFile)(file, options) + + data = stripBom(data) + + let obj + try { + obj = JSON.parse(data, options ? options.reviver : null) + } catch (err) { + if (shouldThrow) { + err.message = `${file}: ${err.message}` + throw err + } else { + return null + } + } + + return obj +} + +const readFile = universalify.fromPromise(_readFile) + +function readFileSync (file, options = {}) { + if (typeof options === 'string') { + options = { encoding: options } + } + + const fs = options.fs || _fs + + const shouldThrow = 'throws' in options ? options.throws : true + + try { + let content = fs.readFileSync(file, options) + content = stripBom(content) + return JSON.parse(content, options.reviver) + } catch (err) { + if (shouldThrow) { + err.message = `${file}: ${err.message}` + throw err + } else { + return null + } + } +} + +async function _writeFile (file, obj, options = {}) { + const fs = options.fs || _fs + + const str = stringify(obj, options) + + await universalify.fromCallback(fs.writeFile)(file, str, options) +} + +const writeFile = universalify.fromPromise(_writeFile) + +function writeFileSync (file, obj, options = {}) { + const fs = options.fs || _fs + + const str = stringify(obj, options) + // not sure if fs.writeFileSync returns anything, but just in case + return fs.writeFileSync(file, str, options) +} + +const jsonfile = { + readFile, + readFileSync, + writeFile, + writeFileSync +} + +module.exports = jsonfile diff --git a/vscodeEvalExtension/node_modules/jsonfile/package.json b/vscodeEvalExtension/node_modules/jsonfile/package.json new file mode 100644 index 0000000..4d01eb1 --- /dev/null +++ b/vscodeEvalExtension/node_modules/jsonfile/package.json @@ -0,0 +1,40 @@ +{ + "name": "jsonfile", + "version": "6.1.0", + "description": "Easily read/write JSON files.", + "repository": { + "type": "git", + "url": "git@github.com:jprichardson/node-jsonfile.git" + }, + "keywords": [ + "read", + "write", + "file", + "json", + "fs", + "fs-extra" + ], + "author": "JP Richardson ", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + }, + "devDependencies": { + "mocha": "^8.2.0", + "rimraf": "^2.4.0", + "standard": "^16.0.1" + }, + "main": "index.js", + "files": [ + "index.js", + "utils.js" + ], + "scripts": { + "lint": "standard", + "test": "npm run lint && npm run unit", + "unit": "mocha" + } +} diff --git a/vscodeEvalExtension/node_modules/jsonfile/utils.js b/vscodeEvalExtension/node_modules/jsonfile/utils.js new file mode 100644 index 0000000..b5ff48e --- /dev/null +++ b/vscodeEvalExtension/node_modules/jsonfile/utils.js @@ -0,0 +1,14 @@ +function stringify (obj, { EOL = '\n', finalEOL = true, replacer = null, spaces } = {}) { + const EOF = finalEOL ? EOL : '' + const str = JSON.stringify(obj, replacer, spaces) + + return str.replace(/\n/g, EOL) + EOF +} + +function stripBom (content) { + // we do this because JSON.parse would convert it to a utf8 string if encoding wasn't specified + if (Buffer.isBuffer(content)) content = content.toString('utf8') + return content.replace(/^\uFEFF/, '') +} + +module.exports = { stringify, stripBom } diff --git a/vscodeEvalExtension/node_modules/universalify/LICENSE b/vscodeEvalExtension/node_modules/universalify/LICENSE new file mode 100644 index 0000000..514e84e --- /dev/null +++ b/vscodeEvalExtension/node_modules/universalify/LICENSE @@ -0,0 +1,20 @@ +(The MIT License) + +Copyright (c) 2017, Ryan Zimmerman + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the 'Software'), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vscodeEvalExtension/node_modules/universalify/README.md b/vscodeEvalExtension/node_modules/universalify/README.md new file mode 100644 index 0000000..1184939 --- /dev/null +++ b/vscodeEvalExtension/node_modules/universalify/README.md @@ -0,0 +1,76 @@ +# universalify + +![GitHub Workflow Status (branch)](https://img.shields.io/github/actions/workflow/status/RyanZim/universalify/ci.yml?branch=master) +![Coveralls github branch](https://img.shields.io/coveralls/github/RyanZim/universalify/master.svg) +![npm](https://img.shields.io/npm/dm/universalify.svg) +![npm](https://img.shields.io/npm/l/universalify.svg) + +Make a callback- or promise-based function support both promises and callbacks. + +Uses the native promise implementation. + +## Installation + +```bash +npm install universalify +``` + +## API + +### `universalify.fromCallback(fn)` + +Takes a callback-based function to universalify, and returns the universalified function. + +Function must take a callback as the last parameter that will be called with the signature `(error, result)`. `universalify` does not support calling the callback with three or more arguments, and does not ensure that the callback is only called once. + +```js +function callbackFn (n, cb) { + setTimeout(() => cb(null, n), 15) +} + +const fn = universalify.fromCallback(callbackFn) + +// Works with Promises: +fn('Hello World!') +.then(result => console.log(result)) // -> Hello World! +.catch(error => console.error(error)) + +// Works with Callbacks: +fn('Hi!', (error, result) => { + if (error) return console.error(error) + console.log(result) + // -> Hi! +}) +``` + +### `universalify.fromPromise(fn)` + +Takes a promise-based function to universalify, and returns the universalified function. + +Function must return a valid JS promise. `universalify` does not ensure that a valid promise is returned. + +```js +function promiseFn (n) { + return new Promise(resolve => { + setTimeout(() => resolve(n), 15) + }) +} + +const fn = universalify.fromPromise(promiseFn) + +// Works with Promises: +fn('Hello World!') +.then(result => console.log(result)) // -> Hello World! +.catch(error => console.error(error)) + +// Works with Callbacks: +fn('Hi!', (error, result) => { + if (error) return console.error(error) + console.log(result) + // -> Hi! +}) +``` + +## License + +MIT diff --git a/vscodeEvalExtension/node_modules/universalify/index.js b/vscodeEvalExtension/node_modules/universalify/index.js new file mode 100644 index 0000000..233beac --- /dev/null +++ b/vscodeEvalExtension/node_modules/universalify/index.js @@ -0,0 +1,24 @@ +'use strict' + +exports.fromCallback = function (fn) { + return Object.defineProperty(function (...args) { + if (typeof args[args.length - 1] === 'function') fn.apply(this, args) + else { + return new Promise((resolve, reject) => { + args.push((err, res) => (err != null) ? reject(err) : resolve(res)) + fn.apply(this, args) + }) + } + }, 'name', { value: fn.name }) +} + +exports.fromPromise = function (fn) { + return Object.defineProperty(function (...args) { + const cb = args[args.length - 1] + if (typeof cb !== 'function') return fn.apply(this, args) + else { + args.pop() + fn.apply(this, args).then(r => cb(null, r), cb) + } + }, 'name', { value: fn.name }) +} diff --git a/vscodeEvalExtension/node_modules/universalify/package.json b/vscodeEvalExtension/node_modules/universalify/package.json new file mode 100644 index 0000000..d60fccb --- /dev/null +++ b/vscodeEvalExtension/node_modules/universalify/package.json @@ -0,0 +1,34 @@ +{ + "name": "universalify", + "version": "2.0.1", + "description": "Make a callback- or promise-based function support both promises and callbacks.", + "keywords": [ + "callback", + "native", + "promise" + ], + "homepage": "https://github.com/RyanZim/universalify#readme", + "bugs": "https://github.com/RyanZim/universalify/issues", + "license": "MIT", + "author": "Ryan Zimmerman ", + "files": [ + "index.js" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/RyanZim/universalify.git" + }, + "scripts": { + "test": "standard && nyc --reporter text --reporter lcovonly tape test/*.js | colortape" + }, + "devDependencies": { + "colortape": "^0.1.2", + "coveralls": "^3.0.1", + "nyc": "^15.0.0", + "standard": "^14.3.1", + "tape": "^5.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } +} diff --git a/vscodeEvalExtension/out/extension.js b/vscodeEvalExtension/out/extension.js index 11376dc..c4cf32b 100644 --- a/vscodeEvalExtension/out/extension.js +++ b/vscodeEvalExtension/out/extension.js @@ -27,31 +27,26 @@ exports.deactivate = exports.activate = void 0; // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below const vscode = __importStar(require("vscode")); +const fs = __importStar(require("fs-extra")); // This method is called when your extension is activated // Your extension is activated the very first time the command is executed function activate(context) { - // Use the console to output diagnostic information (console.log) and errors (console.error) - // This line of code will only be executed once when your extension is activated - // console.log('Congratulations, your extension "eval" is now active!'); // The command has been defined in the package.json file // Now provide the implementation of the command with registerCommand // The commandId parameter must match the command field in package.json let OpenProject = vscode.commands.registerCommand('eval.OpenProject', () => { - // The code you place here will be executed every time your command is executed - // Display a message box to the user - // vscode.window.showInformationMessage(String(vscode.window.state.focused)); if (vscode.workspace.workspaceFolders) { - console.log(vscode.workspace.workspaceFolders[0].name); + fs.writeFileSync("/home/user/OpenProject.txt", vscode.workspace.workspaceFolders[0].name); } else { - console.log(false); + fs.writeFileSync("/home/user/OpenProject.txt", ""); } }); let GetColorTheme = vscode.commands.registerCommand('eval.GetColorTheme', () => { - console.log(vscode.window.activeColorTheme.kind == 2); + fs.writeFileSync("/home/user/GetColorTheme.txt", String(vscode.window.activeColorTheme.kind)); // ==2 }); let GetBreakPoint = vscode.commands.registerCommand('eval.GetBreakPoint', () => { - console.log(vscode.debug.breakpoints.length == 1); + fs.writeFileSync("/home/user/GetBreakPoint.txt", String(vscode.debug.breakpoints.length)); // ==1 }); context.subscriptions.push(OpenProject, GetColorTheme, GetBreakPoint); } diff --git a/vscodeEvalExtension/out/extension.js.map b/vscodeEvalExtension/out/extension.js.map index ac47063..f68ddac 100644 --- a/vscodeEvalExtension/out/extension.js.map +++ b/vscodeEvalExtension/out/extension.js.map @@ -1 +1 @@ -{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6DAA6D;AAC7D,8EAA8E;AAC9E,+CAAiC;AAEjC,yDAAyD;AACzD,0EAA0E;AAC1E,SAAgB,QAAQ,CAAC,OAAgC;IAExD,4FAA4F;IAC5F,gFAAgF;IAChF,wEAAwE;IAExE,wDAAwD;IACxD,qEAAqE;IACrE,uEAAuE;IACvE,IAAI,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC1E,+EAA+E;QAC/E,oCAAoC;QACpC,6EAA6E;QAC7E,IAAI,MAAM,CAAC,SAAS,CAAC,gBAAgB,EAAE,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC;aAAM,CAAC;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,IAAI,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC9E,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,IAAI,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC9E,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AACvE,CAAC;AA7BD,4BA6BC;AAED,2DAA2D;AAC3D,SAAgB,UAAU,KAAI,CAAC;AAA/B,gCAA+B"} \ No newline at end of file +{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6DAA6D;AAC7D,8EAA8E;AAC9E,+CAAiC;AACjC,6CAA+B;AAE/B,yDAAyD;AACzD,0EAA0E;AAC1E,SAAgB,QAAQ,CAAC,OAAgC;IACxD,wDAAwD;IACxD,qEAAqE;IACrE,uEAAuE;IACvE,IAAI,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC1E,IAAI,MAAM,CAAC,SAAS,CAAC,gBAAgB,EAAE,CAAC;YACvC,EAAE,CAAC,aAAa,CAAC,4BAA4B,EAAE,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3F,CAAC;aAAM,CAAC;YACP,EAAE,CAAC,aAAa,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;QACpD,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,IAAI,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC9E,EAAE,CAAC,aAAa,CAAC,8BAA8B,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM;IACtG,CAAC,CAAC,CAAC;IAEH,IAAI,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC9E,EAAE,CAAC,aAAa,CAAC,8BAA8B,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM;IAClG,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AACvE,CAAC;AArBD,4BAqBC;AAED,2DAA2D;AAC3D,SAAgB,UAAU,KAAI,CAAC;AAA/B,gCAA+B"} \ No newline at end of file diff --git a/vscodeEvalExtension/package-lock.json b/vscodeEvalExtension/package-lock.json index 2f6da85..cc449c8 100644 --- a/vscodeEvalExtension/package-lock.json +++ b/vscodeEvalExtension/package-lock.json @@ -7,6 +7,10 @@ "": { "name": "eval", "version": "0.0.1", + "dependencies": { + "@types/fs-extra": "^11.0.4", + "fs-extra": "^11.2.0" + }, "devDependencies": { "@types/mocha": "^10.0.6", "@types/node": "18.x", @@ -262,12 +266,29 @@ "node": ">= 6" } }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/mocha": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", @@ -278,7 +299,6 @@ "version": "18.19.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.4.tgz", "integrity": "sha512-xNzlUhzoHotIsnFoXmJB+yWmBvFZgKCI9TtPIEdYIMM1KWfwuY8zh7wvc1u1OAXlC7dlf6mZVx/s+Y5KfFz19A==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -1252,6 +1272,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1350,6 +1383,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -1598,6 +1636,17 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -2556,8 +2605,15 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } }, "node_modules/uri-js": { "version": "4.4.1", diff --git a/vscodeEvalExtension/package.json b/vscodeEvalExtension/package.json index 0843db9..5885208 100644 --- a/vscodeEvalExtension/package.json +++ b/vscodeEvalExtension/package.json @@ -36,14 +36,18 @@ "test": "vscode-test" }, "devDependencies": { - "@types/vscode": "^1.85.0", "@types/mocha": "^10.0.6", "@types/node": "18.x", + "@types/vscode": "^1.85.0", "@typescript-eslint/eslint-plugin": "^6.15.0", "@typescript-eslint/parser": "^6.15.0", - "eslint": "^8.56.0", - "typescript": "^5.3.3", "@vscode/test-cli": "^0.0.4", - "@vscode/test-electron": "^2.3.8" + "@vscode/test-electron": "^2.3.8", + "eslint": "^8.56.0", + "typescript": "^5.3.3" + }, + "dependencies": { + "@types/fs-extra": "^11.0.4", + "fs-extra": "^11.2.0" } } diff --git a/vscodeEvalExtension/src/extension.ts b/vscodeEvalExtension/src/extension.ts index be28847..9e57de3 100644 --- a/vscodeEvalExtension/src/extension.ts +++ b/vscodeEvalExtension/src/extension.ts @@ -1,35 +1,28 @@ // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; +import * as fs from 'fs-extra'; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed export function activate(context: vscode.ExtensionContext) { - - // Use the console to output diagnostic information (console.log) and errors (console.error) - // This line of code will only be executed once when your extension is activated - // console.log('Congratulations, your extension "eval" is now active!'); - // The command has been defined in the package.json file // Now provide the implementation of the command with registerCommand // The commandId parameter must match the command field in package.json let OpenProject = vscode.commands.registerCommand('eval.OpenProject', () => { - // The code you place here will be executed every time your command is executed - // Display a message box to the user - // vscode.window.showInformationMessage(String(vscode.window.state.focused)); if (vscode.workspace.workspaceFolders) { - console.log(vscode.workspace.workspaceFolders[0].name); + fs.writeFileSync("/home/user/OpenProject.txt", vscode.workspace.workspaceFolders[0].name); } else { - console.log(false); + fs.writeFileSync("/home/user/OpenProject.txt", ""); } }); let GetColorTheme = vscode.commands.registerCommand('eval.GetColorTheme', () => { - console.log(vscode.window.activeColorTheme.kind == 2); + fs.writeFileSync("/home/user/GetColorTheme.txt", String(vscode.window.activeColorTheme.kind)); // ==2 }); let GetBreakPoint = vscode.commands.registerCommand('eval.GetBreakPoint', () => { - console.log(vscode.debug.breakpoints.length == 1); + fs.writeFileSync("/home/user/GetBreakPoint.txt", String(vscode.debug.breakpoints.length)); // ==1 }); context.subscriptions.push(OpenProject, GetColorTheme, GetBreakPoint); From d6f694da1c9113e8fd66570ec67be676b3c01c54 Mon Sep 17 00:00:00 2001 From: Siheng Zhao <1730625285@qq.com> Date: Fri, 12 Jan 2024 16:36:02 +0800 Subject: [PATCH 7/7] update GIMP examples and eval --- desktop_env/evaluators/metrics/gimp.py | 43 ++++++++----------- ...554785e9-4523-4e7a-b8e1-8016f565f56a.json} | 20 ++++----- ...7a4deb26-d57d-4ea9-9a73-630f66a7b568.json} | 12 +++--- 3 files changed, 35 insertions(+), 40 deletions(-) rename evaluation_examples/examples/gimp/{7a4deb26-d57d-4ea9-9a73-630f66a7b568 copy => 554785e9-4523-4e7a-b8e1-8016f565f56a.json} (61%) rename evaluation_examples/examples/gimp/{7a4deb26-d57d-4ea9-9a73-630f66a7b568 => 7a4deb26-d57d-4ea9-9a73-630f66a7b568.json} (78%) diff --git a/desktop_env/evaluators/metrics/gimp.py b/desktop_env/evaluators/metrics/gimp.py index 9607ba6..cac7635 100644 --- a/desktop_env/evaluators/metrics/gimp.py +++ b/desktop_env/evaluators/metrics/gimp.py @@ -1,5 +1,5 @@ import os - +from PIL import Image, ImageChops, ImageStat def get_gimp_export_path(): # Path to GIMP's configuration file. This example assumes GIMP version 2.10. @@ -21,21 +21,19 @@ def get_gimp_export_path(): print("GIMP configuration file not found") return False -from PIL import Image, ImageChops, ImageStat +def increase_saturation(image1_path: str, image2_path: str) -> float: + def calculate_saturation(image): + # convert the image to HSV mode + hsv_image = image.convert("HSV") -def calculate_saturation(image): - # convert the image to HSV mode - hsv_image = image.convert("HSV") + saturation_channel = hsv_image.split()[1] - saturation_channel = hsv_image.split()[1] + # calculate the mean saturation level + stat = ImageStat.Stat(saturation_channel) + mean_saturation = stat.mean[0] - # calculate the mean saturation level - stat = ImageStat.Stat(saturation_channel) - mean_saturation = stat.mean[0] + return mean_saturation - return mean_saturation - -def increase_saturation(image1_path, image2_path): image1 = Image.open(image1_path) image2 = Image.open(image2_path) @@ -45,17 +43,17 @@ def increase_saturation(image1_path, image2_path): return 1 if saturation1 < saturation2 else 0 -def calculate_brightness(image): - # Convert the image to grayscale mode - grayscale_image = image.convert("L") +def decrease_brightness(image1_path: str, image2_path: str) -> float: + def calculate_brightness(image): + # Convert the image to grayscale mode + grayscale_image = image.convert("L") - # Get the image data - pixels = list(grayscale_image.getdata()) + # Get the image data + pixels = list(grayscale_image.getdata()) - brightness = sum(pixels) / len(pixels) - return brightness + brightness = sum(pixels) / len(pixels) + return brightness -def decrease_brightness(image1_path, image2_path): image1 = Image.open(image1_path) image2 = Image.open(image2_path) @@ -65,12 +63,9 @@ def decrease_brightness(image1_path, image2_path): return 1 if brightness1 > brightness2 else 0 if __name__ == "__main__": - # 输入两张图片的路径 image1_path = "../Downloads/1.png" image2_path = "../Downloads/edited_darker.png" - # 比较图片亮度 decrease_brightness(image1_path, image2_path) - - # 比较图片饱和度 + increase_saturation(image1_path, image2_path) diff --git a/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 copy b/evaluation_examples/examples/gimp/554785e9-4523-4e7a-b8e1-8016f565f56a.json similarity index 61% rename from evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 copy rename to evaluation_examples/examples/gimp/554785e9-4523-4e7a-b8e1-8016f565f56a.json index eb8862a..0e4f7f8 100644 --- a/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 copy +++ b/evaluation_examples/examples/gimp/554785e9-4523-4e7a-b8e1-8016f565f56a.json @@ -9,8 +9,8 @@ "parameters": { "files": [ { - "url": "https://drive.usercontent.google.com/download?id=1SIvX9Wimyw6i2UvnoLTNDHIObvDLAsIM&export=download&authuser=0&confirm=t&uuid=a48447ab-13a2-421f-9662-6ffff8f6f6d5&at=APZUnTVRxofs822XxgEv33WwYCkb:1705046264363", - "path": "Desktop/1.png" + "url": "", + "path": "Desktop/2.png" } ] } @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "Desktop/View_Person_Organizational_Summary.docx" + "path": "Desktop/2.png" } } ], @@ -28,15 +28,15 @@ ], "evaluator": { "func": "increase_saturation", + "expected": { + "type": "cloud_file", + "path": "", + "dest": "edited_colorful.png" + }, "result": { "type": "vm_file", - "path": "Desktop/1.png", - "dest": "1.png" - }, - "expected": { - "type": "vm_file", - "path": "Desktop/edited_colorful.png", - "dest": "edited_colorful.png" + "path": "Desktop/2.png", + "dest": "2.png" } } } \ No newline at end of file diff --git a/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 b/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568.json similarity index 78% rename from evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 rename to evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568.json index ab644b2..a2acd0b 100644 --- a/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568 +++ b/evaluation_examples/examples/gimp/7a4deb26-d57d-4ea9-9a73-630f66a7b568.json @@ -18,7 +18,7 @@ { "type": "open", "parameters": { - "path": "Desktop/View_Person_Organizational_Summary.docx" + "path": "Desktop/1.png" } } ], @@ -28,15 +28,15 @@ ], "evaluator": { "func": "decrease_brightness", + "expected": { + "type": "cloud_file", + "path": "https://drive.usercontent.google.com/download?id=1M7T5iPv0kWvmZBbdTcRdG45zIpHMtrBn&export=download&authuser=0&confirm=t&uuid=d95db1f8-27dc-4532-9976-ea99c293f53e&at=APZUnTXfpgNCtXDtlqd55LgmrIAj:1705048270986", + "dest": "edited_darker.png" + }, "result": { "type": "vm_file", "path": "Desktop/1.png", "dest": "1.png" - }, - "expected": { - "type": "vm_file", - "path": "Desktop/edited_darker.png", - "dest": "edited_darker.png" } } } \ No newline at end of file