phml.core.core
1from io import TextIOWrapper 2from pathlib import Path 3from typing import Any, Optional 4 5from phml.core.formats import Format, Formats 6from phml.core.nodes import AST, NODE 7from phml.utilities import cmpt_name_from_path, parse_component 8 9from .compiler import Compiler 10from .parser import Parser 11 12__all__ = ["PHML"] 13 14 15PathLike = str | Path 16CompiledComponent = dict[str, list | NODE] | AST | PathLike 17Component = dict[str, CompiledComponent] | tuple[str, CompiledComponent] | list[PathLike] | PathLike 18 19 20class PHML: 21 """A helper class that bundles the functionality 22 of the parser and compiler together. Allows for loading source files, 23 parsing strings and dicts, rendering to a different format, and finally 24 writing the results of a render to a file. 25 """ 26 27 @property 28 def ast(self) -> AST: 29 """The parsed ast value.""" 30 return self._parser.ast 31 32 @ast.setter 33 def ast(self, _ast: AST): 34 self._parser.ast = _ast 35 36 @property 37 def components(self) -> dict: 38 """The components currently stored in the compiler.""" 39 return self._compiler.components 40 41 def __init__( 42 self, 43 scopes: Optional[list[str]] = None, 44 components: Optional[dict[str, dict[str, list | NODE]]] = None, 45 **contexts: Any, 46 ): 47 self._parser = Parser() 48 self._compiler = Compiler(components=components) 49 self._scopes = scopes or [] 50 self._context = dict(contexts) 51 52 def expose(self, **kwargs: Any): 53 """Add additional data to the compilers global values. These values are exposed for every 54 call to render or write. 55 """ 56 self._context.update(kwargs) 57 58 def redact(self, key: str): 59 """Remove a value from the compilers globally exposed values.""" 60 self._context.pop(key, None) 61 62 def expand(self, *args: str): 63 """Add relative paths to a directory, that you want added to the python path 64 for every time render or write is called. 65 """ 66 self._scopes.extend([arg for arg in args if arg not in self._scopes]) 67 68 def restrict(self, *args: str): 69 """Remove relative paths to a directory, that are in the compilers globally added scopes. 70 This prevents them from being added to the python path. 71 """ 72 for arg in args: 73 if arg in self._scopes: 74 self._scopes.remove(arg) 75 76 def add( 77 self, 78 *components: Component, 79 strip: str = "", 80 ): 81 """Add a component to the compiler's component list. 82 83 Components passed in can be of a few types. The first type it can be is a 84 pathlib.Path type. This will allow for automatic parsing of the file at the 85 path and then the filename and parsed ast are passed to the compiler. It can 86 also be a dictionary of str being the name of the element to be replaced. 87 The name can be snake case, camel case, or pascal cased. The value can either 88 be the parsed result of the component from phml.utilities.parse_component() or the 89 parsed ast of the component. Lastely, the component can be a tuple. The first 90 value is the name of the element to be replaced; with the second value being 91 either the parsed result of the component or the component's ast. 92 93 Note: 94 Any duplicate components will be replaced. 95 96 Args: 97 components: Any number values indicating 98 name of the component and the the component. The name is used 99 to replace a element with the tag==name. 100 """ 101 102 for component in components: 103 if isinstance(component, list): 104 if not all(isinstance(path, PathLike) for path in component): 105 raise TypeError("If a component argument is a list all values must be either a \ 106str or pathlib.Path pointing to the file.") 107 for path in component: 108 self._parser.load(Path(path)) 109 self._compiler.add( 110 ( 111 cmpt_name_from_path(Path(path), strip), 112 parse_component(self._parser.ast), 113 ) 114 ) 115 elif isinstance(component, PathLike): 116 self._parser.load(Path(component)) 117 self._compiler.add( 118 ( 119 cmpt_name_from_path(Path(component), strip), 120 parse_component(self._parser.ast), 121 ) 122 ) 123 elif isinstance(component, tuple) and isinstance(component[1], PathLike): 124 self._parser.load(Path(component[1])) 125 self._compiler.add((component[0], parse_component(self._parser.ast))) 126 else: 127 self._compiler.add(component) 128 return self 129 130 def remove(self, *components: str | NODE): 131 """Remove an element from the list of element replacements. 132 133 Takes any number of strings or node objects. If a string is passed 134 it is used as the key that will be removed. If a node object is passed 135 it will attempt to find a matching node and remove it. 136 """ 137 self._compiler.remove(*components) 138 return self 139 140 def load(self, file_path: str | Path, from_format: Optional[Format] = None, auto_close: bool = True): 141 """Load a source files data and parse it to phml. 142 143 Args: 144 file_path (str | Path): The file path to the source file. 145 """ 146 self._parser.load(file_path, from_format, auto_close) 147 return self 148 149 def parse(self, data: str | dict, from_format: Format = Formats.PHML, auto_close: bool = True): 150 """Parse a str or dict object into phml. 151 152 Args: 153 data (str | dict): Object to parse to phml 154 """ 155 self._parser.parse(data, from_format, auto_close) 156 return self 157 158 def compile( 159 self, 160 file_type: Format = Formats.HTML, 161 scopes: Optional[list[str]] = None, 162 components: Optional[dict] = None, 163 **kwargs, 164 ) -> AST: 165 """Compile the parsed ast into it's fully processed form. 166 167 Args: 168 file_type (str): The format to render to. Currently support html, phml, and json. 169 indent (Optional[int], optional): The number of spaces per indent. By default it will 170 use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json 171 has 2 spaces. 172 173 Returns: 174 AST: The processed ast. Ast is in the final format of the passed in file_type 175 """ 176 177 scopes = scopes or [] 178 for scope in self._scopes: 179 if scope not in scopes: 180 scopes.append(scope) 181 182 return self._compiler.compile( 183 self._parser.ast, 184 to_format=file_type, 185 scopes=scopes, 186 components=components, 187 **{**self._context, **kwargs}, 188 ) 189 190 def render( 191 self, 192 file_type: Format = Formats.HTML, 193 indent: Optional[int] = None, 194 scopes: Optional[list[str]] = None, 195 components: Optional[dict] = None, 196 **kwargs, 197 ) -> str: 198 """Render the parsed ast to a different format. Defaults to rendering to html. 199 200 Args: 201 file_type (str): The format to render to. Currently support html, phml, and json. 202 indent (Optional[int], optional): The number of spaces per indent. By default it will 203 use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json 204 has 2 spaces. 205 206 Returns: 207 str: The rendered content in the appropriate format. 208 """ 209 210 scopes = scopes or [] 211 for scope in self._scopes: 212 if scope not in scopes: 213 scopes.append(scope) 214 215 return self._compiler.render( 216 self._parser.ast, 217 to_format=file_type, 218 indent=indent, 219 scopes=scopes, 220 components=components, 221 **{**self._context, **kwargs}, 222 ) 223 224 def write( 225 self, 226 file: str | Path | TextIOWrapper, 227 file_type: Format = Formats.HTML, 228 indent: Optional[int] = None, 229 scopes: Optional[list[str]] = None, 230 replace_suffix: bool = False, 231 components: Optional[dict] = None, 232 **kwargs, 233 ): 234 """Renders the parsed ast to a different format, then writes 235 it to a given file. Defaults to rendering and writing out as html. 236 237 Args: 238 file (str | Path | TextIOWrapper): The path to the file to be written to, or the opened 239 file to write to. 240 241 file_type (str): The format to render the ast as. 242 243 indent (Optional[int], optional): The number of spaces per indent. By default it will 244 use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json 245 has 2 spaces. 246 247 scopes (list[str], None): The relative paths from the cwd to the directory that will 248 be inserted into the python path. 249 250 replace_suffix (bool): Override to use the preferred file suffix no matter what. 251 Defaults to False, as the preferred suffix will only be used if no suffix is provided. 252 253 kwargs: Any additional data to pass to the compiler that will be exposed to the 254 phml files. 255 """ 256 if isinstance(file, (str | Path)): 257 file = Path(file) 258 259 file.parent.mkdir(parents=True, exist_ok=True) 260 261 if file.suffix == "" or replace_suffix: 262 file = file.with_suffix(file_type.suffix()) 263 264 with open(file, "+w", encoding="utf-8") as dest_file: 265 dest_file.write( 266 self.render( 267 file_type=file_type, 268 indent=indent, 269 scopes=scopes, 270 components=components, 271 **kwargs, 272 ) 273 ) 274 elif isinstance(file, TextIOWrapper): 275 file.write( 276 self.render( 277 file_type=file_type, 278 indent=indent, 279 scopes=scopes, 280 components=components, 281 **kwargs, 282 ) 283 ) 284 return self
21class PHML: 22 """A helper class that bundles the functionality 23 of the parser and compiler together. Allows for loading source files, 24 parsing strings and dicts, rendering to a different format, and finally 25 writing the results of a render to a file. 26 """ 27 28 @property 29 def ast(self) -> AST: 30 """The parsed ast value.""" 31 return self._parser.ast 32 33 @ast.setter 34 def ast(self, _ast: AST): 35 self._parser.ast = _ast 36 37 @property 38 def components(self) -> dict: 39 """The components currently stored in the compiler.""" 40 return self._compiler.components 41 42 def __init__( 43 self, 44 scopes: Optional[list[str]] = None, 45 components: Optional[dict[str, dict[str, list | NODE]]] = None, 46 **contexts: Any, 47 ): 48 self._parser = Parser() 49 self._compiler = Compiler(components=components) 50 self._scopes = scopes or [] 51 self._context = dict(contexts) 52 53 def expose(self, **kwargs: Any): 54 """Add additional data to the compilers global values. These values are exposed for every 55 call to render or write. 56 """ 57 self._context.update(kwargs) 58 59 def redact(self, key: str): 60 """Remove a value from the compilers globally exposed values.""" 61 self._context.pop(key, None) 62 63 def expand(self, *args: str): 64 """Add relative paths to a directory, that you want added to the python path 65 for every time render or write is called. 66 """ 67 self._scopes.extend([arg for arg in args if arg not in self._scopes]) 68 69 def restrict(self, *args: str): 70 """Remove relative paths to a directory, that are in the compilers globally added scopes. 71 This prevents them from being added to the python path. 72 """ 73 for arg in args: 74 if arg in self._scopes: 75 self._scopes.remove(arg) 76 77 def add( 78 self, 79 *components: Component, 80 strip: str = "", 81 ): 82 """Add a component to the compiler's component list. 83 84 Components passed in can be of a few types. The first type it can be is a 85 pathlib.Path type. This will allow for automatic parsing of the file at the 86 path and then the filename and parsed ast are passed to the compiler. It can 87 also be a dictionary of str being the name of the element to be replaced. 88 The name can be snake case, camel case, or pascal cased. The value can either 89 be the parsed result of the component from phml.utilities.parse_component() or the 90 parsed ast of the component. Lastely, the component can be a tuple. The first 91 value is the name of the element to be replaced; with the second value being 92 either the parsed result of the component or the component's ast. 93 94 Note: 95 Any duplicate components will be replaced. 96 97 Args: 98 components: Any number values indicating 99 name of the component and the the component. The name is used 100 to replace a element with the tag==name. 101 """ 102 103 for component in components: 104 if isinstance(component, list): 105 if not all(isinstance(path, PathLike) for path in component): 106 raise TypeError("If a component argument is a list all values must be either a \ 107str or pathlib.Path pointing to the file.") 108 for path in component: 109 self._parser.load(Path(path)) 110 self._compiler.add( 111 ( 112 cmpt_name_from_path(Path(path), strip), 113 parse_component(self._parser.ast), 114 ) 115 ) 116 elif isinstance(component, PathLike): 117 self._parser.load(Path(component)) 118 self._compiler.add( 119 ( 120 cmpt_name_from_path(Path(component), strip), 121 parse_component(self._parser.ast), 122 ) 123 ) 124 elif isinstance(component, tuple) and isinstance(component[1], PathLike): 125 self._parser.load(Path(component[1])) 126 self._compiler.add((component[0], parse_component(self._parser.ast))) 127 else: 128 self._compiler.add(component) 129 return self 130 131 def remove(self, *components: str | NODE): 132 """Remove an element from the list of element replacements. 133 134 Takes any number of strings or node objects. If a string is passed 135 it is used as the key that will be removed. If a node object is passed 136 it will attempt to find a matching node and remove it. 137 """ 138 self._compiler.remove(*components) 139 return self 140 141 def load(self, file_path: str | Path, from_format: Optional[Format] = None, auto_close: bool = True): 142 """Load a source files data and parse it to phml. 143 144 Args: 145 file_path (str | Path): The file path to the source file. 146 """ 147 self._parser.load(file_path, from_format, auto_close) 148 return self 149 150 def parse(self, data: str | dict, from_format: Format = Formats.PHML, auto_close: bool = True): 151 """Parse a str or dict object into phml. 152 153 Args: 154 data (str | dict): Object to parse to phml 155 """ 156 self._parser.parse(data, from_format, auto_close) 157 return self 158 159 def compile( 160 self, 161 file_type: Format = Formats.HTML, 162 scopes: Optional[list[str]] = None, 163 components: Optional[dict] = None, 164 **kwargs, 165 ) -> AST: 166 """Compile the parsed ast into it's fully processed form. 167 168 Args: 169 file_type (str): The format to render to. Currently support html, phml, and json. 170 indent (Optional[int], optional): The number of spaces per indent. By default it will 171 use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json 172 has 2 spaces. 173 174 Returns: 175 AST: The processed ast. Ast is in the final format of the passed in file_type 176 """ 177 178 scopes = scopes or [] 179 for scope in self._scopes: 180 if scope not in scopes: 181 scopes.append(scope) 182 183 return self._compiler.compile( 184 self._parser.ast, 185 to_format=file_type, 186 scopes=scopes, 187 components=components, 188 **{**self._context, **kwargs}, 189 ) 190 191 def render( 192 self, 193 file_type: Format = Formats.HTML, 194 indent: Optional[int] = None, 195 scopes: Optional[list[str]] = None, 196 components: Optional[dict] = None, 197 **kwargs, 198 ) -> str: 199 """Render the parsed ast to a different format. Defaults to rendering to html. 200 201 Args: 202 file_type (str): The format to render to. Currently support html, phml, and json. 203 indent (Optional[int], optional): The number of spaces per indent. By default it will 204 use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json 205 has 2 spaces. 206 207 Returns: 208 str: The rendered content in the appropriate format. 209 """ 210 211 scopes = scopes or [] 212 for scope in self._scopes: 213 if scope not in scopes: 214 scopes.append(scope) 215 216 return self._compiler.render( 217 self._parser.ast, 218 to_format=file_type, 219 indent=indent, 220 scopes=scopes, 221 components=components, 222 **{**self._context, **kwargs}, 223 ) 224 225 def write( 226 self, 227 file: str | Path | TextIOWrapper, 228 file_type: Format = Formats.HTML, 229 indent: Optional[int] = None, 230 scopes: Optional[list[str]] = None, 231 replace_suffix: bool = False, 232 components: Optional[dict] = None, 233 **kwargs, 234 ): 235 """Renders the parsed ast to a different format, then writes 236 it to a given file. Defaults to rendering and writing out as html. 237 238 Args: 239 file (str | Path | TextIOWrapper): The path to the file to be written to, or the opened 240 file to write to. 241 242 file_type (str): The format to render the ast as. 243 244 indent (Optional[int], optional): The number of spaces per indent. By default it will 245 use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json 246 has 2 spaces. 247 248 scopes (list[str], None): The relative paths from the cwd to the directory that will 249 be inserted into the python path. 250 251 replace_suffix (bool): Override to use the preferred file suffix no matter what. 252 Defaults to False, as the preferred suffix will only be used if no suffix is provided. 253 254 kwargs: Any additional data to pass to the compiler that will be exposed to the 255 phml files. 256 """ 257 if isinstance(file, (str | Path)): 258 file = Path(file) 259 260 file.parent.mkdir(parents=True, exist_ok=True) 261 262 if file.suffix == "" or replace_suffix: 263 file = file.with_suffix(file_type.suffix()) 264 265 with open(file, "+w", encoding="utf-8") as dest_file: 266 dest_file.write( 267 self.render( 268 file_type=file_type, 269 indent=indent, 270 scopes=scopes, 271 components=components, 272 **kwargs, 273 ) 274 ) 275 elif isinstance(file, TextIOWrapper): 276 file.write( 277 self.render( 278 file_type=file_type, 279 indent=indent, 280 scopes=scopes, 281 components=components, 282 **kwargs, 283 ) 284 ) 285 return self
A helper class that bundles the functionality of the parser and compiler together. Allows for loading source files, parsing strings and dicts, rendering to a different format, and finally writing the results of a render to a file.
42 def __init__( 43 self, 44 scopes: Optional[list[str]] = None, 45 components: Optional[dict[str, dict[str, list | NODE]]] = None, 46 **contexts: Any, 47 ): 48 self._parser = Parser() 49 self._compiler = Compiler(components=components) 50 self._scopes = scopes or [] 51 self._context = dict(contexts)
53 def expose(self, **kwargs: Any): 54 """Add additional data to the compilers global values. These values are exposed for every 55 call to render or write. 56 """ 57 self._context.update(kwargs)
Add additional data to the compilers global values. These values are exposed for every call to render or write.
59 def redact(self, key: str): 60 """Remove a value from the compilers globally exposed values.""" 61 self._context.pop(key, None)
Remove a value from the compilers globally exposed values.
63 def expand(self, *args: str): 64 """Add relative paths to a directory, that you want added to the python path 65 for every time render or write is called. 66 """ 67 self._scopes.extend([arg for arg in args if arg not in self._scopes])
Add relative paths to a directory, that you want added to the python path for every time render or write is called.
69 def restrict(self, *args: str): 70 """Remove relative paths to a directory, that are in the compilers globally added scopes. 71 This prevents them from being added to the python path. 72 """ 73 for arg in args: 74 if arg in self._scopes: 75 self._scopes.remove(arg)
Remove relative paths to a directory, that are in the compilers globally added scopes. This prevents them from being added to the python path.
77 def add( 78 self, 79 *components: Component, 80 strip: str = "", 81 ): 82 """Add a component to the compiler's component list. 83 84 Components passed in can be of a few types. The first type it can be is a 85 pathlib.Path type. This will allow for automatic parsing of the file at the 86 path and then the filename and parsed ast are passed to the compiler. It can 87 also be a dictionary of str being the name of the element to be replaced. 88 The name can be snake case, camel case, or pascal cased. The value can either 89 be the parsed result of the component from phml.utilities.parse_component() or the 90 parsed ast of the component. Lastely, the component can be a tuple. The first 91 value is the name of the element to be replaced; with the second value being 92 either the parsed result of the component or the component's ast. 93 94 Note: 95 Any duplicate components will be replaced. 96 97 Args: 98 components: Any number values indicating 99 name of the component and the the component. The name is used 100 to replace a element with the tag==name. 101 """ 102 103 for component in components: 104 if isinstance(component, list): 105 if not all(isinstance(path, PathLike) for path in component): 106 raise TypeError("If a component argument is a list all values must be either a \ 107str or pathlib.Path pointing to the file.") 108 for path in component: 109 self._parser.load(Path(path)) 110 self._compiler.add( 111 ( 112 cmpt_name_from_path(Path(path), strip), 113 parse_component(self._parser.ast), 114 ) 115 ) 116 elif isinstance(component, PathLike): 117 self._parser.load(Path(component)) 118 self._compiler.add( 119 ( 120 cmpt_name_from_path(Path(component), strip), 121 parse_component(self._parser.ast), 122 ) 123 ) 124 elif isinstance(component, tuple) and isinstance(component[1], PathLike): 125 self._parser.load(Path(component[1])) 126 self._compiler.add((component[0], parse_component(self._parser.ast))) 127 else: 128 self._compiler.add(component) 129 return self
Add a component to the compiler's component list.
Components passed in can be of a few types. The first type it can be is a pathlib.Path type. This will allow for automatic parsing of the file at the path and then the filename and parsed ast are passed to the compiler. It can also be a dictionary of str being the name of the element to be replaced. The name can be snake case, camel case, or pascal cased. The value can either be the parsed result of the component from phml.utilities.parse_component() or the parsed ast of the component. Lastely, the component can be a tuple. The first value is the name of the element to be replaced; with the second value being either the parsed result of the component or the component's ast.
Note:
Any duplicate components will be replaced.
Arguments:
- components: Any number values indicating
- name of the component and the the component. The name is used
- to replace a element with the tag==name.
131 def remove(self, *components: str | NODE): 132 """Remove an element from the list of element replacements. 133 134 Takes any number of strings or node objects. If a string is passed 135 it is used as the key that will be removed. If a node object is passed 136 it will attempt to find a matching node and remove it. 137 """ 138 self._compiler.remove(*components) 139 return self
Remove an element from the list of element replacements.
Takes any number of strings or node objects. If a string is passed it is used as the key that will be removed. If a node object is passed it will attempt to find a matching node and remove it.
141 def load(self, file_path: str | Path, from_format: Optional[Format] = None, auto_close: bool = True): 142 """Load a source files data and parse it to phml. 143 144 Args: 145 file_path (str | Path): The file path to the source file. 146 """ 147 self._parser.load(file_path, from_format, auto_close) 148 return self
Load a source files data and parse it to phml.
Arguments:
- file_path (str | Path): The file path to the source file.
150 def parse(self, data: str | dict, from_format: Format = Formats.PHML, auto_close: bool = True): 151 """Parse a str or dict object into phml. 152 153 Args: 154 data (str | dict): Object to parse to phml 155 """ 156 self._parser.parse(data, from_format, auto_close) 157 return self
Parse a str or dict object into phml.
Arguments:
- data (str | dict): Object to parse to phml
159 def compile( 160 self, 161 file_type: Format = Formats.HTML, 162 scopes: Optional[list[str]] = None, 163 components: Optional[dict] = None, 164 **kwargs, 165 ) -> AST: 166 """Compile the parsed ast into it's fully processed form. 167 168 Args: 169 file_type (str): The format to render to. Currently support html, phml, and json. 170 indent (Optional[int], optional): The number of spaces per indent. By default it will 171 use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json 172 has 2 spaces. 173 174 Returns: 175 AST: The processed ast. Ast is in the final format of the passed in file_type 176 """ 177 178 scopes = scopes or [] 179 for scope in self._scopes: 180 if scope not in scopes: 181 scopes.append(scope) 182 183 return self._compiler.compile( 184 self._parser.ast, 185 to_format=file_type, 186 scopes=scopes, 187 components=components, 188 **{**self._context, **kwargs}, 189 )
Compile the parsed ast into it's fully processed form.
Arguments:
- file_type (str): The format to render to. Currently support html, phml, and json.
- indent (Optional[int], optional): The number of spaces per indent. By default it will
- use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json
- has 2 spaces.
Returns:
AST: The processed ast. Ast is in the final format of the passed in file_type
191 def render( 192 self, 193 file_type: Format = Formats.HTML, 194 indent: Optional[int] = None, 195 scopes: Optional[list[str]] = None, 196 components: Optional[dict] = None, 197 **kwargs, 198 ) -> str: 199 """Render the parsed ast to a different format. Defaults to rendering to html. 200 201 Args: 202 file_type (str): The format to render to. Currently support html, phml, and json. 203 indent (Optional[int], optional): The number of spaces per indent. By default it will 204 use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json 205 has 2 spaces. 206 207 Returns: 208 str: The rendered content in the appropriate format. 209 """ 210 211 scopes = scopes or [] 212 for scope in self._scopes: 213 if scope not in scopes: 214 scopes.append(scope) 215 216 return self._compiler.render( 217 self._parser.ast, 218 to_format=file_type, 219 indent=indent, 220 scopes=scopes, 221 components=components, 222 **{**self._context, **kwargs}, 223 )
Render the parsed ast to a different format. Defaults to rendering to html.
Arguments:
- file_type (str): The format to render to. Currently support html, phml, and json.
- indent (Optional[int], optional): The number of spaces per indent. By default it will
- use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json
- has 2 spaces.
Returns:
str: The rendered content in the appropriate format.
225 def write( 226 self, 227 file: str | Path | TextIOWrapper, 228 file_type: Format = Formats.HTML, 229 indent: Optional[int] = None, 230 scopes: Optional[list[str]] = None, 231 replace_suffix: bool = False, 232 components: Optional[dict] = None, 233 **kwargs, 234 ): 235 """Renders the parsed ast to a different format, then writes 236 it to a given file. Defaults to rendering and writing out as html. 237 238 Args: 239 file (str | Path | TextIOWrapper): The path to the file to be written to, or the opened 240 file to write to. 241 242 file_type (str): The format to render the ast as. 243 244 indent (Optional[int], optional): The number of spaces per indent. By default it will 245 use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json 246 has 2 spaces. 247 248 scopes (list[str], None): The relative paths from the cwd to the directory that will 249 be inserted into the python path. 250 251 replace_suffix (bool): Override to use the preferred file suffix no matter what. 252 Defaults to False, as the preferred suffix will only be used if no suffix is provided. 253 254 kwargs: Any additional data to pass to the compiler that will be exposed to the 255 phml files. 256 """ 257 if isinstance(file, (str | Path)): 258 file = Path(file) 259 260 file.parent.mkdir(parents=True, exist_ok=True) 261 262 if file.suffix == "" or replace_suffix: 263 file = file.with_suffix(file_type.suffix()) 264 265 with open(file, "+w", encoding="utf-8") as dest_file: 266 dest_file.write( 267 self.render( 268 file_type=file_type, 269 indent=indent, 270 scopes=scopes, 271 components=components, 272 **kwargs, 273 ) 274 ) 275 elif isinstance(file, TextIOWrapper): 276 file.write( 277 self.render( 278 file_type=file_type, 279 indent=indent, 280 scopes=scopes, 281 components=components, 282 **kwargs, 283 ) 284 ) 285 return self
Renders the parsed ast to a different format, then writes it to a given file. Defaults to rendering and writing out as html.
Arguments:
- file (str | Path | TextIOWrapper): The path to the file to be written to, or the opened
- file to write to.
- file_type (str): The format to render the ast as.
- indent (Optional[int], optional): The number of spaces per indent. By default it will
- use the standard for the given format. HTML has 4 spaces, phml has 4 spaces, and json
- has 2 spaces.
- scopes (list[str], None): The relative paths from the cwd to the directory that will
- be inserted into the python path.
- replace_suffix (bool): Override to use the preferred file suffix no matter what.
- Defaults to False, as the preferred suffix will only be used if no suffix is provided.
- kwargs: Any additional data to pass to the compiler that will be exposed to the
- phml files.