Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STU-288 | Test Sequencer Project #1123

Merged
merged 46 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b1d790e
Templating
LatentDream Feb 28, 2024
98278e9
New UI Element for file select
LatentDream Feb 28, 2024
1157dbc
Starting New Project Modal
LatentDream Feb 28, 2024
bbe03cc
PathInput | Support Directory
LatentDream Feb 29, 2024
e6bff91
Project Creation templating
LatentDream Feb 29, 2024
9c67a86
Fix my dumb mistake that took me way to long to figure out
LatentDream Mar 1, 2024
f262ed4
Create, save, load
LatentDream Mar 1, 2024
5aa1c8c
handle "save" button
LatentDream Mar 1, 2024
d04fbf1
Better handling of name
LatentDream Mar 1, 2024
2537a1d
Handle Path in Conditional and optional import
LatentDream Mar 1, 2024
0d5063f
[TS-Project] Big cleanup of the logic
LatentDream Mar 2, 2024
6a96bdd
[TS-Project] Migrating frontend
LatentDream Mar 2, 2024
bd5fd22
[TS-Project] React .... :'( Wtf
LatentDream Mar 2, 2024
f9daca8
[TS-Project] Fix All Path Problem
LatentDream Mar 2, 2024
f43f9f0
[TS-Project] Result Err + Toast.error: Weird behavior -> Throw instead
LatentDream Mar 2, 2024
92ce06a
[TS-Project] Disabled import tests that are not in project scope
LatentDream Mar 3, 2024
26bd6d4
[TS-Project] Handle Windows potetial problematic sep
LatentDream Mar 3, 2024
5dd9a7e
close option
LatentDream Mar 4, 2024
d302e86
[TS-Project] Fix Path problem on windows
LatentDream Mar 4, 2024
aa4d4db
[TS-Project] Project always in Unix like path | test in platform styl…
LatentDream Mar 4, 2024
bb0e56b
[TS-Project] Export with deps for internal interpreter
LatentDream Mar 4, 2024
0bc0b04
[TS-Project] Dark mode UI for path input
LatentDream Mar 4, 2024
9e64182
[TS-Project] Permission for view to import sequencer project
LatentDream Mar 5, 2024
18f429f
[TS-Project] Removing Dead Code
LatentDream Mar 5, 2024
e64623d
[TS-Project] Turn off iterpreter feature [For Now]
LatentDream Mar 5, 2024
2e9d7dc
small error fix
LatentDream Mar 5, 2024
c1184fd
PR Comments part 1
LatentDream Mar 6, 2024
86e1dcb
Formatting
LatentDream Mar 6, 2024
3b70130
[TS-Project] Merge Main
LatentDream Mar 9, 2024
a3f1451
[TS-Project] Clean Up Migration
LatentDream Mar 9, 2024
65b35f8
[TS-Project] Fix Project Zed Schema and replace never throw to a solu…
LatentDream Mar 9, 2024
dec7672
Formatting
LatentDream Mar 9, 2024
6179bae
[TS-Project] Fix potential error from LSP
LatentDream Mar 9, 2024
f4f123b
[TS-Project] Project handler / frontend:infer all path are posix
LatentDream Mar 9, 2024
6e80bda
Formatting
LatentDream Mar 9, 2024
292ee29
[TS-Project] CreateNewTest Util func
LatentDream Mar 10, 2024
9d6632a
[TS-Project] Gateway function: AddNewTest to test sequencer
LatentDream Mar 10, 2024
b11899d
[TS-Project] Merge branch 'TS-Project' of https://github.com/LatentDr…
LatentDream Mar 10, 2024
a90adc1
Formatting
LatentDream Mar 10, 2024
5e9ae24
[TS-Project] Removing empty file
LatentDream Mar 10, 2024
5d6c802
[TS-Project] Merge branch 'TS-Project' of https://github.com/LatentDr…
LatentDream Mar 10, 2024
2343f57
[TS-Project] Import Project present only when project is loaded
LatentDream Mar 10, 2024
6cff7e7
[TS-Project] Merge with the export to cloud feature
LatentDream Mar 10, 2024
306421e
[TS-Project] Save project now save exportToCloud config
LatentDream Mar 10, 2024
96dcc08
[TS-Project] Removed undefined exportToCloud in discover test
LatentDream Mar 10, 2024
95639dd
Formatting
LatentDream Mar 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions captain/utils/pytest/discover_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from pytest_jsonreport.plugin import JSONReport
from captain.utils.import_utils import unload_module
import re
import pathlib


def check_missing_imports(report: RootModel):
Expand Down Expand Up @@ -61,7 +62,9 @@ def dfs(
test_list.append(
TestDiscoveryResponse(
test_name=node.nodeid.replace(" ", "_"),
path=os.path.join(json_data.root, node.nodeid),
path=pathlib.Path(
os.path.join(json_data.root, node.nodeid)
).as_posix(),
)
)

Expand All @@ -72,7 +75,9 @@ def dfs(
return
if one_file:
return_val.append(
TestDiscoveryResponse(test_name=os.path.basename(path), path=path)
TestDiscoveryResponse(
test_name=os.path.basename(path), path=pathlib.Path(path).as_posix()
)
)
else:
return_val.extend(test_list)
9 changes: 9 additions & 0 deletions src/api/fileSave.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ export function saveFile(
ipcRenderer.send(API.writeFileSync, path, data, allowedExtensions);
}

export async function saveToFile(path: string, data: string): Promise<boolean> {
try {
saveFile(path, data, ["tjoy"]);
return true;
} catch {
return false;
}
}

export async function saveFileAs(
defaultFilename: string,
data: string,
Expand Down
14 changes: 13 additions & 1 deletion src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { InterpretersList } from "@/main/python/interpreter";
import { PoetryGroupInfo, PythonDependency } from "src/types/poetry";
import { ResultAsync, fromPromise } from "neverthrow";
import type { User } from "@/types/auth";
import path from "path";

export const API = {
checkPythonInstallation: "CHECK_PYTHON_INSTALLATION",
Expand All @@ -20,6 +21,7 @@ export const API = {
statusBarLogging: "STATUSBAR_LOGGING",
setPythonInterpreter: "SET_PY_INTERPRETER",
writeFileSync: "WRITE_FILE_SYNC",
writeFile: "WRITE_FILE",
showSaveDialog: "SHOW_SAVE_DIALOG",
browsePythonInterpreter: "BROWSE_PY_INTERPRETER",
sendLogToStatusbar: "SEND_LOG_TO_STATUSBAR",
Expand All @@ -41,8 +43,10 @@ export const API = {
poetryInstallDepUserGroup: "POETRY_INSTALL_DEP_USER_GROUP",
poetryUninstallDepUserGroup: "POETRY_UNINSTALL_DEP_USER_GROUP",
poetryUninstallDepGroup: "POETRY_UNINSTALL_DEP_GROUP",
poetryInstallRequirementsUserGroup: "POETRY_INSTALL_REQUIREMENTS_USER_GROUP",
openFilePicker: "OPEN_FILE_PICKER",
getFileContent: "GET_FILE_CONTENT",
isFileOnDisk: "IS_FILE_ON_DISK",
openEditorWindow: "OPEN_EDITOR_WINDOW",
loadFileFromFullPath: "LOAD_FILE_FROM_FULL_PATH",
saveFileToFullPath: "SAVE_FILE_TO_FULL_PATH",
Expand Down Expand Up @@ -95,7 +99,8 @@ export default {
ping: (addr: string): Promise<string> => ipcRenderer.invoke(API.ping, addr),
netstat: (): Promise<string> => ipcRenderer.invoke(API.netstat),
ifconfig: (): Promise<string> => ipcRenderer.invoke(API.ifconfig),
pickDirectory: (): Promise<string> => ipcRenderer.invoke(API.pickDirectory),
pickDirectory: (allowDirectoryCreation: boolean): Promise<string> =>
ipcRenderer.invoke(API.pickDirectory, allowDirectoryCreation),
downloadLogs: (): void => ipcRenderer.send(API.downloadLogs),
checkForUpdates: (): void => ipcRenderer.send(API.checkForUpdates),
restartCaptain: (): Promise<void> => ipcRenderer.invoke(API.restartCaptain),
Expand All @@ -116,12 +121,17 @@ export default {
ipcRenderer.invoke(API.poetryUninstallDepGroup, group),
poetryInstallDepUserGroup: (dep: string): Promise<boolean> =>
ipcRenderer.invoke(API.poetryInstallDepUserGroup, dep),
poetryInstallRequirementsUserGroup: (filePath: string): Promise<boolean> =>
ipcRenderer.invoke(API.poetryInstallRequirementsUserGroup, filePath),
poetryUninstallDepUserGroup: (dep: string): Promise<boolean> =>
ipcRenderer.invoke(API.poetryUninstallDepUserGroup, dep),

openTestPicker: (): Promise<{ filePath: string; fileContent: string }> =>
ipcRenderer.invoke(API.openTestPicker),

isFileOnDisk: (filepath: string): Promise<boolean> =>
ipcRenderer.invoke(API.isFileOnDisk, filepath),

openFilePicker: (
allowedExtensions: string[] = ["json"],
): Promise<{ filePath: string; fileContent: string } | undefined> =>
Expand All @@ -130,6 +140,8 @@ export default {
getFileContent: (filepath: string): Promise<string> =>
ipcRenderer.invoke(API.getFileContent, filepath),

getPathSeparator: () => path.sep,

openEditorWindow: (filepath: string): Promise<void> =>
ipcRenderer.invoke(API.openEditorWindow, filepath),

Expand Down
7 changes: 7 additions & 0 deletions src/main/ipc-main-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
readFileSync,
saveFileToFullPath,
writeFileSync,
isFileOnDisk,
} from "./utils";
import {
getAllLogs,
Expand Down Expand Up @@ -41,6 +42,7 @@ import {
poetryGetGroupInfo,
poetryInstallDepGroup,
poetryInstallDepUserGroup,
poetryInstallRequirementsUserGroup,
poetryShowTopLevel,
poetryShowUserGroup,
poetryUninstallDepGroup,
Expand Down Expand Up @@ -100,6 +102,7 @@ export const registerIpcMainHandlers = () => {
return Promise.resolve(!app.isPackaged);
});
ipcMain.handle(API.getAllLogs, getAllLogs);
ipcMain.handle(API.writeFile, writeFileSync);
ipcMain.handle(API.getCustomBlocksDir, getCustomBlocksDir);
ipcMain.handle(API.restartCaptain, restartCaptain);
ipcMain.handle(API.setPythonInterpreter, handlePythonInterpreter);
Expand Down Expand Up @@ -139,6 +142,9 @@ export const registerIpcMainHandlers = () => {
ipcMain.handle(API.poetryInstallDepUserGroup, (_, dep) => {
return poetryInstallDepUserGroup(dep);
});
ipcMain.handle(API.poetryInstallRequirementsUserGroup, (_, filePath) => {
return poetryInstallRequirementsUserGroup(filePath);
});
ipcMain.handle(API.openFilePicker, openFilePicker);
ipcMain.handle(
API.openTestPicker,
Expand Down Expand Up @@ -168,4 +174,5 @@ export const registerIpcMainHandlers = () => {
ipcMain.handle(API.createUserProfile, createUserProfile);
ipcMain.handle(API.deleteUserProfile, deleteUserProfile);
ipcMain.handle(API.getFileContent, readFileSync);
ipcMain.handle(API.isFileOnDisk, isFileOnDisk);
};
19 changes: 19 additions & 0 deletions src/main/python/poetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { execCommand } from "../executor";
import pyproject from "../../../pyproject.toml?raw";
import toml from "toml";
import { store } from "../store";
import * as fs from "fs";

// FIXME: do not hardcode the groups here
export const POETRY_DEP_GROUPS: Pick<
Expand Down Expand Up @@ -156,6 +157,24 @@ export async function poetryInstallDepUserGroup(
return true;
}

export async function poetryInstallRequirementsUserGroup(
filePath: string,
): Promise<boolean> {
try {
const content = fs.readFileSync(filePath, { encoding: "utf-8" }).toString();
const packages: string[] = content
.split("\n")
.filter((line) => line !== "" && !line.startsWith("#"));
izi-on marked this conversation as resolved.
Show resolved Hide resolved
if (packages.length > 0) {
await poetryInstallDepUserGroup(packages.join(" "));
}
return true;
} catch (e) {
console.error(e);
return false;
}
}

export async function poetryUninstallDepUserGroup(
name: string,
): Promise<boolean> {
Expand Down
24 changes: 19 additions & 5 deletions src/main/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { isIP } from "net";
import { execCommand } from "./executor";
import { Command } from "./command";
import { app, dialog } from "electron";
import { join } from "path";
import { join, posix, sep } from "path";
import { killCaptain } from "./python";
import log from "electron-log";
import { ChildProcess } from "node:child_process";
Expand Down Expand Up @@ -73,11 +73,21 @@ export const writeFileSync = (_, filePath: string, text: string): void => {
fs.writeFileSync(filePath, text);
};

export const pickDirectory = async (): Promise<string> => {
export const pickDirectory = async (
_,
allowDirectoryCreation: boolean = false,
): Promise<string> => {
const properties = ["openDirectory"];
if (allowDirectoryCreation) {
properties.push("createDirectory");
}
const handler = await dialog.showOpenDialog({
properties: ["openDirectory"],
// @ts-ignore
properties: properties,
});
return handler.canceled ? "" : handler.filePaths[0];
return handler.canceled
? ""
: handler.filePaths[0].split(sep).join(posix.sep);
};

export const getCustomBlocksDir = async () => {
Expand Down Expand Up @@ -128,7 +138,7 @@ export const openFilePicker = (
encoding: "utf-8",
});
resolve({
filePath: selectedPaths[0],
filePath: selectedPaths[0].split(sep).join(posix.sep),
fileContent,
});
}
Expand Down Expand Up @@ -166,3 +176,7 @@ export const saveFileToFullPath = fs.writeFileSync;
export const readFileSync = (_, filePath: string) => {
return fs.readFileSync(filePath, { encoding: "utf-8" });
};

export const isFileOnDisk = (_, filePath: string): Promise<boolean> => {
return Promise.resolve(fs.existsSync(filePath));
};
1 change: 1 addition & 0 deletions src/renderer/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const buttonVariants = cva(
hover:rounded-md shadow-[4px_4px_0px_0px] shadow-foreground
active:translate-x-[4px] active:translate-y-[4px]
active:rounded-2xl active:shadow-none`,
none: "",
// neumorphism:
// "px-4 py-2 rounded-full flex items-center gap-2 text-slate-500 shadow-[-5px_-5px_10px_rgba(255,_255,_255,_0.8),_5px_5px_10px_rgba(0,_0,_0,_0.25)] transition-all hover:shadow-[-1px_-1px_5px_rgba(255,_255,_255,_0.6),_1px_1px_5px_rgba(0,_0,_0,_0.3),inset_-2px_-2px_5px_rgba(255,_255,_255,_1),inset_2px_2px_4px_rgba(0,_0,_0,_0.3)] hover:text-violet-500",
},
Expand Down
122 changes: 122 additions & 0 deletions src/renderer/components/ui/path-input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import * as React from "react";
LatentDream marked this conversation as resolved.
Show resolved Hide resolved
import { cn } from "@/renderer/lib/utils";
import { Button } from "./button";

interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
allowedExtention?: string[];
allowDirectoryCreation?: boolean;
pickerType?: "file" | "directory";
}

const filePicker = (
allowedExtensions: string[] = [],
): Promise<string | null> => {
return new Promise((resolve, reject) => {
window.api
.openFilePicker(allowedExtensions)
LatentDream marked this conversation as resolved.
Show resolved Hide resolved
.then((result) => {
if (!result) resolve(null);
else resolve(result.filePath);
})
.catch((error) => {
console.error("Errors when trying to load file: ", error);
reject(error);
});
});
};

const directoryPicker = (
allowDirectoryCreation: boolean = false,
): Promise<string | null> => {
return new Promise((resolve, reject) => {
window.api
.pickDirectory(allowDirectoryCreation)
.then((result) => {
if (!result) resolve(null);
else resolve(result);
})
.catch((error) => {
console.error("Errors when trying to load file: ", error);
reject(error);
});
});
};

const PathInput = React.forwardRef<HTMLInputElement, InputProps>(
(
{
className,
onChange: onChangeProp,
disabled,
allowedExtention,
allowDirectoryCreation,
pickerType,
...props
},
ref,
) => {
const [selectedFilePath, setSelectedFilePath] = React.useState<
string | null
>("");
const [manualPath, setManualPath] = React.useState<string>("");

const handlePickerClick = async () => {
const path =
pickerType === "directory"
? await directoryPicker(allowDirectoryCreation)
: await filePicker(allowedExtention);
if (path) {
setSelectedFilePath(path);
setManualPath(path);
if (onChangeProp) {
onChangeProp({
target: { value: path },
} as React.ChangeEvent<HTMLInputElement>);
}
}
};

const handleManualPathChange = (
event: React.ChangeEvent<HTMLInputElement>,
) => {
setManualPath(event.target.value);
setSelectedFilePath("");
if (onChangeProp) {
onChangeProp(event);
}
};

return (
<div
className={cn(
"flex inline-flex h-10 w-full items-center justify-center rounded-md rounded-md border bg-background text-sm text-sm font-medium ring-offset-background transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 disabled:opacity-50",
)}
>
<input
className={cn(
"h-9 w-full rounded-md bg-background pl-3 ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
className,
)}
ref={ref}
// @ts-ignore
value={selectedFilePath !== "" ? selectedFilePath : manualPath}
onChange={handleManualPathChange}
disabled={disabled}
{...props}
/>
<Button
variant={"none"}
disabled={disabled}
className="h-9 hover:accent-transparent"
onClick={handlePickerClick}
>
{" "}
{"Select"}{" "}
</Button>
</div>
);
},
);
PathInput.displayName = "Select a path";

export { PathInput };
Empty file.
Loading
Loading