From 7c340e14d637165aa44fa5e5fbf191683beef448 Mon Sep 17 00:00:00 2001 From: codegen-bot Date: Fri, 24 Jan 2025 12:33:23 -0800 Subject: [PATCH 1/6] added exports --- src/codegen/sdk/core/codebase.py | 31 +++++++++ src/codegen/sdk/core/directory.py | 30 +++++++- .../codebase/test_codebase_raise_error.py | 17 +++++ .../codebase/test_codebase_exports.py | 52 ++++++++++++++ .../export/test_directory_exports.py | 52 ++++++++++++++ .../test_directory_import.py | 69 +++++++++++++++++++ 6 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 tests/unit/codegen/sdk/python/codebase/test_codebase_raise_error.py create mode 100644 tests/unit/codegen/sdk/typescript/codebase/test_codebase_exports.py create mode 100644 tests/unit/codegen/sdk/typescript/export/test_directory_exports.py create mode 100644 tests/unit/codegen/sdk/typescript/import_resolution/test_directory_import.py diff --git a/src/codegen/sdk/core/codebase.py b/src/codegen/sdk/core/codebase.py index 7805fa36f..91afed142 100644 --- a/src/codegen/sdk/core/codebase.py +++ b/src/codegen/sdk/core/codebase.py @@ -42,6 +42,7 @@ from codegen.sdk.core.file import File, SourceFile from codegen.sdk.core.function import Function from codegen.sdk.core.import_resolution import Import +from codegen.sdk.core.export import Export from codegen.sdk.core.interface import Interface from codegen.sdk.core.interfaces.editable import Editable from codegen.sdk.core.interfaces.has_name import HasName @@ -66,6 +67,8 @@ from codegen.sdk.typescript.file import TSFile from codegen.sdk.typescript.function import TSFunction from codegen.sdk.typescript.import_resolution import TSImport +from codegen.sdk.typescript.statements.import_statement import TSImportStatement +from codegen.sdk.typescript.export import TSExport from codegen.sdk.typescript.interface import TSInterface from codegen.sdk.typescript.symbol import TSSymbol from codegen.sdk.typescript.type_alias import TSTypeAlias @@ -90,6 +93,7 @@ TTypeAlias = TypeVar("TTypeAlias", bound="TypeAlias") TParameter = TypeVar("TParameter", bound="Parameter") TCodeBlock = TypeVar("TCodeBlock", bound="CodeBlock") +TExport = TypeVar("TExport", bound="Export") @apidoc @@ -262,6 +266,27 @@ def imports(self) -> list[TImport]: """ return self.G.get_nodes(NodeType.IMPORT) + @property + def exports(self: 'Codebase[TSFile, Directory, TSSymbol, TSClass, TSFunction, TSImport, TSAssignment, TSInterface, TSTypeAlias, TSParameter, TSCodeBlock]') -> list[TSExport]: + """Returns a list of all Export nodes in the codebase. + + Retrieves all Export nodes from the codebase graph. These exports represent all export statements across all files in the codebase, + including exports from both internal modules and external packages. This is a TypeScript-only codebase property. + + Args: + None + + Returns: + list[TSExport]: A list of Export nodes representing all exports in the codebase. + TExport can only be a TSExport for TypeScript codebases. + + """ + + if self.language == ProgrammingLanguage.PYTHON: + raise NotImplementedError("Exports are not supported for Python codebases since Python does not have an export mechanism.") + + return self.G.get_nodes(NodeType.EXPORT) + @property def external_modules(self) -> list[ExternalModule]: """Returns a list of all external modules in the codebase. @@ -1143,6 +1168,12 @@ def from_repo(cls, repo_name: str, *, tmp_dir: str | None = None, commit: str | # The last 2 lines of code are added to the runner. See codegen-backend/cli/generate/utils.py # Type Aliases +TSGlobalVar = TypeVar("TSGlobalVar", bound="Assignment") +TSDirectory = Directory[TSFile, TSSymbol, TSImportStatement, TSGlobalVar, TSClass, TSFunction, TSImport] + + CodebaseType = Codebase[SourceFile, Directory, Symbol, Class, Function, Import, Assignment, Interface, TypeAlias, Parameter, CodeBlock] PyCodebaseType = Codebase[PyFile, Directory, PySymbol, PyClass, PyFunction, PyImport, PyAssignment, Interface, TypeAlias, PyParameter, PyCodeBlock] TSCodebaseType = Codebase[TSFile, Directory, TSSymbol, TSClass, TSFunction, TSImport, TSAssignment, TSInterface, TSTypeAlias, TSParameter, TSCodeBlock] + + diff --git a/src/codegen/sdk/core/directory.py b/src/codegen/sdk/core/directory.py index 07c53d3f7..1a4b99941 100644 --- a/src/codegen/sdk/core/directory.py +++ b/src/codegen/sdk/core/directory.py @@ -12,6 +12,14 @@ from codegen.sdk.core.function import Function from codegen.sdk.core.import_resolution import ImportStatement from codegen.sdk.core.symbol import Symbol + from codegen.sdk.typescript.export import TSExport + from codegen.sdk.core.import_resolution import Import + from codegen.sdk.typescript.file import TSFile + from codegen.sdk.typescript.function import TSFunction + from codegen.sdk.typescript.import_resolution import TSImport + from codegen.sdk.typescript.statements.import_statement import TSImportStatement + from codegen.sdk.typescript.symbol import TSSymbol + from codegen.sdk.typescript.class_definition import TSClass import logging @@ -24,10 +32,12 @@ TGlobalVar = TypeVar("TGlobalVar", bound="Assignment") TClass = TypeVar("TClass", bound="Class") TFunction = TypeVar("TFunction", bound="Function") +TImport = TypeVar("TImport", bound="Import") +TSGlobalVar = TypeVar("TSGlobalVar", bound="Assignment") @apidoc -class Directory(Generic[TFile, TSymbol, TImportStatement, TGlobalVar, TClass, TFunction]): +class Directory(Generic[TFile, TSymbol, TImportStatement, TGlobalVar, TClass, TFunction, TImport]): """Directory representation for codebase. GraphSitter abstraction of a file directory that can be used to look for files and symbols within a specific directory. """ @@ -133,6 +143,16 @@ def functions(self) -> list[TFunction]: """Get a recursive list of all functions in the directory and its subdirectories.""" return list(chain.from_iterable(f.functions for f in self.files)) + @property + def exports(self: "Directory[TSFile, TSSymbol, TSImportStatement, TSGlobalVar, TSClass, TSFunction, TSImport]") -> "list[TSExport]": + """Get a recursive list of all exports in the directory and its subdirectories.""" + return list(chain.from_iterable(f.exports for f in self.files)) + + @property + def imports(self) -> list[TImport]: + """Get a recursive list of all imports in the directory and its subdirectories.""" + return list(chain.from_iterable(f.imports for f in self.files)) + def get_symbol(self, name: str) -> TSymbol | None: """Get a symbol by name in the directory and its subdirectories.""" return next((s for s in self.symbols if s.name == name), None) @@ -176,6 +196,14 @@ def get_file(self, filename: str, ignore_case: bool = False) -> TFile | None: return next((f for name, f in self.items.items() if name.lower() == filename.lower() and isinstance(f, File)), None) return self.items.get(filename, None) + def get_export(self: "Directory[TSFile, TSSymbol, TSImportStatement, TSGlobalVar, TSClass, TSFunction, TSImport]", name: str) -> "TSExport | None": + """Get an export by name in the directory and its subdirectories (supports only typescript).""" + return next((s for s in self.exports if s.name == name), None) + + def get_import(self, name: str) -> TImport | None: + """Get an import by name in the directory and its subdirectories.""" + return next((s for s in self.imports if s.name == name), None) + def add_subdirectory(self, subdirectory: Self) -> None: """Add a subdirectory to the directory.""" rel_path = os.path.relpath(subdirectory.dirpath, self.dirpath) diff --git a/tests/unit/codegen/sdk/python/codebase/test_codebase_raise_error.py b/tests/unit/codegen/sdk/python/codebase/test_codebase_raise_error.py new file mode 100644 index 000000000..4c46d78f9 --- /dev/null +++ b/tests/unit/codegen/sdk/python/codebase/test_codebase_raise_error.py @@ -0,0 +1,17 @@ +import pytest +from codegen.sdk.codebase.factory.get_session import get_codebase_session +from codegen.sdk.enums import ProgrammingLanguage + + +def test_python_exports_not_supported(tmpdir): + """Test that exports are not supported in Python codebases.""" + # language=python + content = """ +def hello(): + pass + """ + # Create a Python codebase with a simple Python file + with get_codebase_session(tmpdir=tmpdir, files={"test.py": content}, programming_language=ProgrammingLanguage.PYTHON) as codebase: + # Verify that accessing exports raises NotImplementedError + with pytest.raises(NotImplementedError): + _ = codebase.exports \ No newline at end of file diff --git a/tests/unit/codegen/sdk/typescript/codebase/test_codebase_exports.py b/tests/unit/codegen/sdk/typescript/codebase/test_codebase_exports.py new file mode 100644 index 000000000..df4d017e7 --- /dev/null +++ b/tests/unit/codegen/sdk/typescript/codebase/test_codebase_exports.py @@ -0,0 +1,52 @@ +from codegen.sdk.codebase.factory.get_session import get_codebase_session +from codegen.sdk.enums import ProgrammingLanguage + + +def test_codebase_exports(tmpdir) -> None: + # language=typescript + content = """ + export const a = 1; + export let b = 2; + export var c = 3; + export function foo() {} + export class Bar {} + export interface IFoo {} + export type MyType = string; + export { foo as default }; + """ + with get_codebase_session(tmpdir=tmpdir, files={"file.ts": content}, programming_language=ProgrammingLanguage.TYPESCRIPT) as codebase: + assert len(codebase.exports) == 8 + export_names = {exp.name for exp in codebase.exports} + assert export_names == {"a", "b", "c", "foo", "Bar", "IFoo", "MyType", "default"} + + +def test_codebase_reexports(tmpdir) -> None: + # language=typescript + content1 = """ + export const x = 1; + export const y = 2; + """ + content2 = """ + export { x } from './file1'; + export { y as z } from './file1'; + """ + with get_codebase_session( + tmpdir=tmpdir, + files={"file1.ts": content1, "file2.ts": content2}, + programming_language=ProgrammingLanguage.TYPESCRIPT + ) as codebase: + assert len(codebase.exports) == 4 + export_names = {exp.name for exp in codebase.exports} + assert export_names == {"x", "y", "z"} + + +def test_codebase_default_exports(tmpdir) -> None: + # language=typescript + content = """ + const value = 42; + export default value; + """ + with get_codebase_session(tmpdir=tmpdir, files={"file.ts": content}, programming_language=ProgrammingLanguage.TYPESCRIPT) as codebase: + assert len(codebase.exports) == 1 + export = codebase.exports[0] + assert export.name == "value" \ No newline at end of file diff --git a/tests/unit/codegen/sdk/typescript/export/test_directory_exports.py b/tests/unit/codegen/sdk/typescript/export/test_directory_exports.py new file mode 100644 index 000000000..df4d017e7 --- /dev/null +++ b/tests/unit/codegen/sdk/typescript/export/test_directory_exports.py @@ -0,0 +1,52 @@ +from codegen.sdk.codebase.factory.get_session import get_codebase_session +from codegen.sdk.enums import ProgrammingLanguage + + +def test_codebase_exports(tmpdir) -> None: + # language=typescript + content = """ + export const a = 1; + export let b = 2; + export var c = 3; + export function foo() {} + export class Bar {} + export interface IFoo {} + export type MyType = string; + export { foo as default }; + """ + with get_codebase_session(tmpdir=tmpdir, files={"file.ts": content}, programming_language=ProgrammingLanguage.TYPESCRIPT) as codebase: + assert len(codebase.exports) == 8 + export_names = {exp.name for exp in codebase.exports} + assert export_names == {"a", "b", "c", "foo", "Bar", "IFoo", "MyType", "default"} + + +def test_codebase_reexports(tmpdir) -> None: + # language=typescript + content1 = """ + export const x = 1; + export const y = 2; + """ + content2 = """ + export { x } from './file1'; + export { y as z } from './file1'; + """ + with get_codebase_session( + tmpdir=tmpdir, + files={"file1.ts": content1, "file2.ts": content2}, + programming_language=ProgrammingLanguage.TYPESCRIPT + ) as codebase: + assert len(codebase.exports) == 4 + export_names = {exp.name for exp in codebase.exports} + assert export_names == {"x", "y", "z"} + + +def test_codebase_default_exports(tmpdir) -> None: + # language=typescript + content = """ + const value = 42; + export default value; + """ + with get_codebase_session(tmpdir=tmpdir, files={"file.ts": content}, programming_language=ProgrammingLanguage.TYPESCRIPT) as codebase: + assert len(codebase.exports) == 1 + export = codebase.exports[0] + assert export.name == "value" \ No newline at end of file diff --git a/tests/unit/codegen/sdk/typescript/import_resolution/test_directory_import.py b/tests/unit/codegen/sdk/typescript/import_resolution/test_directory_import.py new file mode 100644 index 000000000..6f7898d17 --- /dev/null +++ b/tests/unit/codegen/sdk/typescript/import_resolution/test_directory_import.py @@ -0,0 +1,69 @@ +from codegen.sdk.codebase.factory.get_session import get_codebase_session +from codegen.sdk.enums import ImportType, ProgrammingLanguage + + +def test_directory_imports(tmpdir) -> None: + # language=typescript + content1 = """ + import { a, b } from '../shared'; + import type { IFoo } from './types'; + """ + content2 = """ + import { c } from '../shared'; + import defaultExport from './module'; + """ + with get_codebase_session( + tmpdir=tmpdir, + files={ + "dir1/file1.ts": content1, + "dir1/file2.ts": content2, + "dir2/file3.ts": "import { d } from '../shared';" + }, + programming_language=ProgrammingLanguage.TYPESCRIPT + ) as codebase: + dir1 = codebase.get_directory("dir1") + dir2 = codebase.get_directory("dir2") + + # Test dir1 imports + assert len(dir1.imports) == 5 + dir1_import_names = {imp.name for imp in dir1.imports} + assert dir1_import_names == {"a", "b", "IFoo", "c", "defaultExport"} + + # Test dir2 imports + assert len(dir2.imports) == 1 + assert dir2.imports[0].name == "d" + + # Test get_import method + assert dir1.get_import("a") is not None + assert dir1.get_import("d") is None + assert dir2.get_import("d") is not None + + +def test_directory_nested_imports(tmpdir) -> None: + # language=typescript + content1 = """ + import { a } from './module1'; + """ + content2 = """ + import { b } from '../module2'; + """ + content3 = """ + import { c } from '../../module3'; + """ + with get_codebase_session( + tmpdir=tmpdir, + files={ + "dir1/file1.ts": content1, + "dir1/subdir/file2.ts": content2, + "dir1/subdir/deepdir/file3.ts": content3 + }, + programming_language=ProgrammingLanguage.TYPESCRIPT + ) as codebase: + dir1 = codebase.get_directory("dir1") + subdir = codebase.get_directory("dir1/subdir") + deepdir = codebase.get_directory("dir1/subdir/deepdir") + + # Test imports at each directory level + assert len(dir1.imports) == 3 # Should include all nested imports + assert len(subdir.imports) == 2 # Should include its own and deeper imports + assert len(deepdir.imports) == 1 # Should only include its own imports \ No newline at end of file From 6015877979683bf7106fde1dfef64fb63f27e11b Mon Sep 17 00:00:00 2001 From: codegen-bot Date: Mon, 27 Jan 2025 10:20:11 -0800 Subject: [PATCH 2/6] added py_noapidocs for the TS specific methods? --- src/codegen/sdk/core/codebase.py | 6 +++--- src/codegen/sdk/core/directory.py | 4 +++- src/codegen/shared/decorators/docs.py | 13 +++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/codegen/sdk/core/codebase.py b/src/codegen/sdk/core/codebase.py index 23ad99dd8..f87744cd8 100644 --- a/src/codegen/sdk/core/codebase.py +++ b/src/codegen/sdk/core/codebase.py @@ -74,7 +74,7 @@ from codegen.sdk.typescript.symbol import TSSymbol from codegen.sdk.typescript.type_alias import TSTypeAlias from codegen.sdk.utils import determine_project_language -from codegen.shared.decorators.docs import apidoc, noapidoc +from codegen.shared.decorators.docs import apidoc, noapidoc, py_noapidoc from codegen.shared.exceptions.control_flow import MaxAIRequestsError from codegen.shared.performance.stopwatch_utils import stopwatch from codegen.visualizations.visualization_manager import VisualizationManager @@ -266,8 +266,10 @@ def imports(self) -> list[TImport]: TImport can be PyImport for Python codebases or TSImport for TypeScript codebases. """ return self.G.get_nodes(NodeType.IMPORT) + @property + @py_noapidoc def exports(self: 'Codebase[TSFile, Directory, TSSymbol, TSClass, TSFunction, TSImport, TSAssignment, TSInterface, TSTypeAlias, TSParameter, TSCodeBlock]') -> list[TSExport]: """Returns a list of all Export nodes in the codebase. @@ -1176,5 +1178,3 @@ def from_repo(cls, repo_name: str, *, tmp_dir: str | None = None, commit: str | CodebaseType = Codebase[SourceFile, Directory, Symbol, Class, Function, Import, Assignment, Interface, TypeAlias, Parameter, CodeBlock] PyCodebaseType = Codebase[PyFile, Directory, PySymbol, PyClass, PyFunction, PyImport, PyAssignment, Interface, TypeAlias, PyParameter, PyCodeBlock] TSCodebaseType = Codebase[TSFile, Directory, TSSymbol, TSClass, TSFunction, TSImport, TSAssignment, TSInterface, TSTypeAlias, TSParameter, TSCodeBlock] - - diff --git a/src/codegen/sdk/core/directory.py b/src/codegen/sdk/core/directory.py index 1a4b99941..c7769187b 100644 --- a/src/codegen/sdk/core/directory.py +++ b/src/codegen/sdk/core/directory.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import TYPE_CHECKING, Generic, Self, TypeVar -from codegen.shared.decorators.docs import apidoc +from codegen.shared.decorators.docs import apidoc, py_noapidoc if TYPE_CHECKING: from codegen.sdk.core.assignment import Assignment @@ -144,6 +144,7 @@ def functions(self) -> list[TFunction]: return list(chain.from_iterable(f.functions for f in self.files)) @property + @py_noapidoc def exports(self: "Directory[TSFile, TSSymbol, TSImportStatement, TSGlobalVar, TSClass, TSFunction, TSImport]") -> "list[TSExport]": """Get a recursive list of all exports in the directory and its subdirectories.""" return list(chain.from_iterable(f.exports for f in self.files)) @@ -196,6 +197,7 @@ def get_file(self, filename: str, ignore_case: bool = False) -> TFile | None: return next((f for name, f in self.items.items() if name.lower() == filename.lower() and isinstance(f, File)), None) return self.items.get(filename, None) + @py_noapidoc def get_export(self: "Directory[TSFile, TSSymbol, TSImportStatement, TSGlobalVar, TSClass, TSFunction, TSImport]", name: str) -> "TSExport | None": """Get an export by name in the directory and its subdirectories (supports only typescript).""" return next((s for s in self.exports if s.name == name), None) diff --git a/src/codegen/shared/decorators/docs.py b/src/codegen/shared/decorators/docs.py index e7c2b1d24..002a134c3 100644 --- a/src/codegen/shared/decorators/docs.py +++ b/src/codegen/shared/decorators/docs.py @@ -70,6 +70,19 @@ def noapidoc(obj: T) -> T: return obj +py_no_apidoc_objects: list[DocumentedObject] = [] +py_no_apidoc_signatures: set[str] = set() + + +def py_noapidoc(obj: T) -> T: + """Decorator for things that are hidden from the Python API documentation for AI-agent prompts.""" + obj._py_apidoc = False + obj._api_doc_lang = "python" + if doc_obj := get_documented_object(obj): + bisect.insort(py_no_apidoc_objects, doc_obj) + py_no_apidoc_signatures.add(doc_obj.signature()) + return obj + def get_documented_object(obj) -> DocumentedObject | None: module = inspect.getmodule(obj) module_name = module.__name__ if module else "" From fc6578e0f8161acdc3b2409d78d5a1c88393ccf5 Mon Sep 17 00:00:00 2001 From: codegen-bot Date: Mon, 27 Jan 2025 11:44:29 -0800 Subject: [PATCH 3/6] adding PyDirectroty and TSDirectoryt --- src/codegen/sdk/core/codebase.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/codegen/sdk/core/codebase.py b/src/codegen/sdk/core/codebase.py index f87744cd8..888f4c615 100644 --- a/src/codegen/sdk/core/codebase.py +++ b/src/codegen/sdk/core/codebase.py @@ -60,6 +60,7 @@ from codegen.sdk.python.file import PyFile from codegen.sdk.python.function import PyFunction from codegen.sdk.python.import_resolution import PyImport +from codegen.sdk.python.statements.import_statement import PyImportStatement from codegen.sdk.python.symbol import PySymbol from codegen.sdk.typescript.assignment import TSAssignment from codegen.sdk.typescript.class_definition import TSClass @@ -95,6 +96,14 @@ TParameter = TypeVar("TParameter", bound="Parameter") TCodeBlock = TypeVar("TCodeBlock", bound="CodeBlock") TExport = TypeVar("TExport", bound="Export") +TSGlobalVar = TypeVar("TSGlobalVar", bound="Assignment") +PyGlobalVar = TypeVar("PyGlobalVar", bound="Assignment") +TSDirectory = Directory[TSFile, TSSymbol, TSImportStatement, TSGlobalVar, TSClass, TSFunction, TSImport] +PyDirectory = Directory[PyFile, PySymbol, PyImportStatement, PyGlobalVar, PyClass, PyFunction, PyImport] + + + + @apidoc @@ -1168,13 +1177,8 @@ def from_repo(cls, repo_name: str, *, tmp_dir: str | None = None, commit: str | logger.error(f"Failed to initialize codebase: {e}") raise - # The last 2 lines of code are added to the runner. See codegen-backend/cli/generate/utils.py # Type Aliases -TSGlobalVar = TypeVar("TSGlobalVar", bound="Assignment") -TSDirectory = Directory[TSFile, TSSymbol, TSImportStatement, TSGlobalVar, TSClass, TSFunction, TSImport] - - CodebaseType = Codebase[SourceFile, Directory, Symbol, Class, Function, Import, Assignment, Interface, TypeAlias, Parameter, CodeBlock] -PyCodebaseType = Codebase[PyFile, Directory, PySymbol, PyClass, PyFunction, PyImport, PyAssignment, Interface, TypeAlias, PyParameter, PyCodeBlock] -TSCodebaseType = Codebase[TSFile, Directory, TSSymbol, TSClass, TSFunction, TSImport, TSAssignment, TSInterface, TSTypeAlias, TSParameter, TSCodeBlock] +PyCodebaseType = Codebase[PyFile, PyDirectory, PySymbol, PyClass, PyFunction, PyImport, PyAssignment, Interface, TypeAlias, PyParameter, PyCodeBlock] +TSCodebaseType = Codebase[TSFile, TSDirectory, TSSymbol, TSClass, TSFunction, TSImport, TSAssignment, TSInterface, TSTypeAlias, TSParameter, TSCodeBlock] From 034b82dd672b1051e4f33297c27b951ac8216460 Mon Sep 17 00:00:00 2001 From: codegen-bot Date: Mon, 27 Jan 2025 12:34:27 -0800 Subject: [PATCH 4/6] fixed TSCodebaseType --- src/codegen/sdk/core/codebase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen/sdk/core/codebase.py b/src/codegen/sdk/core/codebase.py index 888f4c615..2f0d2f024 100644 --- a/src/codegen/sdk/core/codebase.py +++ b/src/codegen/sdk/core/codebase.py @@ -279,7 +279,7 @@ def imports(self) -> list[TImport]: @property @py_noapidoc - def exports(self: 'Codebase[TSFile, Directory, TSSymbol, TSClass, TSFunction, TSImport, TSAssignment, TSInterface, TSTypeAlias, TSParameter, TSCodeBlock]') -> list[TSExport]: + def exports(self: 'TSCodebaseType') -> list[TSExport]: """Returns a list of all Export nodes in the codebase. Retrieves all Export nodes from the codebase graph. These exports represent all export statements across all files in the codebase, From 398e4940ecff80472da524d1d1ba182186438b39 Mon Sep 17 00:00:00 2001 From: codegen-bot Date: Mon, 27 Jan 2025 13:06:09 -0800 Subject: [PATCH 5/6] linting --- src/codegen/sdk/core/codebase.py | 17 ++++------- src/codegen/sdk/core/directory.py | 6 ++-- .../codebase/test_codebase_raise_error.py | 3 +- .../codebase/test_codebase_exports.py | 8 ++---- .../export/test_directory_exports.py | 8 ++---- .../test_directory_import.py | 28 ++++++------------- 6 files changed, 23 insertions(+), 47 deletions(-) diff --git a/src/codegen/sdk/core/codebase.py b/src/codegen/sdk/core/codebase.py index a1126280b..54675dbf1 100644 --- a/src/codegen/sdk/core/codebase.py +++ b/src/codegen/sdk/core/codebase.py @@ -39,11 +39,11 @@ from codegen.sdk.core.detached_symbols.code_block import CodeBlock from codegen.sdk.core.detached_symbols.parameter import Parameter from codegen.sdk.core.directory import Directory +from codegen.sdk.core.export import Export from codegen.sdk.core.external_module import ExternalModule from codegen.sdk.core.file import File, SourceFile from codegen.sdk.core.function import Function from codegen.sdk.core.import_resolution import Import -from codegen.sdk.core.export import Export from codegen.sdk.core.interface import Interface from codegen.sdk.core.interfaces.editable import Editable from codegen.sdk.core.interfaces.has_name import HasName @@ -66,12 +66,12 @@ from codegen.sdk.typescript.class_definition import TSClass from codegen.sdk.typescript.detached_symbols.code_block import TSCodeBlock from codegen.sdk.typescript.detached_symbols.parameter import TSParameter +from codegen.sdk.typescript.export import TSExport from codegen.sdk.typescript.file import TSFile from codegen.sdk.typescript.function import TSFunction from codegen.sdk.typescript.import_resolution import TSImport -from codegen.sdk.typescript.statements.import_statement import TSImportStatement -from codegen.sdk.typescript.export import TSExport from codegen.sdk.typescript.interface import TSInterface +from codegen.sdk.typescript.statements.import_statement import TSImportStatement from codegen.sdk.typescript.symbol import TSSymbol from codegen.sdk.typescript.type_alias import TSTypeAlias from codegen.sdk.utils import determine_project_language @@ -102,10 +102,6 @@ PyDirectory = Directory[PyFile, PySymbol, PyImportStatement, PyGlobalVar, PyClass, PyFunction, PyImport] - - - - @apidoc class Codebase(Generic[TSourceFile, TDirectory, TSymbol, TClass, TFunction, TImport, TGlobalVar, TInterface, TTypeAlias, TParameter, TCodeBlock]): """This class provides the main entrypoint for most programs to analyzing and manipulating codebases. @@ -275,11 +271,10 @@ def imports(self) -> list[TImport]: TImport can be PyImport for Python codebases or TSImport for TypeScript codebases. """ return self.G.get_nodes(NodeType.IMPORT) - @property @py_noapidoc - def exports(self: 'TSCodebaseType') -> list[TSExport]: + def exports(self: "TSCodebaseType") -> list[TSExport]: """Returns a list of all Export nodes in the codebase. Retrieves all Export nodes from the codebase graph. These exports represent all export statements across all files in the codebase, @@ -291,9 +286,8 @@ def exports(self: 'TSCodebaseType') -> list[TSExport]: Returns: list[TSExport]: A list of Export nodes representing all exports in the codebase. TExport can only be a TSExport for TypeScript codebases. - - """ + """ if self.language == ProgrammingLanguage.PYTHON: raise NotImplementedError("Exports are not supported for Python codebases since Python does not have an export mechanism.") @@ -1177,6 +1171,7 @@ def from_repo(cls, repo_name: str, *, tmp_dir: str | None = None, commit: str | logger.error(f"Failed to initialize codebase: {e}") raise + # The last 2 lines of code are added to the runner. See codegen-backend/cli/generate/utils.py # Type Aliases CodebaseType = Codebase[SourceFile, Directory, Symbol, Class, Function, Import, Assignment, Interface, TypeAlias, Parameter, CodeBlock] diff --git a/src/codegen/sdk/core/directory.py b/src/codegen/sdk/core/directory.py index 4eecd7581..e2097bc21 100644 --- a/src/codegen/sdk/core/directory.py +++ b/src/codegen/sdk/core/directory.py @@ -10,16 +10,15 @@ from codegen.sdk.core.class_definition import Class from codegen.sdk.core.file import File from codegen.sdk.core.function import Function - from codegen.sdk.core.import_resolution import ImportStatement + from codegen.sdk.core.import_resolution import Import, ImportStatement from codegen.sdk.core.symbol import Symbol + from codegen.sdk.typescript.class_definition import TSClass from codegen.sdk.typescript.export import TSExport - from codegen.sdk.core.import_resolution import Import from codegen.sdk.typescript.file import TSFile from codegen.sdk.typescript.function import TSFunction from codegen.sdk.typescript.import_resolution import TSImport from codegen.sdk.typescript.statements.import_statement import TSImportStatement from codegen.sdk.typescript.symbol import TSSymbol - from codegen.sdk.typescript.class_definition import TSClass import logging @@ -36,6 +35,7 @@ TSGlobalVar = TypeVar("TSGlobalVar", bound="Assignment") + @apidoc class Directory(Generic[TFile, TSymbol, TImportStatement, TGlobalVar, TClass, TFunction, TImport]): """Directory representation for codebase. diff --git a/tests/unit/codegen/sdk/python/codebase/test_codebase_raise_error.py b/tests/unit/codegen/sdk/python/codebase/test_codebase_raise_error.py index 4c46d78f9..a183ea2ef 100644 --- a/tests/unit/codegen/sdk/python/codebase/test_codebase_raise_error.py +++ b/tests/unit/codegen/sdk/python/codebase/test_codebase_raise_error.py @@ -1,4 +1,5 @@ import pytest + from codegen.sdk.codebase.factory.get_session import get_codebase_session from codegen.sdk.enums import ProgrammingLanguage @@ -14,4 +15,4 @@ def hello(): with get_codebase_session(tmpdir=tmpdir, files={"test.py": content}, programming_language=ProgrammingLanguage.PYTHON) as codebase: # Verify that accessing exports raises NotImplementedError with pytest.raises(NotImplementedError): - _ = codebase.exports \ No newline at end of file + _ = codebase.exports diff --git a/tests/unit/codegen/sdk/typescript/codebase/test_codebase_exports.py b/tests/unit/codegen/sdk/typescript/codebase/test_codebase_exports.py index df4d017e7..b6ef55d21 100644 --- a/tests/unit/codegen/sdk/typescript/codebase/test_codebase_exports.py +++ b/tests/unit/codegen/sdk/typescript/codebase/test_codebase_exports.py @@ -30,11 +30,7 @@ def test_codebase_reexports(tmpdir) -> None: export { x } from './file1'; export { y as z } from './file1'; """ - with get_codebase_session( - tmpdir=tmpdir, - files={"file1.ts": content1, "file2.ts": content2}, - programming_language=ProgrammingLanguage.TYPESCRIPT - ) as codebase: + with get_codebase_session(tmpdir=tmpdir, files={"file1.ts": content1, "file2.ts": content2}, programming_language=ProgrammingLanguage.TYPESCRIPT) as codebase: assert len(codebase.exports) == 4 export_names = {exp.name for exp in codebase.exports} assert export_names == {"x", "y", "z"} @@ -49,4 +45,4 @@ def test_codebase_default_exports(tmpdir) -> None: with get_codebase_session(tmpdir=tmpdir, files={"file.ts": content}, programming_language=ProgrammingLanguage.TYPESCRIPT) as codebase: assert len(codebase.exports) == 1 export = codebase.exports[0] - assert export.name == "value" \ No newline at end of file + assert export.name == "value" diff --git a/tests/unit/codegen/sdk/typescript/export/test_directory_exports.py b/tests/unit/codegen/sdk/typescript/export/test_directory_exports.py index df4d017e7..b6ef55d21 100644 --- a/tests/unit/codegen/sdk/typescript/export/test_directory_exports.py +++ b/tests/unit/codegen/sdk/typescript/export/test_directory_exports.py @@ -30,11 +30,7 @@ def test_codebase_reexports(tmpdir) -> None: export { x } from './file1'; export { y as z } from './file1'; """ - with get_codebase_session( - tmpdir=tmpdir, - files={"file1.ts": content1, "file2.ts": content2}, - programming_language=ProgrammingLanguage.TYPESCRIPT - ) as codebase: + with get_codebase_session(tmpdir=tmpdir, files={"file1.ts": content1, "file2.ts": content2}, programming_language=ProgrammingLanguage.TYPESCRIPT) as codebase: assert len(codebase.exports) == 4 export_names = {exp.name for exp in codebase.exports} assert export_names == {"x", "y", "z"} @@ -49,4 +45,4 @@ def test_codebase_default_exports(tmpdir) -> None: with get_codebase_session(tmpdir=tmpdir, files={"file.ts": content}, programming_language=ProgrammingLanguage.TYPESCRIPT) as codebase: assert len(codebase.exports) == 1 export = codebase.exports[0] - assert export.name == "value" \ No newline at end of file + assert export.name == "value" diff --git a/tests/unit/codegen/sdk/typescript/import_resolution/test_directory_import.py b/tests/unit/codegen/sdk/typescript/import_resolution/test_directory_import.py index 6f7898d17..50d6349b4 100644 --- a/tests/unit/codegen/sdk/typescript/import_resolution/test_directory_import.py +++ b/tests/unit/codegen/sdk/typescript/import_resolution/test_directory_import.py @@ -1,5 +1,5 @@ from codegen.sdk.codebase.factory.get_session import get_codebase_session -from codegen.sdk.enums import ImportType, ProgrammingLanguage +from codegen.sdk.enums import ProgrammingLanguage def test_directory_imports(tmpdir) -> None: @@ -13,26 +13,20 @@ def test_directory_imports(tmpdir) -> None: import defaultExport from './module'; """ with get_codebase_session( - tmpdir=tmpdir, - files={ - "dir1/file1.ts": content1, - "dir1/file2.ts": content2, - "dir2/file3.ts": "import { d } from '../shared';" - }, - programming_language=ProgrammingLanguage.TYPESCRIPT + tmpdir=tmpdir, files={"dir1/file1.ts": content1, "dir1/file2.ts": content2, "dir2/file3.ts": "import { d } from '../shared';"}, programming_language=ProgrammingLanguage.TYPESCRIPT ) as codebase: dir1 = codebase.get_directory("dir1") dir2 = codebase.get_directory("dir2") - + # Test dir1 imports assert len(dir1.imports) == 5 dir1_import_names = {imp.name for imp in dir1.imports} assert dir1_import_names == {"a", "b", "IFoo", "c", "defaultExport"} - + # Test dir2 imports assert len(dir2.imports) == 1 assert dir2.imports[0].name == "d" - + # Test get_import method assert dir1.get_import("a") is not None assert dir1.get_import("d") is None @@ -51,19 +45,13 @@ def test_directory_nested_imports(tmpdir) -> None: import { c } from '../../module3'; """ with get_codebase_session( - tmpdir=tmpdir, - files={ - "dir1/file1.ts": content1, - "dir1/subdir/file2.ts": content2, - "dir1/subdir/deepdir/file3.ts": content3 - }, - programming_language=ProgrammingLanguage.TYPESCRIPT + tmpdir=tmpdir, files={"dir1/file1.ts": content1, "dir1/subdir/file2.ts": content2, "dir1/subdir/deepdir/file3.ts": content3}, programming_language=ProgrammingLanguage.TYPESCRIPT ) as codebase: dir1 = codebase.get_directory("dir1") subdir = codebase.get_directory("dir1/subdir") deepdir = codebase.get_directory("dir1/subdir/deepdir") - + # Test imports at each directory level assert len(dir1.imports) == 3 # Should include all nested imports assert len(subdir.imports) == 2 # Should include its own and deeper imports - assert len(deepdir.imports) == 1 # Should only include its own imports \ No newline at end of file + assert len(deepdir.imports) == 1 # Should only include its own imports From a815be4650a134b2dd29737d85c446cd846f0fa6 Mon Sep 17 00:00:00 2001 From: codegen-bot Date: Mon, 27 Jan 2025 13:11:13 -0800 Subject: [PATCH 6/6] more linting --- src/codegen/shared/decorators/docs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/codegen/shared/decorators/docs.py b/src/codegen/shared/decorators/docs.py index 002a134c3..a7a1aaa49 100644 --- a/src/codegen/shared/decorators/docs.py +++ b/src/codegen/shared/decorators/docs.py @@ -83,6 +83,7 @@ def py_noapidoc(obj: T) -> T: py_no_apidoc_signatures.add(doc_obj.signature()) return obj + def get_documented_object(obj) -> DocumentedObject | None: module = inspect.getmodule(obj) module_name = module.__name__ if module else ""