Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
3fb31b0
feat(python-ast):initial commit
yuval-hazaz Mar 30, 2025
f037930
refactor(python-ast): ClassReference vs Import
yuval-hazaz Mar 30, 2025
e2b448c
refactor(python-ast): improve write method to handle line indentation…
yuval-hazaz Mar 30, 2025
b3820cf
feat(python-ast): add update-snapshot executor to project configuration
yuval-hazaz Mar 30, 2025
4619e5b
feat(python-ast): enhance write method to include imports handling
yuval-hazaz Mar 30, 2025
4d5b77c
fix(python-ast): update snapshots to reflect changes in class and mod…
yuval-hazaz Mar 30, 2025
c488ef1
fix(python-ast): adjust import handling to apply aliases only for sin…
yuval-hazaz Mar 30, 2025
6171c47
fix(python-ast): update import tests to use toContain for string matc…
yuval-hazaz Mar 30, 2025
498a4d9
fix(python-ast): update parameter tests to check for both import and …
yuval-hazaz Mar 30, 2025
2f8e586
fix(python-ast): enhance parameter tests to verify import presence al…
yuval-hazaz Mar 30, 2025
59a0b12
refactor(python-ast): reorganize User class structure and example usa…
yuval-hazaz Mar 31, 2025
1b8d8de
refactor(python-ast): consolidate module structure to maintain order …
yuval-hazaz Mar 31, 2025
9dc2d8f
refactor(python-ast): streamline User class formatting and improve re…
yuval-hazaz Mar 31, 2025
95c47e2
refactor(python-ast): fix indentation
yuval-hazaz Mar 31, 2025
8d3338d
refactor(python-ast): remove sample code
yuval-hazaz Mar 31, 2025
f61bd2f
feat(python-ast): implement complex class generation with methods and…
yuval-hazaz Mar 31, 2025
7f9b1bc
feat(python-ast): add Python AST docs
yuval-hazaz Mar 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ This repository contains the following libraries:

- Java AST library (java-ast)
- C# AST library (csharp-ast)
- Python AST library (python-ast)
- Common AST types and interfaces (ast-types)

## Overview
Expand All @@ -26,7 +27,7 @@ The AST libraries are not intended to cover all language functionality. Instead,
When more specialized or custom code is needed, the `CodeBlock` can be used as a generic node that can include any code as a string. This flexibility allows you to generate both structured AST-based code and custom code blocks when necessary.

```typescript
import { CodeBlock } from '@amplication/java-ast'; // or '@amplication/csharp-ast'
import { CodeBlock } from '@amplication/java-ast'; // or '@amplication/csharp-ast' or '@amplication/python-ast'

// Create a custom code block when needed
const customLogic = new CodeBlock(`
Expand Down Expand Up @@ -64,6 +65,15 @@ The C# AST library provides functionality for generating C# code through an abst
- Attributes and documentation
- Namespace management

#### python-ast
The Python AST library provides functionality for generating Python code through an abstract syntax tree. It supports:
- Class and function definitions
- Method decorators and type annotations
- Module and import management
- Docstring generation
- Static and class methods
- Async functions

## Installation

To install the libraries:
Expand All @@ -75,6 +85,9 @@ npm install @amplication/java-ast
# For C# AST
npm install @amplication/csharp-ast

# For Python AST
npm install @amplication/python-ast

# For AST Types
npm install @amplication/ast-types
```
Expand All @@ -87,6 +100,8 @@ To use these libraries in your project:
import { Class, Interface, Method } from '@amplication/java-ast';
// or
import { Class, Interface, Method } from '@amplication/csharp-ast';
// or
import { ClassDef, FunctionDef, Decorator } from '@amplication/python-ast';
```

## Contributing
Expand Down
307 changes: 307 additions & 0 deletions libs/python-ast/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
# Python AST

This library provides an Abstract Syntax Tree (AST) representation for Python source code, focusing on the core language features necessary for defining classes, functions, and other declarations, while using a generic `CodeBlock` for unsupported language features.

## Key Features

- Core Python language constructs (modules, classes, functions)
- Import management and type annotations
- Generic code block for unsupported language features
- Clean and consistent API that matches other Amplication AST libraries
- Support for static and class methods
- Async function support
- Type hints and annotations

## Installation

```bash
npm install @amplication/python-ast
```

## Usage

### Creating a Python Module with Imports

```typescript
import {
Module,
Import,
ClassReference
} from '@amplication/python-ast';

// Create a module
const module = new Module({
name: 'user_service',
});

// Add imports
module.addImport(new Import({
from: 'typing',
names: ['List', 'Optional']
}));

module.addImport(new Import({
from: 'datetime',
names: ['datetime']
}));

// Result:
// from typing import List, Optional
// from datetime import datetime
```

### Creating a Complete Python Class

```typescript
import {
ClassDef,
FunctionDef,
Parameter,
ClassReference,
CodeBlock,
Module,
Decorator,
Return
} from '@amplication/python-ast';

// Create a class with inheritance
const userClass = new ClassDef({
name: 'User',
moduleName: 'models',
docstring: 'Represents a user in the system',
bases: [
new ClassReference({ name: 'BaseModel', moduleName: 'database.models' })
]
});

// Add class attributes with type annotations
userClass.addAttribute(new CodeBlock({
code: 'created_at: datetime = datetime.now()'
}));

// Add constructor
const initMethod = new FunctionDef({
name: '__init__',
parameters: [
new Parameter({ name: 'self' }),
new Parameter({
name: 'username',
type: new ClassReference({ name: 'str' })
}),
new Parameter({
name: 'email',
type: new ClassReference({ name: 'str' })
}),
new Parameter({
name: 'age',
type: new ClassReference({ name: 'Optional', genericTypes: [new ClassReference({ name: 'int' })] })
})
],
docstring: 'Initialize a new User instance'
});

initMethod.addStatement(new CodeBlock({
code: 'self.username = username\nself.email = email\nself.age = age'
}));

userClass.addMethod(initMethod);

// Add a static method
const createMethod = new FunctionDef({
name: 'create_user',
isStatic: true,
parameters: [
new Parameter({
name: 'username',
type: new ClassReference({ name: 'str' })
}),
new Parameter({
name: 'email',
type: new ClassReference({ name: 'str' })
})
],
returnType: new ClassReference({ name: 'User' }),
docstring: 'Create a new user instance'
});

createMethod.addStatement(new CodeBlock({
code: 'user = User(username, email)\nuser.save()\nreturn user'
}));

userClass.addMethod(createMethod);

// Add an async method
const fetchDataMethod = new FunctionDef({
name: 'fetch_data',
isAsync: true,
parameters: [new Parameter({ name: 'self' })],
returnType: new ClassReference({ name: 'dict' }),
docstring: 'Fetch user data asynchronously'
});

fetchDataMethod.addStatement(new CodeBlock({
code: 'data = await api.get_user_data(self.username)\nreturn data'
}));

userClass.addMethod(fetchDataMethod);

// Create a module and add the class
const module = new Module({ name: 'models' });
module.addClass(userClass);

// This will generate:
/*
from database.models import BaseModel
from datetime import datetime
from typing import Optional

class User(BaseModel):
"""Represents a user in the system"""

created_at: datetime = datetime.now()

def __init__(self, username: str, email: str, age: Optional[int]):
"""Initialize a new User instance"""
self.username = username
self.email = email
self.age = age

@staticmethod
def create_user(username: str, email: str) -> "User":
"""Create a new user instance"""
user = User(username, email)
user.save()
return user

async def fetch_data(self) -> dict:
"""Fetch user data asynchronously"""
data = await api.get_user_data(self.username)
return data
*/
```

### Using CodeBlock for Unsupported Features

The `CodeBlock` class is useful for Python features not directly supported by the AST library:

```typescript
// Exception handling
const tryExceptBlock = new CodeBlock({
code: `
try:
result = process_data()
return result
except ValueError as e:
logger.error(f"Invalid data: {e}")
raise
finally:
cleanup_resources()
`,
references: [
new ClassReference({ name: 'ValueError' }),
new ClassReference({ name: 'logger', moduleName: 'logging' })
]
});

// Context managers
const withBlock = new CodeBlock({
code: `
with open(file_path, 'r') as file:
content = file.read()
process_content(content)
`
});

// Decorators with arguments
const decoratedMethod = new FunctionDef({
name: 'process_request',
decorators: [
new Decorator({
name: 'retry',
arguments: ['max_attempts=3', 'delay=1'],
moduleName: 'utils.decorators'
})
]
});
```

## API Reference

The library provides the following main components:

- **Module**: Top-level container for Python code
- Manages imports and class definitions
- Handles module-level code organization

- **ClassDef**: Class definition with methods and attributes
- Supports inheritance
- Manages class attributes and methods
- Handles docstrings and decorators

- **FunctionDef**: Function or method definition
- Supports static and class methods
- Handles async functions
- Manages parameters and return types
- Supports decorators

- **Parameter**: Function or method parameter
- Supports type annotations
- Handles default values
- Supports generic types

- **Decorator**: Python decorator for functions/classes
- Supports decorator arguments
- Handles import management

- **Import**: Import statement management
- Supports from-import statements
- Handles multiple imports
- Manages import aliases

- **ClassReference**: Reference to a class
- Used for imports and type hints
- Supports generic types
- Handles module paths

- **CodeBlock**: Generic container for unsupported features
- Allows raw Python code
- Manages dependencies through references
- Preserves formatting

## Publishing

## Publish to npm

In order to publish to npm `@amplication/python-ast` :

1. Make sure to update the version in the package.json.
2. Run the following:


```sh
# From the monorepo root folder
npm i

npx nx build python-ast

cd ./dist/libs/python-ast

```

To publish the package as "beta" run:

```
npm publish --access public --tag beta
```

To publish the package as "latest" run:

```sh

npm publish --access public

```

## License

MIT
11 changes: 11 additions & 0 deletions libs/python-ast/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* eslint-disable */
export default {
displayName: "python-ast",
preset: "../../jest.preset.js",
testEnvironment: "node",
transform: {
"^.+\\.[tj]s$": ["ts-jest", { tsconfig: "<rootDir>/tsconfig.spec.json" }],
},
moduleFileExtensions: ["ts", "js", "html"],
coverageDirectory: "../../coverage/libs/python-ast",
};
11 changes: 11 additions & 0 deletions libs/python-ast/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "@amplication/python-ast",
"version": "0.1.0",
"description": "Python AST library in TypeScript",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@amplication/ast-types": "*"
}
}
Loading
Loading