diff --git a/components/deducers/python-pyright/src/code-extractor.ts b/components/deducers/python-pyright/src/code-extractor.ts
new file mode 100644
index 00000000..6c501d9a
--- /dev/null
+++ b/components/deducers/python-pyright/src/code-extractor.ts
@@ -0,0 +1,544 @@
+import assert from "node:assert";
+import { SourceFile } from "pyright-internal/dist/analyzer/sourceFile";
+import { TypeEvaluator } from "pyright-internal/dist/analyzer/typeEvaluatorTypes";
+import {
+  ArgumentNode,
+  CallNode,
+  ClassNode,
+  ExpressionNode,
+  FunctionNode,
+  ImportAsNode,
+  ImportFromAsNode,
+  LambdaNode,
+  MemberAccessNode,
+  NameNode,
+  ParseNode,
+  ParseNodeType,
+} from "pyright-internal/dist/parser/parseNodes";
+import { Scope } from "pyright-internal/dist/analyzer/scope";
+import { DeclarationType } from "pyright-internal/dist/analyzer/declaration";
+import { ParseTreeWalker } from "pyright-internal/dist/analyzer/parseTreeWalker";
+import * as AnalyzerNodeInfo from "pyright-internal/dist/analyzer/analyzerNodeInfo";
+import { getBuiltInScope, getScopeForNode } from "pyright-internal/dist/analyzer/scopeUtils";
+import * as TextUtils from "./text-utils";
+import * as TypeUtils from "./type-utils";
+import * as TypeConsts from "./type-consts";
+import * as ScopeUtils from "./scope-utils";
+import { SpecialNodeMap } from "./special-node-map";
+import { Value, ValueEvaluator } from "./value-evaluator";
+
+export interface CodeSegment {
+  readonly node: ParseNode;
+  /**
+   * If a code segment hasn't an exportable name, it means the segment is not a direct exportable
+   * expression, such as a lambda function or a function call. If we want to export the code
+   * segment, we need to assign it to a variable, and then export the variable.
+   */
+  readonly exportableName?: string;
+  /**
+   * The code after being transformed from a node expression, including constant folding, etc. It
+   * contains only one code segment related to the `node`, such as a variable assignment, a function
+   * call, a class definition, etc. And it dependencies are specified in the `dependencies`.
+   */
+  readonly code: string;
+  /**
+   * The `dependencies` includes the variables, functions, classes, etc., that are accessed in the
+   * current node.
+   */
+  readonly dependencies: CodeSegment[];
+}
+
+// eslint-disable-next-line @typescript-eslint/no-namespace
+export namespace CodeSegment {
+  export function toString(segment: CodeSegment): string {
+    const extractedNodeIds: Set<number> = new Set();
+    function concatCodeRecursively(segment: CodeSegment): string {
+      const depsCode = segment.dependencies.map((dep) => concatCodeRecursively(dep)).join("\n");
+
+      if (extractedNodeIds.has(segment.node.id)) {
+        // Avoid extracting the same node multiple times.
+        return depsCode;
+      }
+
+      extractedNodeIds.add(segment.node.id);
+      return `${depsCode}\n${segment.code}`;
+    }
+
+    return concatCodeRecursively(segment);
+  }
+}
+
+/**
+ * Extract the code and its dependencies of one expression.
+ */
+export class CodeExtractor {
+  constructor(
+    private readonly typeEvaluator: TypeEvaluator,
+    private readonly specialNodeMap: SpecialNodeMap<CallNode>,
+    private readonly valueEvaluator: ValueEvaluator
+  ) {}
+
+  /**
+   * Extract the code and its dependencies of one expression, such as a variable, a function call,
+   * etc.
+   * @param node - The expression node.
+   * @param sourceFile - The source file where the expression node is located.
+   */
+  public extractExpressionWithDependencies(
+    node: ExpressionNode,
+    sourceFile: SourceFile
+  ): CodeSegment {
+    let segment: CodeSegment | undefined;
+    switch (node.nodeType) {
+      case ParseNodeType.Lambda:
+        segment = this.extractLambdaWithDependencies(node, sourceFile);
+        break;
+      case ParseNodeType.Name:
+        segment = this.extractNameNodeWithDependencies(node, sourceFile);
+        break;
+      case ParseNodeType.Call:
+        segment = this.extractCallWithDependencies(node, sourceFile);
+        break;
+      case ParseNodeType.MemberAccess:
+        segment = this.extractMemberAccessWithDependencies(node, sourceFile);
+        break;
+      case ParseNodeType.Number:
+      case ParseNodeType.StringList:
+        segment = {
+          node,
+          code: TextUtils.getTextOfNode(node, sourceFile)!,
+          dependencies: [],
+        };
+        break;
+      default:
+        throw new Error(`Unsupported node type: ${node.nodeType}`);
+    }
+    return segment;
+  }
+
+  private extractLambdaWithDependencies(
+    lambdaNode: LambdaNode,
+    sourceFile: SourceFile
+  ): CodeSegment {
+    const nodeText = TextUtils.getTextOfNode(lambdaNode, sourceFile);
+
+    const lambdaScope = getScopeForNode(lambdaNode.expression);
+    if (!lambdaScope) {
+      throw new Error(`No scope found for this lambda function '${nodeText}'.`);
+    }
+
+    // Find the symbols that are used in the lambda function but defined outside of it.
+    const walker = new OutsideSymbolFinder(this.typeEvaluator, lambdaScope);
+    walker.walk(lambdaNode);
+
+    // Get the dependencies of the lambda function.
+    const dependencies: CodeSegment[] = [];
+    for (const nameNode of walker.nameNodes) {
+      const dep = this.extractNameNodeWithDependencies(nameNode, sourceFile);
+      dependencies.push(dep);
+    }
+
+    return {
+      node: lambdaNode,
+      code: nodeText!,
+      dependencies,
+    };
+  }
+
+  /**
+   * The name node can represent various types of nodes, like variables, functions, classes, etc.
+   * When dealing with the name node, we extract what it refers to — the declaration — rather than the
+   * node itself, and return the code segment for that declaration. Therefore, the function's return
+   * value is the code segment of the declaration associated with the name node.
+   */
+  private extractNameNodeWithDependencies(nameNode: NameNode, sourceFile: SourceFile): CodeSegment {
+    const lookUpResult = this.typeEvaluator.lookUpSymbolRecursive(nameNode, nameNode.value, false);
+    if (!lookUpResult) {
+      throw new Error(`No symbol found for node '${nameNode.value}'.`);
+    }
+
+    // Find the declaration of the symbol.
+    const symbol = lookUpResult.symbol;
+    if (!symbol.hasDeclarations()) {
+      throw new Error(`No declaration found for symbol '${nameNode.value}'.`);
+    }
+    const declarations = symbol.getDeclarations();
+    if (declarations.length > 1) {
+      throw new Error(
+        `Multiple declarations found for symbol '${nameNode.value}'. We don't support this yet.`
+      );
+    }
+    const declaration = declarations[0];
+
+    switch (declaration.type) {
+      case DeclarationType.Variable: {
+        switch (declaration.node.nodeType) {
+          case ParseNodeType.StringList: {
+            const value = this.valueEvaluator.getValue(declaration.node);
+            const text = Value.toString(value);
+            return {
+              node: declaration.node,
+              code: text,
+              dependencies: [],
+            };
+          }
+          case ParseNodeType.Name: {
+            // The name node is a variable.
+            return this.extractVariableWithDependencies(declaration.node, sourceFile);
+          }
+          default:
+            throw new Error(`Unable to reach here.`);
+        }
+      }
+
+      case DeclarationType.Function: {
+        return this.extractFunctionWithDependencies(declaration.node, sourceFile);
+      }
+
+      case DeclarationType.Class: {
+        return this.extractClassWithDependencies(declaration.node, sourceFile);
+      }
+
+      case DeclarationType.Alias: {
+        switch (declaration.node.nodeType) {
+          case ParseNodeType.ImportFromAs:
+            return this.extractImportFromAsWithDependencies(declaration.node);
+          case ParseNodeType.ImportAs:
+            return this.extractImportAsWithDependencies(declaration.node);
+          default:
+            throw new Error(`Unsupported node type: ${declaration.node.nodeType}`);
+        }
+      }
+
+      default:
+        if (process.env.DEBUG) {
+          console.debug(
+            "Don't support this declaration: ",
+            TextUtils.getTextOfNode(declaration.node, sourceFile)
+          );
+        }
+        throw new Error(`Unsupported declaration type: ${declaration.type}`);
+    }
+    throw new Error("Unable to reach here.");
+  }
+
+  private extractVariableWithDependencies(node: NameNode, sourceFile: SourceFile): CodeSegment {
+    if (node.parent?.nodeType !== ParseNodeType.Assignment) {
+      throw new Error(
+        `We only support the simplest assignment statement, the tuple assignment or other statements are not supported yet.`
+      );
+    }
+
+    const dependencies: CodeSegment[] = [];
+    let rightExpressionText = "";
+
+    const rightExpression = node.parent.rightExpression;
+    const segment = this.extractExpressionWithDependencies(rightExpression, sourceFile);
+    if (rightExpression.nodeType === ParseNodeType.Name) {
+      // If the expression on the right is a named node, then the code segment includes the
+      // declaration of this named node. We should add this declaration segment to the dependencies
+      // and use the value of the named node as the text for the right expression.
+      dependencies.push(segment);
+      rightExpressionText = rightExpression.value;
+    } else {
+      // Otherwise, the code segment includes the expression itself, and we should add the
+      // dependencies of the expression to the current segment's dependencies. And use the code of
+      // the expression as the text for the right expression.
+      dependencies.push(...segment.dependencies);
+      rightExpressionText = segment.code;
+    }
+
+    const statement = `${node.value} = ${rightExpressionText}`;
+    return {
+      node: node,
+      exportableName: node.value,
+      code: statement,
+      dependencies: dependencies,
+    };
+  }
+
+  private extractFunctionWithDependencies(
+    funcNode: FunctionNode,
+    sourceFile: SourceFile
+  ): CodeSegment {
+    const functionScope = getScopeForNode(funcNode.suite);
+    if (!functionScope) {
+      throw new Error(`No scope found for this function '${funcNode.name.value}'.`);
+    }
+
+    const walker = new OutsideSymbolFinder(this.typeEvaluator, functionScope, funcNode.name);
+    walker.walk(funcNode);
+
+    const dependencies: CodeSegment[] = [];
+    for (const nameNode of walker.nameNodes) {
+      const dep = this.extractNameNodeWithDependencies(nameNode, sourceFile);
+      dependencies.push(dep);
+    }
+
+    return {
+      node: funcNode,
+      exportableName: funcNode.name.value,
+      code: TextUtils.getTextOfNode(funcNode, sourceFile)!,
+      dependencies,
+    };
+  }
+
+  private extractCallWithDependencies(node: CallNode, sourceFile: SourceFile): CodeSegment {
+    // If this call node is for constructing a resource object, we don't need to extract the
+    // function type argument from it. The function type argument will be sent to the cloud and
+    // accessed via RPC.
+    const extractFunctionArg = !this.specialNodeMap.getNodeById(
+      node.id,
+      TypeConsts.IRESOURCE_FULL_NAME
+    );
+
+    const dependencies: CodeSegment[] = [];
+    // The code for building each argument of the construct statement.
+    const argumentCodes: string[] = [];
+    node.arguments.forEach((arg) => {
+      const segment = this.extractArgumentWithDependencies(arg, sourceFile, extractFunctionArg);
+      dependencies.push(...segment.dependencies);
+      argumentCodes.push(segment.code);
+    });
+
+    let methodCode = "";
+    const segment = this.extractExpressionWithDependencies(node.leftExpression, sourceFile);
+    if (node.leftExpression.nodeType === ParseNodeType.Name) {
+      // If this left expression is a name node, then the code segment encapsulates the declaration
+      // corresponding to this node.
+      dependencies.push(segment);
+      methodCode = node.leftExpression.value;
+    } else {
+      // If the left expression if not a name node, it may be a member access node, the segment
+      // encapsulates the caller expression itself. So, we add the dependencies of the caller's
+      // expression to the current segment's dependencies. And use the code of the caller's
+      // expression as the text for the left expression.
+      dependencies.push(...segment.dependencies);
+      methodCode = segment.code;
+    }
+
+    const statement = `${methodCode}(${argumentCodes.join(", ")})`;
+    return {
+      node: node,
+      code: statement,
+      dependencies,
+    };
+  }
+
+  private extractArgumentWithDependencies(
+    arg: ArgumentNode,
+    sourceFile: SourceFile,
+    extractFunctionArg: boolean
+  ): CodeSegment {
+    if (
+      TypeUtils.isLambdaNode(arg.valueExpression) ||
+      TypeUtils.isFunctionVar(arg.valueExpression, this.typeEvaluator)
+    ) {
+      // The argument is either a lambda function, a function variable, or a function call which
+      // returns a function.
+      if (!extractFunctionArg) {
+        // If we don't need to extract the function argument, we just use a lambda function as a
+        // placeholder.
+        return {
+          node: arg,
+          code: "lambda _: _",
+          dependencies: [],
+        };
+      }
+    }
+
+    const segment = this.extractExpressionWithDependencies(arg.valueExpression, sourceFile);
+    if (arg.valueExpression.nodeType === ParseNodeType.Name) {
+      // If the expression is a name node, then the code segment encapsulates the declaration of
+      // this node. We should add this declaration segment to the dependencies. And use the value of
+      // the named node as the text for the argument expression.
+      return {
+        node: arg,
+        code: arg.valueExpression.value,
+        dependencies: [segment],
+      };
+    } else {
+      // Otherwise, we use the code of the expression as the text for the argument expression, so we
+      // just directly return the segment of the expression.
+      return segment;
+    }
+  }
+
+  /**
+   * Extract the class definition and its dependencies.
+   * @param classNode - The class node.
+   * @param sourceFile - The source file where the class node is located.
+   */
+  private extractClassWithDependencies(classNode: ClassNode, sourceFile: SourceFile): CodeSegment {
+    const nodeText = TextUtils.getTextOfNode(classNode, sourceFile);
+
+    const classScope = getScopeForNode(classNode.suite);
+    if (!classScope) {
+      throw new Error(`No scope found for this lambda function '${nodeText}'.`);
+    }
+
+    const walker = new OutsideSymbolFinder(this.typeEvaluator, classScope, classNode.name);
+    walker.walk(classNode);
+
+    const dependencies: CodeSegment[] = [];
+    for (const nameNode of walker.nameNodes) {
+      const dep = this.extractNameNodeWithDependencies(nameNode, sourceFile);
+      dependencies.push(dep);
+    }
+
+    return {
+      node: classNode,
+      exportableName: classNode.name.value,
+      code: nodeText!,
+      dependencies,
+    };
+  }
+
+  /**
+   * Extract the member access expression, like `obj.method`, `func().method`, `module.method`, etc.
+   * Only the left expression needs to be extracted, as the right expression is the method name,
+   * which isn't a dependency.
+   * @param node - The member access node.
+   * @param sourceFile - The source file where the member access node is located.
+   */
+  private extractMemberAccessWithDependencies(
+    node: MemberAccessNode,
+    sourceFile: SourceFile
+  ): CodeSegment {
+    const callerSegment = this.extractExpressionWithDependencies(node.leftExpression, sourceFile);
+
+    let code = "";
+    const dependencies: CodeSegment[] = [];
+    if (node.leftExpression.nodeType === ParseNodeType.Name) {
+      // Like `obj.method`, `module.method`, etc.
+      dependencies.push(callerSegment);
+      code = `${node.leftExpression.value}.${node.memberName.value}`;
+    } else {
+      // Like `func().method`, `func().attr.method`, etc.
+      dependencies.push(...callerSegment.dependencies);
+      code = `${callerSegment.code}.${node.memberName.value}`;
+    }
+
+    return {
+      node: node,
+      code: code,
+      dependencies: dependencies,
+    };
+  }
+
+  /**
+   * Extract the import-from statement, such as `from module import name`, `from module import name
+   * as alias`.
+   * @param node
+   * @returns
+   */
+  private extractImportFromAsWithDependencies(node: ImportFromAsNode): CodeSegment {
+    assert(node.parent?.nodeType === ParseNodeType.ImportFrom);
+    const moduleNameNode = node.parent.module;
+    const moduleName = AnalyzerNodeInfo.getImportInfo(moduleNameNode)?.importName;
+    assert(moduleName);
+
+    const name = node.name.value;
+    const alias = node.alias?.value;
+    const statement = `from ${moduleName} import ${name}` + (alias ? ` as ${alias}` : "");
+    return {
+      node: node,
+      code: statement,
+      dependencies: [],
+    };
+  }
+
+  /**
+   * Extract the import statement, such as `import module`, `import module as alias`.
+   * @param node - The import-as node.
+   */
+  private extractImportAsWithDependencies(node: ImportAsNode): CodeSegment {
+    const moduleNameNode = node.module;
+    const moduleName = AnalyzerNodeInfo.getImportInfo(moduleNameNode)?.importName;
+    assert(moduleName);
+
+    const alias = node.alias?.value;
+    const statement = `import ${moduleName}` + (alias ? ` as ${alias}` : "");
+    return {
+      node: node,
+      code: statement,
+      dependencies: [],
+    };
+  }
+}
+
+/**
+ * Get the symbols that are used in the function but defined outside of it, and not in the built-in
+ * scope.
+ */
+class OutsideSymbolFinder extends ParseTreeWalker {
+  /**
+   * The name nodes that defined outside of the function, and not in the built-in scope.
+   */
+  public readonly nameNodes: NameNode[] = [];
+
+  constructor(
+    private readonly typeEvaluator: TypeEvaluator,
+    private readonly scope: Scope,
+    private readonly rootNode?: ParseNode
+  ) {
+    super();
+  }
+
+  public override visitName(node: NameNode): boolean {
+    if (node !== this.rootNode && !this.shouldIgnore(node)) {
+      const symbol = this.typeEvaluator.lookUpSymbolRecursive(node, node.value, false);
+      assert(symbol); // The symbol cannot be undefined; it's checked in `shouldIgnore`.
+      this.nameNodes.push(node);
+    }
+    return true;
+  }
+
+  private shouldIgnore(node: NameNode): boolean {
+    const symbolWithScope = this.typeEvaluator.lookUpSymbolRecursive(node, node.value, false);
+    if (symbolWithScope && ScopeUtils.isScopeContainedWithin(symbolWithScope.scope, this.scope)) {
+      // The symbol is defined in the function's scope.
+      return true;
+    }
+
+    if (this.scope.lookUpSymbol(node.value)) {
+      // Ignore the local variables. We don't need to package the local variables.
+      return true;
+    }
+
+    if (node.parent?.nodeType === ParseNodeType.MemberAccess && node.parent.memberName === node) {
+      // Ignore the member access. We just need to check if the caller is outside of the scope.
+      return true;
+    }
+
+    if (node.parent?.nodeType === ParseNodeType.Argument && node.parent.name === node) {
+      // Ignore the argument name.
+      return true;
+    }
+
+    if (node.parent?.nodeType === ParseNodeType.Parameter && node.parent.name === node) {
+      // Ignore the parameter name.
+      return true;
+    }
+
+    if (node.value === "self") {
+      // Ignore the `self` parameter.
+      return true;
+    }
+
+    // Check if the symbol linked to this node is from the built-in scope.
+    // ```python
+    // isinstance(arr, list)
+    // name: str = "hello"
+    // ```
+    const result = this.typeEvaluator.lookUpSymbolRecursive(node, node.value, false);
+    if (!result) {
+      throw new Error(`No symbol found for node '${node.value}'.`);
+    }
+    if (result.scope === getBuiltInScope(this.scope)) {
+      // This symobl is from the built-in scope.
+      return true;
+    }
+    return false;
+  }
+}
diff --git a/components/deducers/python-pyright/src/index.ts b/components/deducers/python-pyright/src/index.ts
index 44d6474a..7170b205 100644
--- a/components/deducers/python-pyright/src/index.ts
+++ b/components/deducers/python-pyright/src/index.ts
@@ -6,7 +6,12 @@ import { Program } from "pyright-internal/dist/analyzer/program";
 import { TypeCategory } from "pyright-internal/dist/analyzer/types";
 import { SourceFile } from "pyright-internal/dist/analyzer/sourceFile";
 import { TypeEvaluator } from "pyright-internal/dist/analyzer/typeEvaluatorTypes";
-import { ArgumentCategory, CallNode } from "pyright-internal/dist/parser/parseNodes";
+import {
+  ArgumentCategory,
+  ArgumentNode,
+  CallNode,
+  ParseNodeType,
+} from "pyright-internal/dist/parser/parseNodes";
 import { DeduceResult, Deducer } from "@plutolang/base/core";
 import * as TextUtils from "./text-utils";
 import * as TypeConsts from "./type-consts";
@@ -16,6 +21,7 @@ import { TypeSearcher } from "./type-searcher";
 import { SpecialNodeMap } from "./special-node-map";
 import { Value, ValueEvaluator } from "./value-evaluator";
 import { ResourceObjectTracker } from "./resource-object-tracker";
+import { CodeSegment, CodeExtractor } from "./code-extractor";
 
 export default class PyrightDeducer extends Deducer {
   //eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -99,7 +105,15 @@ export default class PyrightDeducer extends Deducer {
           specialType === TypeConsts.IRESOURCE_FULL_NAME ||
           specialType === TypeConsts.IRESOURCE_INFRA_API_FULL_NAME
         ) {
-          getArgumentValue(node, sourceFile, program.evaluator!);
+          const valueEvaluator = new ValueEvaluator(program.evaluator!);
+          getArgumentValue(
+            node,
+            sourceFile,
+            program.evaluator!,
+            this.sepcialNodeMap!,
+            tracker,
+            valueEvaluator
+          );
           // console.log(inGlobalScope(node, sourceFile));
         }
         console.log("\\--------------------/\n\n");
@@ -129,20 +143,41 @@ export default class PyrightDeducer extends Deducer {
 function getArgumentValue(
   callNode: CallNode,
   sourceFile: SourceFile,
-  typeEvaluator: TypeEvaluator
+  typeEvaluator: TypeEvaluator,
+  specialNodeMap: SpecialNodeMap<CallNode>,
+  resourceObjectTracker: ResourceObjectTracker,
+  valueEvaluator: ValueEvaluator
 ) {
+  function isFunctionArgument(arg: ArgumentNode, typeEvaluator: TypeEvaluator) {
+    if (arg.valueExpression.nodeType === ParseNodeType.Lambda) {
+      return true;
+    }
+    const valueNodeType = typeEvaluator.getType(arg.valueExpression);
+    return valueNodeType?.category === TypeCategory.Function;
+  }
+
   callNode.arguments.forEach((arg) => {
     console.log("| Argument:");
     console.log("|   Text: ", TextUtils.getTextOfNode(arg, sourceFile));
 
-    const valueNodeType = typeEvaluator.getType(arg.valueExpression);
-    if (valueNodeType?.category === TypeCategory.Function) {
-      console.log("|   Value is a function, we need to encapsulate it into closures afterward.");
+    if (isFunctionArgument(arg, typeEvaluator)) {
+      const codeExtractor = new CodeExtractor(typeEvaluator, specialNodeMap, valueEvaluator);
+      const segment = codeExtractor.extractExpressionWithDependencies(
+        arg.valueExpression,
+        sourceFile
+      );
+      console.log("| ================= Segment Begin ================== ");
+      console.log(
+        CodeSegment.toString(segment)
+          .split("\n")
+          .map((s) => "| " + s)
+          .join("\n")
+      );
+      console.log("| ================= Segment End ================== ");
       return;
     }
 
     if (arg.argumentCategory === ArgumentCategory.Simple) {
-      const valueEvaluator = new ValueEvaluator(typeEvaluator);
       const value = valueEvaluator.getValue(arg.valueExpression);
       console.log("|   Value: ", value);
       console.log("|   Stringified: ", Value.toString(value));
diff --git a/components/deducers/python-pyright/src/resource-object-tracker.ts b/components/deducers/python-pyright/src/resource-object-tracker.ts
index db4ad26b..afd9befb 100644
--- a/components/deducers/python-pyright/src/resource-object-tracker.ts
+++ b/components/deducers/python-pyright/src/resource-object-tracker.ts
@@ -70,14 +70,14 @@ export class ResourceObjectTracker {
   }
 
   /**
-   * The caller variable refers to a resource object. We're attempting to locate the calling node
-   * that creates this resource object.
+   * The variable refers to a resource object. We're attempting to locate the calling node that
+   * creates this resource object.
    * @param node - The name node refering to the resource object.
    * @param sourceFile - The source file that the node is in.
    * @returns - The node that constructs the resource object. If the node is not found, return
    * undefined.
    */
-  private getConstructNodeByNameNode(node: NameNode, sourceFile: SourceFile): CallNode | undefined {
+  public getConstructNodeByNameNode(node: NameNode, sourceFile: SourceFile): CallNode | undefined {
     if (this.cache.has(node.id)) {
       return this.cache.get(node.id);
     }
diff --git a/components/deducers/python-pyright/src/scope-utils.ts b/components/deducers/python-pyright/src/scope-utils.ts
index ac867d52..b5531a11 100644
--- a/components/deducers/python-pyright/src/scope-utils.ts
+++ b/components/deducers/python-pyright/src/scope-utils.ts
@@ -1,12 +1,14 @@
 import assert from "node:assert";
-import { getScopeForNode } from "pyright-internal/dist/analyzer/scopeUtils";
+import * as ScopeUtils from "pyright-internal/dist/analyzer/scopeUtils";
 import { SourceFile } from "pyright-internal/dist/analyzer/sourceFile";
 import { CallNode } from "pyright-internal/dist/parser/parseNodes";
 
 export function inGlobalScope(node: CallNode, sourceFile: SourceFile): boolean {
-  const scope = getScopeForNode(node);
+  const scope = ScopeUtils.getScopeForNode(node);
   const parseTree = sourceFile.getParseResults()?.parseTree;
   assert(parseTree, "No parse tree found in source file.");
-  const globalScope = getScopeForNode(parseTree!);
+  const globalScope = ScopeUtils.getScopeForNode(parseTree!);
   return scope === globalScope;
 }
+
+export const isScopeContainedWithin = ScopeUtils.isScopeContainedWithin;
diff --git a/components/deducers/python-pyright/src/test/code-extractor.test.ts b/components/deducers/python-pyright/src/test/code-extractor.test.ts
new file mode 100644
index 00000000..3958f752
--- /dev/null
+++ b/components/deducers/python-pyright/src/test/code-extractor.test.ts
@@ -0,0 +1,94 @@
+import * as path from "path";
+import { Program } from "pyright-internal/dist/analyzer/program";
+import { SourceFile } from "pyright-internal/dist/analyzer/sourceFile";
+import { ParseNode, ParseNodeType } from "pyright-internal/dist/parser/parseNodes";
+import { ParseTreeWalker } from "pyright-internal/dist/analyzer/parseTreeWalker";
+import * as TestUtils from "./test-utils";
+import * as TypeUtils from "../type-utils";
+import * as TypeConsts from "../type-consts";
+import { ValueEvaluator } from "../value-evaluator";
+import { CodeSegment, CodeExtractor } from "../code-extractor";
+import { ResourceObjectTracker } from "../resource-object-tracker";
+
+const SAMPLES_ROOT = path.join(__dirname, "samples");
+
+test("should correctly extract the code segment for the most situations", () => {
+  const filepath = path.join(SAMPLES_ROOT, "code_extractor_valid.py");
+  const { program, sourceFiles } = TestUtils.parseFiles([filepath]);
+  expect(sourceFiles.length).toBe(1);
+  const sourceFile = sourceFiles[0];
+
+  const { specialNodeMap, extractor } = createTools(program, sourceFile);
+
+  const constructNodes = specialNodeMap.getNodesByType(TypeConsts.IRESOURCE_FULL_NAME);
+  const infraApiCalls = specialNodeMap.getNodesByType(TypeConsts.IRESOURCE_INFRA_API_FULL_NAME);
+
+  for (const node of [constructNodes, infraApiCalls].flat()) {
+    node?.arguments.forEach((arg) => {
+      if (
+        TypeUtils.isLambdaNode(arg.valueExpression) ||
+        TypeUtils.isFunctionVar(arg.valueExpression, program.evaluator!)
+      ) {
+        const segment = extractor.extractExpressionWithDependencies(
+          arg.valueExpression,
+          sourceFile
+        );
+        CodeSegment.toString(segment);
+      }
+    });
+  }
+});
+
+test("should throw an error when the assignment statement is not a simple assignment", () => {
+  const code = `
+a, b = 1, 2
+
+def foo(x):
+  return x + b  # Throw an error here
+
+foo(a)
+`;
+
+  const { program, sourceFile, clean } = TestUtils.parseCode(code);
+  const { extractor } = createTools(program, sourceFile);
+
+  const walker = new NodeFetcher([ParseNodeType.Call]);
+  walker.walk(sourceFile.getParseResults()!.parseTree!);
+
+  walker.nodes.forEach((node) => {
+    if (
+      node.nodeType === ParseNodeType.Call &&
+      node.leftExpression.nodeType === ParseNodeType.Name &&
+      node.leftExpression.value === "foo"
+    ) {
+      expect(() => extractor.extractExpressionWithDependencies(node, sourceFile)).toThrow(
+        /We only support the simplest assignment statement/
+      );
+    }
+  });
+
+  clean();
+});
+
+function createTools(program: Program, sourceFile: SourceFile) {
+  const specialNodeMap = TestUtils.getSpecialNodeMap(program, sourceFile);
+  const tracker = new ResourceObjectTracker(program.evaluator!, specialNodeMap);
+  const valueEvaluator = new ValueEvaluator(program.evaluator!);
+  const extractor = new CodeExtractor(program.evaluator!, specialNodeMap, valueEvaluator);
+  return { specialNodeMap, tracker, valueEvaluator, extractor };
+}
+
+class NodeFetcher extends ParseTreeWalker {
+  public readonly nodes: ParseNode[] = [];
+
+  constructor(private readonly expectedNodeTypes: ParseNodeType[]) {
+    super();
+  }
+
+  visit(node: ParseNode): boolean {
+    if (this.expectedNodeTypes.includes(node.nodeType)) {
+      this.nodes.push(node);
+    }
+    return true;
+  }
+}
diff --git a/components/deducers/python-pyright/src/test/resource-object-tracker.test.ts b/components/deducers/python-pyright/src/test/resource-object-tracker.test.ts
index fec1e9b0..05fcbec2 100644
--- a/components/deducers/python-pyright/src/test/resource-object-tracker.test.ts
+++ b/components/deducers/python-pyright/src/test/resource-object-tracker.test.ts
@@ -1,7 +1,4 @@
-import { Program } from "pyright-internal/dist/analyzer/program";
-import { SourceFile } from "pyright-internal/dist/analyzer/sourceFile";
 import { ResourceObjectTracker } from "../resource-object-tracker";
-import { TypeSearcher } from "../type-searcher";
 import * as TypeConsts from "../type-consts";
 import * as TestUtils from "./test-utils";
 
@@ -26,7 +23,7 @@ aliasQueue.subscribe(subscribe_handler)  # infra api call
 
   const { program, sourceFile, clean } = TestUtils.parseCode(code);
 
-  const specialNodeMap = getSpecialNodeMap(program, sourceFile);
+  const specialNodeMap = TestUtils.getSpecialNodeMap(program, sourceFile);
   const tracker = new ResourceObjectTracker(program.evaluator!, specialNodeMap);
 
   const infraApiCalls = specialNodeMap.getNodesByType(TypeConsts.IRESOURCE_INFRA_API_FULL_NAME);
@@ -63,7 +60,7 @@ indirectFn("/path", lambda x: x)
 `;
 
   const { program, sourceFile, clean } = TestUtils.parseCode(code);
-  const specialNodeMap = getSpecialNodeMap(program, sourceFile);
+  const specialNodeMap = TestUtils.getSpecialNodeMap(program, sourceFile);
   const tracker = new ResourceObjectTracker(program.evaluator!, specialNodeMap);
 
   const infraApiCalls = specialNodeMap.getNodesByType(TypeConsts.IRESOURCE_INFRA_API_FULL_NAME);
@@ -89,7 +86,7 @@ router.get("/path", lambda x: x)
 `;
 
   const { program, sourceFile, clean } = TestUtils.parseCode(code);
-  const specialNodeMap = getSpecialNodeMap(program, sourceFile);
+  const specialNodeMap = TestUtils.getSpecialNodeMap(program, sourceFile);
   const tracker = new ResourceObjectTracker(program.evaluator!, specialNodeMap);
 
   const infraApiCalls = specialNodeMap.getNodesByType(TypeConsts.IRESOURCE_INFRA_API_FULL_NAME);
@@ -116,7 +113,7 @@ router.get("/path", lambda x: x)
 `;
 
   const { program, sourceFile, clean } = TestUtils.parseCode(code);
-  const specialNodeMap = getSpecialNodeMap(program, sourceFile);
+  const specialNodeMap = TestUtils.getSpecialNodeMap(program, sourceFile);
   const tracker = new ResourceObjectTracker(program.evaluator!, specialNodeMap);
 
   const infraApiCalls = specialNodeMap.getNodesByType(TypeConsts.IRESOURCE_INFRA_API_FULL_NAME);
@@ -130,13 +127,3 @@ router.get("/path", lambda x: x)
 
   clean();
 });
-
-function getSpecialNodeMap(program: Program, sourceFile: SourceFile) {
-  const parseResult = sourceFile.getParseResults();
-  expect(parseResult).toBeDefined();
-  const parseTree = parseResult!.parseTree;
-
-  const walker = new TypeSearcher(program.evaluator!, sourceFile);
-  walker.walk(parseTree);
-  return walker.specialNodeMap;
-}
diff --git a/components/deducers/python-pyright/src/test/samples/code_extractor_valid.py b/components/deducers/python-pyright/src/test/samples/code_extractor_valid.py
new file mode 100644
index 00000000..8c65b59e
--- /dev/null
+++ b/components/deducers/python-pyright/src/test/samples/code_extractor_valid.py
@@ -0,0 +1,88 @@
+import json
+from datetime import datetime
+from dataclasses import dataclass
+from typing import Callable
+
+import pluto_client
+import pluto_client as pluto_client_alias
+from pluto_client import (
+    HttpRequest,
+    Function as PlutoFunction,
+    FunctionOptions,
+)
+from pluto_client.router import HttpResponse
+
+queueName = "test-queue"
+queue = pluto_client.Queue(queueName)  # resource object construction
+router = pluto_client_alias.Router("test-router")  # resource object construction
+
+
+@dataclass
+class Base:
+    id: str
+
+
+class Model(Base):
+    name: str
+    age: int
+
+    def __init__(self, name: str, age: int):
+        self.name = name
+        self.age = age
+
+
+const_num = 10
+
+
+def func(a: int, b: Callable[[int], int], c: Callable[[int], int]):
+    model = Model("name", 1)  # class dependency
+    print(router.url())  # invoke client method
+    return a + const_num  # variable dependency
+
+
+def echo(x):
+    return x
+
+
+var_from_call = func(1, lambda x: x, echo)
+
+
+def get_handler(req: HttpRequest) -> pluto_client_alias.HttpResponse:
+    print(var_from_call)  # variable dependency
+    func(1, echo, lambda x: x)  # nested function dependency
+    name = req.query["name"] if "name" in req.query else "Anonym"
+    if isinstance(name, list):
+        name = ",".join(name)
+    message = f"{name} access at {int(datetime.now().timestamp() * 1000)}"
+    queue.push(json.dumps({"name": name, "message": message}))  # invoke client method
+    return pluto_client_alias.HttpResponse(
+        status_code=200, body=f"Publish a message: {message}."
+    )
+
+
+func_obj = PlutoFunction(
+    func, FunctionOptions(name="func")
+)  # resource object construction with options
+
+
+def add(a: int):
+    def inner(b: int):
+        return a + b
+
+    return inner
+
+
+def returnHandler(path: str, add: Callable):
+    def handler(req: HttpRequest) -> pluto_client_alias.HttpResponse:
+        func_obj.invoke(1)
+        return pluto_client_alias.HttpResponse(status_code=200, body=f"Path: {path}")
+
+    return handler
+
+
+# infrastructure method invocations
+router.get("/get", get_handler)  # function variable
+router.post(
+    "/post", lambda x: HttpResponse(status_code=200, body="Post")  # lambda expression
+)
+router.put("/put", returnHandler("put", add(1)))  # function closure
diff --git a/components/deducers/python-pyright/src/test/test-utils.ts b/components/deducers/python-pyright/src/test/test-utils.ts
index 67bdd6c8..e76af916 100644
--- a/components/deducers/python-pyright/src/test/test-utils.ts
+++ b/components/deducers/python-pyright/src/test/test-utils.ts
@@ -7,6 +7,7 @@ import { LogLevel } from "pyright-internal/dist/common/console";
 import { SourceFile } from "pyright-internal/dist/analyzer/sourceFile";
 
 import * as ProgramUtils from "../program-utils";
+import { TypeSearcher } from "../type-searcher";
 
 export interface ParseResult {
   program: Program;
@@ -60,3 +61,13 @@ export function parseCode(code: string, filename: string = "tmp.py") {
     },
   };
 }
+
+export function getSpecialNodeMap(program: Program, sourceFile: SourceFile) {
+  const parseResult = sourceFile.getParseResults();
+  expect(parseResult).toBeDefined();
+  const parseTree = parseResult!.parseTree;
+
+  const walker = new TypeSearcher(program.evaluator!, sourceFile);
+  walker.walk(parseTree);
+  return walker.specialNodeMap;
+}
diff --git a/components/deducers/python-pyright/src/type-utils.ts b/components/deducers/python-pyright/src/type-utils.ts
index 5edfae9a..5828d0ea 100644
--- a/components/deducers/python-pyright/src/type-utils.ts
+++ b/components/deducers/python-pyright/src/type-utils.ts
@@ -1,7 +1,15 @@
 import { DeclarationType } from "pyright-internal/dist/analyzer/declaration";
 import { ParseTreeWalker } from "pyright-internal/dist/analyzer/parseTreeWalker";
+import { TypeEvaluator } from "pyright-internal/dist/analyzer/typeEvaluatorTypes";
 import { ClassType, Type, TypeCategory } from "pyright-internal/dist/analyzer/types";
-import { ClassNode, FunctionNode } from "pyright-internal/dist/parser/parseNodes";
+import {
+  ClassNode,
+  ExpressionNode,
+  FunctionNode,
+  LambdaNode,
+  ParseNode,
+  ParseNodeType,
+} from "pyright-internal/dist/parser/parseNodes";
 
 /**
  * Check if the type is a subclass of the target type.
@@ -9,7 +17,7 @@ import { ClassNode, FunctionNode } from "pyright-internal/dist/parser/parseNodes
  * @param targetTypeFullName - The full name of the target type.
  * @returns True if the type is a subclass of the target type, otherwise false.
  */
-export function isSubclassOf(type: Type, targetTypeFullName: string): boolean {
+export function isSubclassOf(type: Type, targetTypeFullName: string): type is ClassType {
   // If the type is unknown, we cannot determine if it is a subclass of the target class. So, we
   // print a warning and return false.
   if (type.category === TypeCategory.Unknown) {
@@ -106,6 +114,15 @@ function containsMethod(classNode: ClassNode, methodName: string): boolean {
   return walker.found;
 }
 
+export function isFunctionVar(node: ExpressionNode, typeEvaluator: TypeEvaluator) {
+  const valueNodeType = typeEvaluator.getType(node);
+  return valueNodeType?.category === TypeCategory.Function;
+}
+
+export function isLambdaNode(node: ParseNode): node is LambdaNode {
+  return node.nodeType === ParseNodeType.Lambda;
+}
+
 export function getTypeName(type: Type): string {
   switch (type.category) {
     case TypeCategory.Class:
diff --git a/components/deducers/python-pyright/src/value-evaluator.ts b/components/deducers/python-pyright/src/value-evaluator.ts
index 602e8817..fe854316 100644
--- a/components/deducers/python-pyright/src/value-evaluator.ts
+++ b/components/deducers/python-pyright/src/value-evaluator.ts
@@ -15,7 +15,7 @@ export interface Value {
 
 // eslint-disable-next-line @typescript-eslint/no-namespace
 export namespace Value {
-  export function toString(value: Value): string {
+  export function toString(value: Value, containModuleName: boolean = true): string {
     if (value.type === undefined) {
       // This is a primitive. We can directly return the JSON stringified value.
       return JSON.stringify(value.value);
@@ -32,14 +32,37 @@ export namespace Value {
       }
       default: {
         // This is a data class object.
+        const type = containModuleName ? value.type : value.type.split(".").pop()!;
         const values = value.value! as Record<string, Value>;
         const params = Object.entries(values)
           .map(([k, v]) => `${k}=${Value.toString(v)}`)
           .join(", ");
-        return `${value.type}(${params})`;
+        return `${type}(${params})`;
       }
     }
   }
+
+  /**
+   * Get all the types contained in the value.
+   */
+  export function getTypes(value: Value): string[] {
+    const types: string[] = [];
+    if (value.type) {
+      types.push(value.type);
+    }
+    if (value.value) {
+      if (Array.isArray(value.value)) {
+        value.value.forEach((v) => {
+          types.push(...getTypes(v));
+        });
+      } else {
+        Object.values(value.value).forEach((v) => {
+          types.push(...getTypes(v));
+        });
+      }
+    }
+    return types;
+  }
 }
 
 /**
