Repository: pluto-lang/pluto (language: python)

Issue:
Version Packages
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.


# Releases
## @plutolang/cli@0.2.10

### Patch Changes

-   62a0009: feat: instantiate resource infrastructure classes asynchronously within the base class of each resource
-   Updated dependencies [62a0009]
    -   @plutolang/simulator-adapter@0.2.9
    -   @plutolang/static-generator@0.2.8
    -   @plutolang/pulumi-adapter@0.2.9
    -   @plutolang/base@0.2.8
    -   @plutolang/static-deducer@0.2.8
    -   @plutolang/graphviz-generator@0.2.8

## @plutolang/pulumi-adapter@0.2.9

### Patch Changes

-   62a0009: feat: instantiate resource infrastructure classes asynchronously within the base class of each resource
-   Updated dependencies [62a0009]
    -   @plutolang/base@0.2.8

## @plutolang/simulator-adapter@0.2.9

### Patch Changes

-   62a0009: feat: instantiate resource infrastructure classes asynchronously within the base class of each resource
-   Updated dependencies [62a0009]
    -   @plutolang/pluto-infra@0.2.9
    -   @plutolang/pluto@0.2.8
    -   @plutolang/base@0.2.8

## @plutolang/static-deducer@0.2.8

### Patch Changes

-   Updated dependencies [62a0009]
    -   @plutolang/base@0.2.8

## @plutolang/graphviz-generator@0.2.8

### Patch Changes

-   Updated dependencies [62a0009]
    -   @plutolang/base@0.2.8

## @plutolang/static-generator@0.2.8

### Patch Changes

-   62a0009: feat: instantiate resource infrastructure classes asynchronously within the base class of each resource
-   Updated dependencies [62a0009]
    -   @plutolang/base@0.2.8

## @plutolang/base@0.2.8

### Patch Changes

-   62a0009: feat: instantiate resource infrastructure classes asynchronously within the base class of each resource

## @plutolang/pluto@0.2.8

### Patch Changes

-   62a0009: feat: instantiate resource infrastructure classes asynchronously within the base class of each resource
-   Updated dependencies [62a0009]
    -   @plutolang/base@0.2.8

## @plutolang/pluto-infra@0.2.9

### Patch Changes

-   62a0009: feat: instantiate resource infrastructure classes asynchronously within the base class of each resource
-   Updated dependencies [62a0009]
    -   @plutolang/pluto@0.2.8
    -   @plutolang/base@0.2.8



Discussion / hints:

Fix patch:
diff --git a/.changeset/lemon-colts-sniff.md b/.changeset/lemon-colts-sniff.md
new file mode 100644
index 00000000..ccaf50ba
--- /dev/null
+++ b/.changeset/lemon-colts-sniff.md
@@ -0,0 +1,7 @@
+---
+"@plutolang/pyright-deducer": patch
+---
+
+fix(deducer): correct environment variable access code format
+
+The code generation for environment variable access within the infrastructure code, which is written in TypeScript, was incorrectly producing Python format. This change ensures the code is now generated in the proper TypeScript format, resolving the error.
diff --git a/components/deducers/python-pyright/src/custom-infra-fn/evaluate-graph.ts b/components/deducers/python-pyright/src/custom-infra-fn/evaluate-graph.ts
index 3126a656..1fba741a 100644
--- a/components/deducers/python-pyright/src/custom-infra-fn/evaluate-graph.ts
+++ b/components/deducers/python-pyright/src/custom-infra-fn/evaluate-graph.ts
@@ -9,7 +9,7 @@ import { ClassType, TypeCategory } from "pyright-internal/dist/analyzer/types";
 import { TypeEvaluator } from "pyright-internal/dist/analyzer/typeEvaluatorTypes";
 import { ArgumentNode, CallNode, ParseNodeType } from "pyright-internal/dist/parser/parseNodes";
 import { ValueEvaluator } from "../value-evaluator/value-evaluator";
-import { Value, ValueType, genEnvVarAccessTextForPython } from "../value-evaluator";
+import { Value, ValueType, genEnvVarAccessTextForTypeScript } from "../value-evaluator";
 import {
   Argument,
   ArgumentType,
@@ -157,7 +157,7 @@ class GraphEvaluator {
           if (arg.node) {
             const argValue = this.valueEvaluator.evaluate(arg.node, this.argumentFillings);
             const stringified = Value.toJson(argValue, {
-              genEnvVarAccessText: genEnvVarAccessTextForPython,
+              genEnvVarAccessText: genEnvVarAccessTextForTypeScript,
             });
             return JSON.parse(stringified);
           }
@@ -392,8 +392,11 @@ class GraphEvaluator {
     if (argument.node) {
       const argValue = this.valueEvaluator.evaluate(argument.node, this.argumentFillings);
       if (argValue.valueType !== ValueType.None) {
+        // The generator will use the constructed argument to generate the infrastructure code,
+        // which is in TypeScript. Therefore, we need to generate the environment variable access
+        // text in TypeScript format.
         content = Value.toJson(argValue, {
-          genEnvVarAccessText: genEnvVarAccessTextForPython,
+          genEnvVarAccessText: genEnvVarAccessTextForTypeScript,
         });
       }
     }
diff --git a/components/deducers/python-pyright/src/value-evaluator/value-types.ts b/components/deducers/python-pyright/src/value-evaluator/value-types.ts
index 33e34d3a..5857d636 100644
--- a/components/deducers/python-pyright/src/value-evaluator/value-types.ts
+++ b/components/deducers/python-pyright/src/value-evaluator/value-types.ts
@@ -133,6 +133,11 @@ export namespace Value {
      * Whether to contain the module name in the output string. @default true
      */
     containModuleName?: boolean;
+    /**
+     * Generate the text for accessing the environment variable. If not provided, it will try to get
+     * the value directly from the environment variable.
+     */
+    genEnvVarAccessText?: (value: EnvVarAccessValue) => string;
   }
 
   export function toString(value: Value, options: ToStringOptions = {}): string {
@@ -165,11 +170,17 @@ export namespace Value {
         return `${type}(${params})`;
       },
       [ValueType.EnvVarAccess]: (value: EnvVarAccessValue) => {
+        if (options.genEnvVarAccessText) {
+          return options.genEnvVarAccessText(value);
+        }
+
         const envVarName = value.envVarName;
-        if (value.defaultEnvVarValue) {
-          return `os.environ.get("${envVarName}", "${value.defaultEnvVarValue}")`;
+        const envVarValue = process.env[envVarName] ?? value.defaultEnvVarValue;
+        if (envVarValue) {
+          return `"${envVarValue}"`;
+        } else {
+          return "null";
         }
-        return `os.environ.get("${envVarName}")`;
       },
     };
 


Test patch:
diff --git a/components/deducers/python-pyright/src/test/value-evaluator/basic.test.ts b/components/deducers/python-pyright/src/test/value-evaluator/basic.test.ts
index 9204eb4c..0ccbb947 100644
--- a/components/deducers/python-pyright/src/test/value-evaluator/basic.test.ts
+++ b/components/deducers/python-pyright/src/test/value-evaluator/basic.test.ts
@@ -5,7 +5,7 @@ import {
   ParseNodeType,
 } from "pyright-internal/dist/parser/parseNodes";
 import * as TextUtils from "../../text-utils";
-import { Value, ValueEvaluator } from "../../value-evaluator";
+import { genEnvVarAccessTextForPython, Value, ValueEvaluator } from "../../value-evaluator";
 import { DATACLASS_DEF } from "./dataclass.test";
 import { testInlineCode, testPyFile } from "./utils";
 
@@ -181,12 +181,16 @@ var_dataclass = Base("name", common_var_1)
             expect(Value.toString(value)).toEqual("2");
             break;
           case "var_tuple":
-            expect(Value.toString(value)).toEqual(
+            expect(
+              Value.toString(value, { genEnvVarAccessText: genEnvVarAccessTextForPython })
+            ).toEqual(
               '(1, 2, tmp.Model(nullable=None, tup=(1, 2, 3), base=tmp.Base(name="name", age=25), gender=os.environ.get("KEY")))'
             );
             break;
           case "var_dict":
-            expect(Value.toString(value)).toEqual(
+            expect(
+              Value.toString(value, { genEnvVarAccessText: genEnvVarAccessTextForPython })
+            ).toEqual(
               '{"key": 1, "key2": 2, "key3": tmp.Model(nullable=None, tup=(1, 2, 3), base=tmp.Base(name="name", age=25), gender=os.environ.get("KEY"))}'
             );
             break;