pybiolib 1.2.883__py3-none-any.whl → 1.2.1890__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- biolib/__init__.py +33 -10
- biolib/_data_record/data_record.py +220 -126
- biolib/_index/index.py +55 -0
- biolib/_index/query_result.py +103 -0
- biolib/_internal/add_copilot_prompts.py +24 -11
- biolib/_internal/add_gui_files.py +81 -0
- biolib/_internal/data_record/__init__.py +1 -1
- biolib/_internal/data_record/data_record.py +1 -18
- biolib/_internal/data_record/push_data.py +65 -16
- biolib/_internal/data_record/remote_storage_endpoint.py +18 -13
- biolib/_internal/file_utils.py +48 -0
- biolib/_internal/lfs/cache.py +4 -2
- biolib/_internal/push_application.py +95 -24
- biolib/_internal/runtime.py +2 -0
- biolib/_internal/string_utils.py +13 -0
- biolib/_internal/{llm_instructions → templates/copilot_template}/.github/instructions/style-general.instructions.md +5 -0
- biolib/_internal/templates/copilot_template/.github/instructions/style-react-ts.instructions.md +47 -0
- biolib/_internal/templates/copilot_template/.github/prompts/biolib_onboard_repo.prompt.md +19 -0
- biolib/_internal/templates/dashboard_template/.biolib/config.yml +5 -0
- biolib/_internal/templates/{init_template → github_workflow_template}/.github/workflows/biolib.yml +7 -2
- biolib/_internal/templates/gitignore_template/.gitignore +10 -0
- biolib/_internal/templates/gui_template/.yarnrc.yml +1 -0
- biolib/_internal/templates/gui_template/App.tsx +53 -0
- biolib/_internal/templates/gui_template/Dockerfile +27 -0
- biolib/_internal/templates/gui_template/biolib-sdk.ts +82 -0
- biolib/_internal/templates/gui_template/dev-data/output.json +7 -0
- biolib/_internal/templates/gui_template/index.css +5 -0
- biolib/_internal/templates/gui_template/index.html +13 -0
- biolib/_internal/templates/gui_template/index.tsx +10 -0
- biolib/_internal/templates/gui_template/package.json +27 -0
- biolib/_internal/templates/gui_template/tsconfig.json +24 -0
- biolib/_internal/templates/gui_template/vite-plugin-dev-data.ts +50 -0
- biolib/_internal/templates/gui_template/vite.config.mts +10 -0
- biolib/_internal/templates/init_template/.biolib/config.yml +1 -0
- biolib/_internal/templates/init_template/Dockerfile +5 -1
- biolib/_internal/templates/init_template/run.py +6 -15
- biolib/_internal/templates/init_template/run.sh +1 -0
- biolib/_internal/templates/templates.py +21 -1
- biolib/_internal/utils/__init__.py +47 -0
- biolib/_internal/utils/auth.py +46 -0
- biolib/_internal/utils/job_url.py +33 -0
- biolib/_internal/utils/multinode.py +12 -14
- biolib/_runtime/runtime.py +15 -2
- biolib/_session/session.py +7 -5
- biolib/_shared/__init__.py +0 -0
- biolib/_shared/types/__init__.py +74 -0
- biolib/_shared/types/account.py +12 -0
- biolib/_shared/types/account_member.py +8 -0
- biolib/{_internal → _shared}/types/experiment.py +1 -0
- biolib/_shared/types/resource.py +37 -0
- biolib/_shared/types/resource_deploy_key.py +11 -0
- biolib/{_internal → _shared}/types/resource_version.py +8 -2
- biolib/_shared/types/user.py +19 -0
- biolib/_shared/utils/__init__.py +7 -0
- biolib/_shared/utils/resource_uri.py +75 -0
- biolib/api/client.py +5 -48
- biolib/app/app.py +97 -55
- biolib/biolib_api_client/api_client.py +3 -47
- biolib/biolib_api_client/app_types.py +1 -1
- biolib/biolib_api_client/biolib_app_api.py +31 -6
- biolib/biolib_api_client/biolib_job_api.py +1 -1
- biolib/biolib_api_client/user_state.py +34 -2
- biolib/biolib_binary_format/module_input.py +8 -0
- biolib/biolib_binary_format/remote_endpoints.py +3 -3
- biolib/biolib_binary_format/remote_stream_seeker.py +39 -25
- biolib/biolib_logging.py +1 -1
- biolib/cli/__init__.py +2 -2
- biolib/cli/auth.py +4 -16
- biolib/cli/data_record.py +82 -0
- biolib/cli/index.py +32 -0
- biolib/cli/init.py +393 -71
- biolib/cli/lfs.py +1 -1
- biolib/cli/run.py +9 -6
- biolib/cli/start.py +14 -1
- biolib/compute_node/job_worker/executors/docker_executor.py +31 -9
- biolib/compute_node/job_worker/executors/docker_types.py +1 -1
- biolib/compute_node/job_worker/executors/types.py +6 -5
- biolib/compute_node/job_worker/job_storage.py +2 -1
- biolib/compute_node/job_worker/job_worker.py +155 -90
- biolib/compute_node/job_worker/large_file_system.py +2 -6
- biolib/compute_node/job_worker/network_alloc.py +99 -0
- biolib/compute_node/job_worker/network_buffer.py +240 -0
- biolib/compute_node/job_worker/utilization_reporter_thread.py +2 -2
- biolib/compute_node/remote_host_proxy.py +163 -79
- biolib/compute_node/utils.py +2 -0
- biolib/compute_node/webserver/compute_node_results_proxy.py +189 -0
- biolib/compute_node/webserver/proxy_utils.py +28 -0
- biolib/compute_node/webserver/webserver.py +64 -19
- biolib/experiments/experiment.py +111 -16
- biolib/jobs/job.py +128 -31
- biolib/jobs/job_result.py +74 -34
- biolib/jobs/types.py +1 -0
- biolib/sdk/__init__.py +28 -3
- biolib/typing_utils.py +1 -1
- biolib/utils/cache_state.py +8 -5
- biolib/utils/multipart_uploader.py +24 -18
- biolib/utils/seq_util.py +1 -1
- pybiolib-1.2.1890.dist-info/METADATA +41 -0
- pybiolib-1.2.1890.dist-info/RECORD +177 -0
- {pybiolib-1.2.883.dist-info → pybiolib-1.2.1890.dist-info}/WHEEL +1 -1
- pybiolib-1.2.1890.dist-info/entry_points.txt +2 -0
- biolib/_internal/llm_instructions/.github/instructions/style-react-ts.instructions.md +0 -22
- biolib/_internal/templates/init_template/.gitignore +0 -2
- biolib/_internal/types/__init__.py +0 -6
- biolib/_internal/types/resource.py +0 -18
- biolib/biolib_download_container.py +0 -38
- biolib/cli/download_container.py +0 -14
- biolib/utils/app_uri.py +0 -57
- pybiolib-1.2.883.dist-info/METADATA +0 -50
- pybiolib-1.2.883.dist-info/RECORD +0 -148
- pybiolib-1.2.883.dist-info/entry_points.txt +0 -3
- /biolib/{_internal/llm_instructions → _index}/__init__.py +0 -0
- /biolib/_internal/{llm_instructions → templates/copilot_template}/.github/instructions/general-app-knowledge.instructions.md +0 -0
- /biolib/_internal/{llm_instructions → templates/copilot_template}/.github/instructions/style-python.instructions.md +0 -0
- /biolib/_internal/{llm_instructions → templates/copilot_template}/.github/prompts/biolib_app_inputs.prompt.md +0 -0
- /biolib/_internal/{llm_instructions → templates/copilot_template}/.github/prompts/biolib_run_apps.prompt.md +0 -0
- /biolib/{_internal → _shared}/types/app.py +0 -0
- /biolib/{_internal → _shared}/types/data_record.py +0 -0
- /biolib/{_internal → _shared}/types/file_node.py +0 -0
- /biolib/{_internal → _shared}/types/push.py +0 -0
- /biolib/{_internal → _shared}/types/resource_permission.py +0 -0
- /biolib/{_internal → _shared}/types/result.py +0 -0
- /biolib/{_internal → _shared}/types/typing.py +0 -0
- {pybiolib-1.2.883.dist-info → pybiolib-1.2.1890.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def normalize_for_docker_tag(name: str) -> str:
|
|
5
|
+
if not name:
|
|
6
|
+
return ''
|
|
7
|
+
|
|
8
|
+
normalized = re.sub(r'[^a-z0-9-]', '-', name.lower())
|
|
9
|
+
|
|
10
|
+
normalized = re.sub(r'-+', '-', normalized)
|
|
11
|
+
normalized = normalized.strip('-')
|
|
12
|
+
|
|
13
|
+
return normalized
|
|
@@ -7,6 +7,11 @@ applyTo: '**'
|
|
|
7
7
|
- Unit tests are not necessary. Tests should instead be written as simple examples demonstrating the functionality of relevant functions.
|
|
8
8
|
- Always use 4 spaces for indentation.
|
|
9
9
|
- Function definitions should be typed as specifically as possible.
|
|
10
|
+
- Always explicitly type function parameters and return values.
|
|
11
|
+
- Avoid using the `Any` type unless absolutely necessary; use specific types instead.
|
|
12
|
+
- Write code with the expectation that a strict type checker will be used.
|
|
13
|
+
- Prefer failing fast with clear errors over silently providing fallback values.
|
|
14
|
+
- Always lock down the exact version of external dependencies (e.g., use `package==1.2.3` instead of `package>=1.2.3`).
|
|
10
15
|
|
|
11
16
|
# Code Comment Guidelines
|
|
12
17
|
- Code comments should only be added for complex logic or unintuitive code that is not adequately explained by the function names themselves.
|
biolib/_internal/templates/copilot_template/.github/instructions/style-react-ts.instructions.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "**/*.ts,**/*.tsx,**/package.json,**/vite.config.*,**/.yarnrc.yml,**/yarn.lock,**/gui/**"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Apply the [general coding guidelines](./style-general.instructions.md) to all code.
|
|
6
|
+
|
|
7
|
+
# General Project Guidelines
|
|
8
|
+
- Prefer using `export default function` over exporting at the end of the file.
|
|
9
|
+
|
|
10
|
+
# Package Management
|
|
11
|
+
- **Always use yarn instead of npm** for all package management operations
|
|
12
|
+
- Use `yarn install` instead of `npm install`
|
|
13
|
+
- Use `yarn add <package>` instead of `npm install <package>`
|
|
14
|
+
- Use `yarn remove <package>` instead of `npm uninstall <package>`
|
|
15
|
+
- Use `yarn dev` instead of `npm run dev`
|
|
16
|
+
- Use `yarn build` instead of `npm run build`
|
|
17
|
+
|
|
18
|
+
# Build Process
|
|
19
|
+
- BioLib GUI projects use Vite for building and development
|
|
20
|
+
- The build process compiles TypeScript and React into a single HTML file
|
|
21
|
+
- Always run `yarn build` to create the production build before deployment
|
|
22
|
+
- Use `yarn dev` for local development with hot reloading
|
|
23
|
+
|
|
24
|
+
# Configuration Files
|
|
25
|
+
- Respect the `.yarnrc.yml` configuration for yarn settings
|
|
26
|
+
- The `package.json` should specify `"packageManager": "yarn@4.6.0"` or similar
|
|
27
|
+
- Never modify yarn.lock manually - let yarn manage it automatically
|
|
28
|
+
|
|
29
|
+
# Dependencies
|
|
30
|
+
- Add new dependencies using `yarn add <package>` for runtime dependencies
|
|
31
|
+
- Add development dependencies using `yarn add -D <package>`
|
|
32
|
+
- Keep dependencies up to date but test thoroughly after updates
|
|
33
|
+
|
|
34
|
+
# TypeScript Guidelines
|
|
35
|
+
- Use TypeScript for all new code
|
|
36
|
+
- Follow functional programming principles where possible
|
|
37
|
+
- Use interfaces for data structures prefixed with I like `interface IRecord`
|
|
38
|
+
- Prefer immutable data (const, readonly)
|
|
39
|
+
- Use optional chaining (?.) and nullish coalescing (??) operators
|
|
40
|
+
|
|
41
|
+
# React Guidelines
|
|
42
|
+
- Use functional components with hooks
|
|
43
|
+
- Follow the React hooks rules (no conditional hooks)
|
|
44
|
+
- Prefer one component per file
|
|
45
|
+
- Use Tailwindcss for styling
|
|
46
|
+
- Extract props in components with object destructuring like `const { prop1, prop2 } = props;`
|
|
47
|
+
- Instantiate functional components with props like `export default function MyComponent(props: IProps) { ... }`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
mode: 'agent'
|
|
3
|
+
tools: ['githubRepo', 'codebase']
|
|
4
|
+
description: 'Handle onboarding and implementing code from a GitHub repository into a biolib application, with focus on creating easily editable and maintainable code structure.'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Main task
|
|
8
|
+
Your task is to help onboard and implement code from a GitHub repository into a biolib application. This involves understanding the repository structure, implementing the core functionality, and ensuring the code is easily editable for future iterations.
|
|
9
|
+
Generally, you can do this by adding the repository into an src folder as a submodule, and reading the README.md file to understand how to run the code.
|
|
10
|
+
You will then call the relevant functions or classes from the cloned repository in your biolib application
|
|
11
|
+
|
|
12
|
+
## Key requirements:
|
|
13
|
+
- Always ask the user for the GitHub repository if not already provided. Inform them that it needs to be in the format `author/repo_name`.
|
|
14
|
+
- Use the #githubRepo tool to examine the repository structure, README, and key files to understand the project.
|
|
15
|
+
- Focus on creating code that is easily editable and maintainable, as it's likely the implementation won't be perfect on the first attempt.
|
|
16
|
+
- Structure the code in a modular way that allows for easy modifications and improvements.
|
|
17
|
+
- Include clear comments for complex logic, but avoid over-commenting obvious code.
|
|
18
|
+
- Follow the existing biolib application patterns and conventions.
|
|
19
|
+
- Ensure all dependencies are properly specified in requirements.txt with versions locked down.
|
biolib/_internal/templates/{init_template → github_workflow_template}/.github/workflows/biolib.yml
RENAMED
|
@@ -9,8 +9,13 @@ jobs:
|
|
|
9
9
|
steps:
|
|
10
10
|
- uses: actions/checkout@v4
|
|
11
11
|
- name: Build
|
|
12
|
-
run:
|
|
12
|
+
run: BIOLIB_REPLACE_BUILD_COMMAND
|
|
13
13
|
- name: Push
|
|
14
|
-
run:
|
|
14
|
+
run: |
|
|
15
|
+
if [ "$GITHUB_REF_NAME" == "main" ]; then
|
|
16
|
+
biolib push BIOLIB_REPLACE_APP_URI
|
|
17
|
+
else
|
|
18
|
+
biolib push --dev BIOLIB_REPLACE_APP_URI:latest-dev
|
|
19
|
+
fi
|
|
15
20
|
env:
|
|
16
21
|
BIOLIB_TOKEN: ${{ secrets.BIOLIB_TOKEN }}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nodeLinker: node-modules
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import biolib from "./biolib-sdk";
|
|
3
|
+
|
|
4
|
+
export default function App() {
|
|
5
|
+
const [outputFileData, setOutputFileData] = useState<Uint8Array | null>(null);
|
|
6
|
+
const [loading, setLoading] = useState(true);
|
|
7
|
+
|
|
8
|
+
const loadOutputData = async () => {
|
|
9
|
+
setLoading(true);
|
|
10
|
+
try {
|
|
11
|
+
const data = await biolib.getOutputFileData("output.json");
|
|
12
|
+
setOutputFileData(data);
|
|
13
|
+
} catch (error) {
|
|
14
|
+
console.error("Error loading output data:", error);
|
|
15
|
+
setOutputFileData(null);
|
|
16
|
+
} finally {
|
|
17
|
+
setLoading(false);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
loadOutputData();
|
|
23
|
+
}, []);
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div className="min-h-screen bg-gray-100 flex items-center justify-center">
|
|
27
|
+
<div className="text-center max-w-2xl mx-auto p-8">
|
|
28
|
+
<h1 className="text-4xl font-bold mb-4">
|
|
29
|
+
Hello, BioLib!
|
|
30
|
+
</h1>
|
|
31
|
+
<p className="text-lg mb-2">
|
|
32
|
+
You have successfully set up your BioLib GUI application.
|
|
33
|
+
</p>
|
|
34
|
+
<p className="italic mb-6">
|
|
35
|
+
This is a simple React template with Tailwind CSS styling.
|
|
36
|
+
</p>
|
|
37
|
+
|
|
38
|
+
<div className="mt-8 p-4 bg-white rounded-lg shadow">
|
|
39
|
+
<h2 className="text-xl font-semibold mb-4">Example: Reading Output Files</h2>
|
|
40
|
+
{loading ? (
|
|
41
|
+
<p className="text-gray-500">Loading output.json...</p>
|
|
42
|
+
) : outputFileData ? (
|
|
43
|
+
<div className="p-3 bg-gray-50 rounded text-left">
|
|
44
|
+
<pre className="text-sm">{new TextDecoder().decode(outputFileData)}</pre>
|
|
45
|
+
</div>
|
|
46
|
+
) : (
|
|
47
|
+
<p className="text-red-500">Failed to load output.json</p>
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
|
|
3
|
+
FROM node:24.4.1-alpine3.21 AS gui_builder
|
|
4
|
+
|
|
5
|
+
WORKDIR /home/biolib/
|
|
6
|
+
|
|
7
|
+
RUN corepack enable
|
|
8
|
+
COPY .yarnrc.yml .
|
|
9
|
+
COPY package.json .
|
|
10
|
+
COPY vite.config.mts .
|
|
11
|
+
RUN yarn install
|
|
12
|
+
|
|
13
|
+
COPY gui gui
|
|
14
|
+
RUN yarn build
|
|
15
|
+
|
|
16
|
+
FROM python:3.13.5-slim
|
|
17
|
+
WORKDIR /home/biolib/
|
|
18
|
+
|
|
19
|
+
COPY requirements.txt .
|
|
20
|
+
RUN pip install --no-cache-dir -r requirements.txt
|
|
21
|
+
|
|
22
|
+
COPY run.sh .
|
|
23
|
+
COPY run.py .
|
|
24
|
+
|
|
25
|
+
RUN mkdir output
|
|
26
|
+
|
|
27
|
+
COPY --from=gui_builder /home/biolib/gui/dist/index.html result.html
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
interface IGetFileFromDataRecordOptions {
|
|
2
|
+
uri: string;
|
|
3
|
+
path: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
interface IRunJobPayload {
|
|
7
|
+
appUri: string;
|
|
8
|
+
arguments: string[];
|
|
9
|
+
files: Record<string, { data: Uint8Array }>;
|
|
10
|
+
temporaryClientSecrets?: Record<string, string>;
|
|
11
|
+
openResult?: boolean | 'currentWindow' | 'newTab';
|
|
12
|
+
blocking?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface IJobProgress {
|
|
16
|
+
logMessage?: string;
|
|
17
|
+
systemLogMessage?: string;
|
|
18
|
+
jobId: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface IJobResult {
|
|
22
|
+
exit_code: number;
|
|
23
|
+
stderr: Uint8Array;
|
|
24
|
+
stdout: Uint8Array;
|
|
25
|
+
files: Record<string, { data: Uint8Array }>;
|
|
26
|
+
jobId: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface IPendingJobResult {
|
|
30
|
+
jobId: string;
|
|
31
|
+
authToken: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface IBioLibGlobals {
|
|
35
|
+
getFileDataFromDataRecord: (options: IGetFileFromDataRecordOptions) => Promise<Uint8Array>;
|
|
36
|
+
getOutputFileData: (path: string) => Promise<Uint8Array>;
|
|
37
|
+
listOutputFilePaths: () => Promise<string[]>;
|
|
38
|
+
runJob: (payload: IRunJobPayload, jobProgressHandler?: (jobProgress: IJobProgress) => void) => Promise<IJobResult | IPendingJobResult>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
declare global {
|
|
42
|
+
const biolib: IBioLibGlobals;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// DO NOT MODIFY: Development data files are injected at build time from gui/dev-data/ folder
|
|
46
|
+
const DEV_DATA_FILES: Record<string, string> = {};
|
|
47
|
+
|
|
48
|
+
const devSdkBioLib: IBioLibGlobals = {
|
|
49
|
+
getFileDataFromDataRecord: async (_options: IGetFileFromDataRecordOptions): Promise<Uint8Array> => {
|
|
50
|
+
throw new Error('getFileDataFromDataRecord is not available in local development mode.');
|
|
51
|
+
},
|
|
52
|
+
getOutputFileData: async (path: string): Promise<Uint8Array> => {
|
|
53
|
+
console.log(`[SDK] getOutputFileData called with path: ${path}`);
|
|
54
|
+
|
|
55
|
+
const normalizedPath = path.startsWith('/') ? path.slice(1) : path;
|
|
56
|
+
|
|
57
|
+
if (typeof DEV_DATA_FILES !== 'undefined' && normalizedPath in DEV_DATA_FILES) {
|
|
58
|
+
const base64Data = DEV_DATA_FILES[normalizedPath];
|
|
59
|
+
const binaryString = atob(base64Data);
|
|
60
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
61
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
62
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
63
|
+
}
|
|
64
|
+
return bytes;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
throw new Error(`File not found: ${path}. Add this file to the dev-data/ folder for local development.`);
|
|
68
|
+
},
|
|
69
|
+
listOutputFilePaths: async (): Promise<string[]> => {
|
|
70
|
+
throw new Error('listOutputFilePaths is not available in local development mode.');
|
|
71
|
+
},
|
|
72
|
+
runJob: async (_payload: IRunJobPayload, _jobProgressHandler?: (jobProgress: IJobProgress) => void): Promise<IJobResult | IPendingJobResult> => {
|
|
73
|
+
throw new Error('runJob is not available in local development mode.');
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const biolib: IBioLibGlobals =
|
|
78
|
+
process.env.NODE_ENV === "development"
|
|
79
|
+
? devSdkBioLib
|
|
80
|
+
: (window as any).biolib;
|
|
81
|
+
|
|
82
|
+
export default biolib;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<link href="index.css" rel="stylesheet">
|
|
7
|
+
<title>BIOLIB_REPLACE_APP_NAME</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body style="overflow: hidden; background: white">
|
|
10
|
+
<div id="root"></div>
|
|
11
|
+
<script type="module" src="index.tsx"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "biolib_replace_app_name",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "tsc --noEmit -p gui/tsconfig.json && vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"react": "18.3.1",
|
|
13
|
+
"react-dom": "18.3.1"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@tailwindcss/vite": "4.0.14",
|
|
17
|
+
"@types/node": "20.17.10",
|
|
18
|
+
"@types/react": "18.3.3",
|
|
19
|
+
"@types/react-dom": "18.3.0",
|
|
20
|
+
"@vitejs/plugin-react": "4.2.1",
|
|
21
|
+
"tailwindcss": "4.0.14",
|
|
22
|
+
"typescript": "5.2.2",
|
|
23
|
+
"vite": "5.3.4",
|
|
24
|
+
"vite-plugin-singlefile": "2.0.2"
|
|
25
|
+
},
|
|
26
|
+
"packageManager": "yarn@4.6.0"
|
|
27
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"composite": true,
|
|
4
|
+
"target": "ES2020",
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
|
|
9
|
+
/* Bundler mode */
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"allowImportingTsExtensions": true,
|
|
12
|
+
"verbatimModuleSyntax": true,
|
|
13
|
+
"moduleDetection": "force",
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
"jsx": "react-jsx",
|
|
16
|
+
|
|
17
|
+
/* Linting */
|
|
18
|
+
"strict": true,
|
|
19
|
+
"noUnusedLocals": true,
|
|
20
|
+
"noUnusedParameters": true,
|
|
21
|
+
"noFallthroughCasesInSwitch": true
|
|
22
|
+
},
|
|
23
|
+
"include": ["."]
|
|
24
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
export function devDataPlugin(): Plugin {
|
|
6
|
+
let isDev = false;
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
name: 'dev-data-plugin',
|
|
10
|
+
configResolved(config) {
|
|
11
|
+
isDev = config.mode === 'development';
|
|
12
|
+
},
|
|
13
|
+
transform(code: string, id: string) {
|
|
14
|
+
if (id.endsWith('biolib-sdk.ts')) {
|
|
15
|
+
let injectedCode: string;
|
|
16
|
+
|
|
17
|
+
if (isDev) {
|
|
18
|
+
const devDataDir = path.join(__dirname, 'dev-data');
|
|
19
|
+
const devDataMap: Record<string, string> = {};
|
|
20
|
+
|
|
21
|
+
if (fs.existsSync(devDataDir)) {
|
|
22
|
+
const entries = fs.readdirSync(devDataDir, { recursive: true });
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
const relativePath = entry.toString();
|
|
25
|
+
const fullPath = path.join(devDataDir, relativePath);
|
|
26
|
+
if (fs.statSync(fullPath).isFile()) {
|
|
27
|
+
const content = fs.readFileSync(fullPath);
|
|
28
|
+
const base64Content = content.toString('base64');
|
|
29
|
+
devDataMap[relativePath] = base64Content;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const devDataJson = JSON.stringify(devDataMap);
|
|
35
|
+
injectedCode = code.replace(
|
|
36
|
+
"const DEV_DATA_FILES = {};",
|
|
37
|
+
`const DEV_DATA_FILES = ${devDataJson};`
|
|
38
|
+
);
|
|
39
|
+
} else {
|
|
40
|
+
injectedCode = code;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
code: injectedCode,
|
|
45
|
+
map: null
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import react from "@vitejs/plugin-react";
|
|
3
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
4
|
+
import { viteSingleFile } from "vite-plugin-singlefile";
|
|
5
|
+
import { devDataPlugin } from "./gui/vite-plugin-dev-data";
|
|
6
|
+
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
root: "gui",
|
|
9
|
+
plugins: [react(), tailwindcss(), devDataPlugin(), viteSingleFile()],
|
|
10
|
+
});
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
|
|
1
3
|
FROM python:3.13.3-slim
|
|
2
4
|
WORKDIR /home/biolib/
|
|
3
5
|
|
|
6
|
+
RUN pip install --no-cache-dir uv
|
|
7
|
+
|
|
4
8
|
COPY requirements.txt .
|
|
5
|
-
RUN pip install --no-cache-dir -r requirements.txt
|
|
9
|
+
RUN uv pip install --no-cache-dir --system -r requirements.txt
|
|
6
10
|
|
|
7
11
|
COPY run.sh .
|
|
8
12
|
COPY run.py .
|
|
@@ -2,20 +2,11 @@ import argparse
|
|
|
2
2
|
|
|
3
3
|
from biolib.sdk import Runtime
|
|
4
4
|
|
|
5
|
+
parser = argparse.ArgumentParser(description='Process some biological sequences.')
|
|
6
|
+
parser.add_argument('--input', type=str, required=True, help='Input protein sequences')
|
|
7
|
+
args = parser.parse_args()
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
parser.add_argument('--input', type=str, required=True, help='Input protein sequences')
|
|
9
|
-
return parser.parse_args()
|
|
9
|
+
# update the BioLib result name based on the provided file
|
|
10
|
+
Runtime.set_result_name_from_file(args.input)
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
def main(args):
|
|
13
|
-
sequence = args.input
|
|
14
|
-
# Add your processing logic here
|
|
15
|
-
print(f'Received sequence: {sequence}')
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if __name__ == '__main__':
|
|
19
|
-
args = parse_args()
|
|
20
|
-
Runtime.set_result_name_prefix_from_fasta(args.input)
|
|
21
|
-
main(args)
|
|
12
|
+
print(f'Processing input file {args.input}...')
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import os
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def init_template():
|
|
4
|
+
def init_template() -> str:
|
|
5
5
|
return os.path.join(os.path.dirname(__file__), 'init_template')
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def copilot_template() -> str:
|
|
9
|
+
return os.path.join(os.path.dirname(__file__), 'copilot_template')
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def gui_template() -> str:
|
|
13
|
+
return os.path.join(os.path.dirname(__file__), 'gui_template')
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def dashboard_template() -> str:
|
|
17
|
+
return os.path.join(os.path.dirname(__file__), 'dashboard_template')
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def gitignore_template() -> str:
|
|
21
|
+
return os.path.join(os.path.dirname(__file__), 'gitignore_template')
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def github_workflow_template() -> str:
|
|
25
|
+
return os.path.join(os.path.dirname(__file__), 'github_workflow_template')
|
|
@@ -1,5 +1,32 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import shutil
|
|
1
3
|
import time
|
|
2
4
|
import uuid
|
|
5
|
+
from fnmatch import fnmatch
|
|
6
|
+
|
|
7
|
+
from biolib.biolib_binary_format.utils import LazyLoadedFile
|
|
8
|
+
from biolib.typing_utils import Callable, List, Union, cast
|
|
9
|
+
|
|
10
|
+
PathFilter = Union[str, Callable[[str], bool]]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def filter_lazy_loaded_files(files: List[LazyLoadedFile], path_filter: PathFilter) -> List[LazyLoadedFile]:
|
|
14
|
+
if not (isinstance(path_filter, str) or callable(path_filter)):
|
|
15
|
+
raise Exception('Expected path_filter to be a string or a function')
|
|
16
|
+
|
|
17
|
+
if callable(path_filter):
|
|
18
|
+
return list(filter(lambda x: path_filter(x.path), files)) # type: ignore
|
|
19
|
+
|
|
20
|
+
glob_filter = cast(str, path_filter)
|
|
21
|
+
|
|
22
|
+
# since all file paths start with /, make sure filter does too
|
|
23
|
+
if not glob_filter.startswith('/'):
|
|
24
|
+
glob_filter = '/' + glob_filter
|
|
25
|
+
|
|
26
|
+
def _filter_function(file: LazyLoadedFile) -> bool:
|
|
27
|
+
return fnmatch(file.path, glob_filter)
|
|
28
|
+
|
|
29
|
+
return list(filter(_filter_function, files))
|
|
3
30
|
|
|
4
31
|
|
|
5
32
|
def open_browser_window_from_notebook(url_to_open: str) -> None:
|
|
@@ -16,3 +43,23 @@ def open_browser_window_from_notebook(url_to_open: str) -> None:
|
|
|
16
43
|
display(Javascript(f'window.open("{url_to_open}");'), display_id=display_id)
|
|
17
44
|
time.sleep(1)
|
|
18
45
|
update_display(Javascript(''), display_id=display_id)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def base64_encode_string(input_str: str) -> str:
|
|
49
|
+
input_bytes = input_str.encode('utf-8')
|
|
50
|
+
base64_bytes = base64.b64encode(input_bytes)
|
|
51
|
+
base64_str = base64_bytes.decode('utf-8')
|
|
52
|
+
return base64_str
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def decode_base64_string(base64_str: str) -> str:
|
|
56
|
+
base64_bytes = base64_str.encode('utf-8')
|
|
57
|
+
input_bytes = base64.b64decode(base64_bytes)
|
|
58
|
+
input_str = input_bytes.decode('utf-8')
|
|
59
|
+
return input_str
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_pip_command() -> str:
|
|
63
|
+
if shutil.which('uv'):
|
|
64
|
+
return 'uv pip'
|
|
65
|
+
return 'pip'
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import binascii
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any, Dict
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class JwtDecodeError(Exception):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def decode_jwt_without_checking_signature(jwt: str) -> Dict[str, Any]:
|
|
12
|
+
jwt_bytes = jwt.encode('utf-8')
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
signing_input, _ = jwt_bytes.rsplit(b'.', 1)
|
|
16
|
+
header_segment, payload_segment = signing_input.split(b'.', 1)
|
|
17
|
+
except ValueError as error:
|
|
18
|
+
raise JwtDecodeError('Not enough segments') from error
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
header_data = base64.urlsafe_b64decode(header_segment)
|
|
22
|
+
except (TypeError, binascii.Error) as error:
|
|
23
|
+
raise JwtDecodeError('Invalid header padding') from error
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
header = json.loads(header_data)
|
|
27
|
+
except ValueError as error:
|
|
28
|
+
raise JwtDecodeError(f'Invalid header string: {error}') from error
|
|
29
|
+
|
|
30
|
+
if not isinstance(header, dict):
|
|
31
|
+
raise JwtDecodeError('Invalid header string: must be a json object')
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
payload_data = base64.urlsafe_b64decode(payload_segment)
|
|
35
|
+
except (TypeError, binascii.Error) as error:
|
|
36
|
+
raise JwtDecodeError('Invalid payload padding') from error
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
payload = json.loads(payload_data)
|
|
40
|
+
except ValueError as error:
|
|
41
|
+
raise JwtDecodeError(f'Invalid payload string: {error}') from error
|
|
42
|
+
|
|
43
|
+
if not isinstance(payload, dict):
|
|
44
|
+
raise JwtDecodeError('Invalid payload string: must be a json object')
|
|
45
|
+
|
|
46
|
+
return dict(header=header, payload=payload)
|