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
class PHML:
 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.

PHML( scopes: Optional[list[str]] = None, components: Optional[dict[str, dict[str, list | phml.core.nodes.nodes.Root | phml.core.nodes.nodes.Element | phml.core.nodes.nodes.Text | phml.core.nodes.nodes.Comment | phml.core.nodes.nodes.DocType | phml.core.nodes.nodes.Parent | phml.core.nodes.nodes.Node | phml.core.nodes.nodes.Literal]]] = None, **contexts: Any)
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)

The parsed ast value.

components: dict

The components currently stored in the compiler.

def expose(self, **kwargs: Any):
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.

def redact(self, key: str):
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.

def expand(self, *args: str):
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.

def restrict(self, *args: str):
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.

def load( self, file_path: str | pathlib.Path, from_format: Optional[phml.core.formats.format.Format] = None, auto_close: bool = True):
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.
def parse( self, data: str | dict, from_format: phml.core.formats.format.Format = <class 'phml.core.formats.phml_format.PHMLFormat'>, auto_close: bool = True):
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
def compile( self, file_type: phml.core.formats.format.Format = <class 'phml.core.formats.html_format.HTMLFormat'>, scopes: Optional[list[str]] = None, components: Optional[dict] = None, **kwargs) -> phml.core.nodes.AST.AST:
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

def render( self, file_type: phml.core.formats.format.Format = <class 'phml.core.formats.html_format.HTMLFormat'>, indent: Optional[int] = None, scopes: Optional[list[str]] = None, components: Optional[dict] = None, **kwargs) -> str:
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.

def write( self, file: str | pathlib.Path | _io.TextIOWrapper, file_type: phml.core.formats.format.Format = <class 'phml.core.formats.html_format.HTMLFormat'>, indent: Optional[int] = None, scopes: Optional[list[str]] = None, replace_suffix: bool = False, components: Optional[dict] = None, **kwargs):
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.