Coverage for src/renaissance/syntax_tree/ast_factory.py: 94%

18 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-15 10:34 +0000

1# Copyright (C) 2024-2026 TNO 

2# 

3# Licensed under the terms specified in the LICENSE file in the root directory 

4# of this repository, also available at: 

5# https://github.com/TNO/Renaissance.Py/blob/main/LICENSE 

6 

7"""AI: Factory for creating instances of ASTNode.""" 

8 

9from collections.abc import Sequence 

10from pathlib import Path 

11 

12from .ast_node import ASTNode 

13 

14 

15class ASTFactory: 

16 """A factory class for creating instances of ASTNode. 

17 

18 Attributes: 

19 clazz (type[ASTNode]): The class type of the AST nodes to be created. 

20 extra_args (Optional[Sequence[str]]): Additional arguments to be passed during the creation of AST nodes. 

21 #TODO working_dir 

22 

23 """ 

24 

25 def __init__( 

26 self, 

27 clazz: type[ASTNode], 

28 extra_args: Sequence[str] | None = None, 

29 working_dir: Path | None = None, 

30 ) -> None: 

31 """AI: Configure a factory that creates AST nodes of the given node-implementation type.""" 

32 self.clazz = clazz 

33 self.extra_args: Sequence[str] = extra_args if isinstance(extra_args, Sequence) else [] 

34 # TODO: Why not 

35 # self.extra_args: Sequence[str] = [] if extra_args is None else extra_args or 

36 # self.extra_args: Sequence[str] = extra_args if extra_args else [] ? 

37 # As the logic is about providing a value when none is provided. 

38 # In other words, the type of the optional argument is not relevant for the logic. 

39 self.working_dir = working_dir or Path.cwd() 

40 

41 def create(self, file_path: Path) -> ASTNode: 

42 """AI: Parse the source file at file_path into an ASTNode using the configured node type.""" 

43 atu = self.clazz.load( 

44 file_path=file_path, 

45 extra_args=self.extra_args, 

46 working_dir=self.working_dir, 

47 ) 

48 assert isinstance(atu, self.clazz), "The loaded AST node is not an instance of the expected type" 

49 return atu 

50 

51 def create_from_text(self, text: str, file_name: str) -> ASTNode: 

52 """AI: Parse source text (attributed to file_name) into an ASTNode using the configured node type.""" 

53 atu = self.clazz.load_from_text(text, file_name, extra_args=self.extra_args, working_dir=self.working_dir) 

54 assert isinstance(atu, self.clazz), "The loaded AST node is not an instance of the expected type" 

55 return atu 

56 

57 

58if __name__ == "__main__": 

59 pass