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

feat: Python venv support #97

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
42 changes: 21 additions & 21 deletions .ghjk/lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,29 @@
"portRef": "[email protected]",
"specifiedVersion": false
},
"bciqj4p5hoqweghbuvz52rupja7sqze34z63dd62nz632c5zxikv6ezy": {
"version": "1.34",
"buildDepConfigs": {},
"portRef": "[email protected]",
"specifiedVersion": false
},
"bciqe6fwheayositrdk7rkr2ngdr4wizldakex23tgivss7w6z7g3q3y": {
"version": "v1.4.8,",
"buildDepConfigs": {},
"portRef": "[email protected]",
"specifiedVersion": false
},
"bciqfvlwwndlfuqibybkgee3fgt7cst5ltpztmm3by6hib5veial5spy": {
"version": "v1.44.2",
"buildDepConfigs": {},
"portRef": "[email protected]",
"specifiedVersion": true
},
"bciqao2s3r3r33ruox4qknfrxqrmemuccxn64dze2ylojrzp2bwvt4ji": {
"version": "3.7.1",
"version": "3.8.0",
"buildDepConfigs": {
"cpy_bs_ghrel": {
"version": "3.12.4",
"version": "3.12.5",
"buildDepConfigs": {
"tar_aa": {
"version": "1.34",
Expand All @@ -45,7 +63,7 @@
"specifiedVersion": false
},
"bciqij3g6mmbjn4a6ps4eipcy2fmw2zumgv5a3gbxycthroffihwquoi": {
"version": "3.12.4",
"version": "3.12.5",
"buildDepConfigs": {
"tar_aa": {
"version": "1.34",
Expand All @@ -62,24 +80,6 @@
},
"portRef": "[email protected]",
"specifiedVersion": false
},
"bciqj4p5hoqweghbuvz52rupja7sqze34z63dd62nz632c5zxikv6ezy": {
"version": "1.34",
"buildDepConfigs": {},
"portRef": "[email protected]",
"specifiedVersion": false
},
"bciqe6fwheayositrdk7rkr2ngdr4wizldakex23tgivss7w6z7g3q3y": {
"version": "v1.4.8,",
"buildDepConfigs": {},
"portRef": "[email protected]",
"specifiedVersion": false
},
"bciqfvlwwndlfuqibybkgee3fgt7cst5ltpztmm3by6hib5veial5spy": {
"version": "v1.44.2",
"buildDepConfigs": {},
"portRef": "[email protected]",
"specifiedVersion": true
}
}
},
Expand Down
1 change: 1 addition & 0 deletions examples/kitchen/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.venv/
7 changes: 6 additions & 1 deletion examples/kitchen/ghjk.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { stdDeps } from "../../files/mod.ts";
import { file } from "../../mod.ts";
import * as ports from "../../ports/mod.ts";
import { pyEnv } from "../../std/py.ts";

const ghjk = file({
// configre an empty env so that no ports are avail by default in our workdir
Expand Down Expand Up @@ -106,7 +107,8 @@ env("python")
ports.cpy_bs({ version: "3.8.18", releaseTag: "20240224" }),
ports.tar(),
ports.zstd(),
);
)
.mixin(pyEnv());

env("dev")
// we can inherit from many envs
Expand All @@ -120,3 +122,6 @@ env("dev")
workingDir: "..",
fn: ($) => $`ls`,
}));

env("venv")
.inherit(["python"]);
139 changes: 139 additions & 0 deletions files/MergedEnvs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { deep_eql } from "../deps/common.ts";
import {
DynamicPosixDirProvision,
PosixDirProvision,
} from "../modules/envs/types.ts";
import getLogger from "../utils/logger.ts";

const logger = getLogger(import.meta);

type Var =
| { kind: "static"; value: string; parentName: string }
| { kind: "dynamic"; taskId: string; parentName: string };

export class ParentEnvs {
#childName: string;
#vars: Map<string, Var> = new Map();
#posixDirs: Array<PosixDirProvision> = [];
#dynamicPosixDirs: Array<DynamicPosixDirProvision> = [];
#installs: Set<string> = new Set();
#onEnterHooks: string[] = [];
#onExitHooks: string[] = [];
#allowedBuildDeps: Map<string, [string, string]> = new Map();

constructor(childName: string) {
this.#childName = childName;
}

addHooks(onEnterHooks: string[], onExitHooks: string[]) {
this.#onEnterHooks.push(...onEnterHooks);
this.#onExitHooks.push(...onExitHooks);
}

mergeVars(parentName: string, vars: Record<string, string>) {
for (const [key, value] of Object.entries(vars)) {
const conflict = this.#vars.get(key);

if (
conflict && !(conflict.kind === "static" && conflict.value === value)
) {
logger.warn(
"environment variable conflict on multiple env inheritance, parent 2 was chosen",
{
child: this.#childName,
Natoandro marked this conversation as resolved.
Show resolved Hide resolved
parent1: conflict.parentName,
parent2: parentName,
variable: key,
},
);
}

this.#vars.set(key, { kind: "static", value, parentName });
}
}

mergeDynVars(parentName: string, dynVars: Record<string, string>) {
for (const [key, taskId] of Object.entries(dynVars)) {
const conflict = this.#vars.get(key);

if (
conflict && !(conflict.kind === "dynamic" && conflict.taskId === taskId)
) {
logger.warn(
"dynamic environment variable conflict on multiple env inheritance, parent 2 was chosen",
{
child: this.#childName,
parent1: conflict.parentName,
parent2: parentName,
variable: key,
},
);
}

this.#vars.set(key, { kind: "dynamic", taskId, parentName });
}
}

mergePosixDirs(
posixDirs: Array<PosixDirProvision>,
dynamicPosixDirs: Array<DynamicPosixDirProvision>,
) {
this.#posixDirs.push(...posixDirs);
this.#dynamicPosixDirs.push(...dynamicPosixDirs);
}

mergeInstalls(
parentName: string,
installs: Set<string>,
allowedBuildDeps: Record<string, string>,
) {
this.#installs = this.#installs.union(installs);

for (const [key, val] of Object.entries(allowedBuildDeps)) {
const conflict = this.#allowedBuildDeps.get(key);
if (conflict && !deep_eql(val, conflict[0])) {
logger.warn(
"allowedBuildDeps conflict on multiple env inheritance, parent 2 was chosen",
{
child: this.#childName,
parent1: conflict[1],
parent2: parentName,
variable: key,
},
);
}

this.#allowedBuildDeps.set(key, [val, parentName]);
}
}

finalize() {
const vars: Record<string, string> = {};
const dynVars: Record<string, string> = {};

for (const [key, value] of this.#vars) {
if (value.kind === "static") {
vars[key] = value.value;
} else {
dynVars[key] = value.taskId;
}
}

return {
installSet: {
installs: this.#installs,
allowedBuildDeps: Object.fromEntries(
[...this.#allowedBuildDeps.entries()].map((
[key, [val]],
) => [key, val]),
),
},
onEnterHookTasks: this.#onEnterHooks,
onExitHookTasks: this.#onExitHooks,
vars,
dynVars,
posixDirs: this.#posixDirs,
dynamicPosixDirs: this.#dynamicPosixDirs,
};
}
Natoandro marked this conversation as resolved.
Show resolved Hide resolved
}
Loading
Loading