collagraph 0.5.2__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- collagraph-0.7.0/PKG-INFO +144 -0
- collagraph-0.7.0/README.md +122 -0
- collagraph-0.7.0/collagraph/__main__.py +131 -0
- collagraph-0.7.0/collagraph/__pyinstaller/__init__.py +8 -0
- collagraph-0.7.0/collagraph/__pyinstaller/hook-collagraph.py +57 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/cgx/cgx.py +123 -89
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/collagraph.py +13 -35
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/component.py +31 -3
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/__init__.py +8 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pygfx_renderer.py +17 -15
- collagraph-0.7.0/collagraph/renderers/pyside/objects/scrollarea.py +11 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/widget.py +7 -3
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/utils.py +1 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside_renderer.py +17 -17
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/types.py +1 -2
- collagraph-0.7.0/pyproject.toml +50 -0
- collagraph-0.5.2/PKG-INFO +0 -87
- collagraph-0.5.2/README.md +0 -66
- collagraph-0.5.2/pyproject.toml +0 -35
- collagraph-0.5.2/setup.py +0 -39
- {collagraph-0.5.2 → collagraph-0.7.0}/LICENSE +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/__init__.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/cgx/__init__.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/cgx/importer.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/compare.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/dict_renderer.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/dom_renderer.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/__init__.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/__init__.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/combobox.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/dialogbuttonbox.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/dockwidget.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/itemmodel.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/listview.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/menu.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/menubar.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/qobject.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/splitter.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/standarditem.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/statusbar.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/tab.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/toolbar.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/treewidget.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/treewidgetitem.py +0 -0
- {collagraph-0.5.2 → collagraph-0.7.0}/collagraph/renderers/pyside/objects/window.py +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: collagraph
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Reactive user interfaces
|
|
5
|
+
Home-page: https://github.com/fork-tongue/collagraph
|
|
6
|
+
License: MIT
|
|
7
|
+
Author: Berend Klein Haneveld
|
|
8
|
+
Author-email: berendkleinhaneveld@gmail.com
|
|
9
|
+
Requires-Python: >=3.9
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Provides-Extra: pygfx
|
|
16
|
+
Provides-Extra: pyside
|
|
17
|
+
Requires-Dist: observ (>=0.14.1)
|
|
18
|
+
Requires-Dist: pygfx (>=0.1.17) ; extra == "pygfx"
|
|
19
|
+
Requires-Dist: pyside6_essentials (>=6.6,<6.7) ; (python_version < "3.13") and (extra == "pyside")
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
[](https://badge.fury.io/py/collagraph)
|
|
23
|
+
[](https://github.com/fork-tongue/collagraph/actions)
|
|
24
|
+
|
|
25
|
+
# Collagraph 📓
|
|
26
|
+
|
|
27
|
+
Reactive user interfaces.
|
|
28
|
+
|
|
29
|
+
> The word [Collagraphy](https://en.wikipedia.org/wiki/Collagraphy) is derived from the Greek word _koll_ or _kolla_, meaning glue, and graph, meaning the activity of drawing.
|
|
30
|
+
|
|
31
|
+
Inspired by Vue and React.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
Write your Python interfaces in a declarative manner with plain render functions, component classes or even single-file components using Vue-like syntax, but with Python!
|
|
37
|
+
|
|
38
|
+
* Reactivity (made possible by leveraging [observ](https://github.com/fork-tongue/observ))
|
|
39
|
+
* Function components
|
|
40
|
+
* Class components with local state and life-cycle methods/hooks
|
|
41
|
+
* Single-file components with Vue-like template syntax (`.cgx` files)
|
|
42
|
+
* Custom renderers
|
|
43
|
+
|
|
44
|
+
Here is an example that shows a counter, made with a component with Vue-like syntax:
|
|
45
|
+
|
|
46
|
+
Contents of `counter.cgx`:
|
|
47
|
+
```html
|
|
48
|
+
<template>
|
|
49
|
+
<widget>
|
|
50
|
+
<label
|
|
51
|
+
:text="f'Count: {count}'"
|
|
52
|
+
/>
|
|
53
|
+
<button
|
|
54
|
+
text="bump"
|
|
55
|
+
@clicked="bump"
|
|
56
|
+
/>
|
|
57
|
+
</widget>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<script>
|
|
61
|
+
import collagraph as cg
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class Counter(cg.Component):
|
|
65
|
+
def __init__(self, *args, **kwargs):
|
|
66
|
+
super().__init__(*args, **kwargs)
|
|
67
|
+
self.state["count"] = 0
|
|
68
|
+
|
|
69
|
+
def bump(self):
|
|
70
|
+
self.state["count"] += 1
|
|
71
|
+
</script>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Contents of `app.py`:
|
|
75
|
+
```python
|
|
76
|
+
from PySide6 import QtWidgets
|
|
77
|
+
import collagraph as cg
|
|
78
|
+
|
|
79
|
+
# After importing collagraph, it's possible to import
|
|
80
|
+
# components directly from .cgx files
|
|
81
|
+
from counter import Counter
|
|
82
|
+
|
|
83
|
+
# Create a Collagraph instance with a PySide renderer
|
|
84
|
+
# and register with the Qt event loop
|
|
85
|
+
gui = cg.Collagraph(renderer=cg.PySideRenderer())
|
|
86
|
+
# Render the component into a container
|
|
87
|
+
# (in this case the app but can be another widget)
|
|
88
|
+
app = QtWidgets.QApplication()
|
|
89
|
+
gui.render(cg.h(Counter), app)
|
|
90
|
+
app.exec()
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Which looks something like this:
|
|
94
|
+
|
|
95
|
+

|
|
96
|
+
|
|
97
|
+
Instead of using a python file as an entry point to run components, you can run them directly using the collagraph CLI:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
poetry run collagraph examples/pyside/counter.cgx
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
For more examples, please take a look at the [examples folder](examples).
|
|
104
|
+
|
|
105
|
+
Currently there are three renderers:
|
|
106
|
+
|
|
107
|
+
* [PysideRenderer](collagraph/renderers/pyside_renderer.py): for rendering PySide6 applications
|
|
108
|
+
* [PygfxRenderer](collagraph/renderers/pygfx_renderer.py): for rendering 3D graphic scenes with [Pygfx](https://github.com/pygfx/pygfx)
|
|
109
|
+
* [DomRenderer](collagraph/renderers/dom_renderer.py): for rendering to browser DOM through [PyScript](https://pyscript.net) (or rather [Pyodide](https://pyodide.org/en/stable/))
|
|
110
|
+
|
|
111
|
+
It is possible to create a custom Renderer using the [Renderer](collagraph/renderers/__init__.py) interface, to render to other UI frameworks, for instance wxPython.
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
To try out Collagraph or start development, run:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
# Basic dev setup (no pygfx or pyside)
|
|
120
|
+
poetry install
|
|
121
|
+
# Full dev setup
|
|
122
|
+
poetry install --with pyside --extras pyside --extras pygfx
|
|
123
|
+
# Run example:
|
|
124
|
+
poetry run python examples/pyside/layout-example.py
|
|
125
|
+
# Run test suite:
|
|
126
|
+
poetry run pytest
|
|
127
|
+
# Install git pre-commit hooks to make sure tests/linting passes before committing
|
|
128
|
+
poetry run pre-commit install
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
### Syntax Highlighting
|
|
133
|
+
|
|
134
|
+
Syntax highlighting for single-file components (`.cgx`) is supported for VSCode and Sublime Text:
|
|
135
|
+
|
|
136
|
+
* [CGX syntax highlight for Sublime Text](https://github.com/fork-tongue/cgx-syntax-highlight-sublime)
|
|
137
|
+
* [CGX syntax highlight for VSCode](https://github.com/fork-tongue/cgx-syntax-highlight-vscode)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
### Formatting and linting
|
|
141
|
+
|
|
142
|
+
Linting cgx files is possible with a flake8 plugin: [flake8-cgx](https://github.com/fork-tongue/flake8-cgx).
|
|
143
|
+
Formatting the contents of the script tag can be done with [black-cgx](https://github.com/fork-tongue/black-cgx).
|
|
144
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
[](https://badge.fury.io/py/collagraph)
|
|
2
|
+
[](https://github.com/fork-tongue/collagraph/actions)
|
|
3
|
+
|
|
4
|
+
# Collagraph 📓
|
|
5
|
+
|
|
6
|
+
Reactive user interfaces.
|
|
7
|
+
|
|
8
|
+
> The word [Collagraphy](https://en.wikipedia.org/wiki/Collagraphy) is derived from the Greek word _koll_ or _kolla_, meaning glue, and graph, meaning the activity of drawing.
|
|
9
|
+
|
|
10
|
+
Inspired by Vue and React.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
Write your Python interfaces in a declarative manner with plain render functions, component classes or even single-file components using Vue-like syntax, but with Python!
|
|
16
|
+
|
|
17
|
+
* Reactivity (made possible by leveraging [observ](https://github.com/fork-tongue/observ))
|
|
18
|
+
* Function components
|
|
19
|
+
* Class components with local state and life-cycle methods/hooks
|
|
20
|
+
* Single-file components with Vue-like template syntax (`.cgx` files)
|
|
21
|
+
* Custom renderers
|
|
22
|
+
|
|
23
|
+
Here is an example that shows a counter, made with a component with Vue-like syntax:
|
|
24
|
+
|
|
25
|
+
Contents of `counter.cgx`:
|
|
26
|
+
```html
|
|
27
|
+
<template>
|
|
28
|
+
<widget>
|
|
29
|
+
<label
|
|
30
|
+
:text="f'Count: {count}'"
|
|
31
|
+
/>
|
|
32
|
+
<button
|
|
33
|
+
text="bump"
|
|
34
|
+
@clicked="bump"
|
|
35
|
+
/>
|
|
36
|
+
</widget>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<script>
|
|
40
|
+
import collagraph as cg
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Counter(cg.Component):
|
|
44
|
+
def __init__(self, *args, **kwargs):
|
|
45
|
+
super().__init__(*args, **kwargs)
|
|
46
|
+
self.state["count"] = 0
|
|
47
|
+
|
|
48
|
+
def bump(self):
|
|
49
|
+
self.state["count"] += 1
|
|
50
|
+
</script>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Contents of `app.py`:
|
|
54
|
+
```python
|
|
55
|
+
from PySide6 import QtWidgets
|
|
56
|
+
import collagraph as cg
|
|
57
|
+
|
|
58
|
+
# After importing collagraph, it's possible to import
|
|
59
|
+
# components directly from .cgx files
|
|
60
|
+
from counter import Counter
|
|
61
|
+
|
|
62
|
+
# Create a Collagraph instance with a PySide renderer
|
|
63
|
+
# and register with the Qt event loop
|
|
64
|
+
gui = cg.Collagraph(renderer=cg.PySideRenderer())
|
|
65
|
+
# Render the component into a container
|
|
66
|
+
# (in this case the app but can be another widget)
|
|
67
|
+
app = QtWidgets.QApplication()
|
|
68
|
+
gui.render(cg.h(Counter), app)
|
|
69
|
+
app.exec()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Which looks something like this:
|
|
73
|
+
|
|
74
|
+

|
|
75
|
+
|
|
76
|
+
Instead of using a python file as an entry point to run components, you can run them directly using the collagraph CLI:
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
poetry run collagraph examples/pyside/counter.cgx
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
For more examples, please take a look at the [examples folder](examples).
|
|
83
|
+
|
|
84
|
+
Currently there are three renderers:
|
|
85
|
+
|
|
86
|
+
* [PysideRenderer](collagraph/renderers/pyside_renderer.py): for rendering PySide6 applications
|
|
87
|
+
* [PygfxRenderer](collagraph/renderers/pygfx_renderer.py): for rendering 3D graphic scenes with [Pygfx](https://github.com/pygfx/pygfx)
|
|
88
|
+
* [DomRenderer](collagraph/renderers/dom_renderer.py): for rendering to browser DOM through [PyScript](https://pyscript.net) (or rather [Pyodide](https://pyodide.org/en/stable/))
|
|
89
|
+
|
|
90
|
+
It is possible to create a custom Renderer using the [Renderer](collagraph/renderers/__init__.py) interface, to render to other UI frameworks, for instance wxPython.
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
## Development
|
|
94
|
+
|
|
95
|
+
To try out Collagraph or start development, run:
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
# Basic dev setup (no pygfx or pyside)
|
|
99
|
+
poetry install
|
|
100
|
+
# Full dev setup
|
|
101
|
+
poetry install --with pyside --extras pyside --extras pygfx
|
|
102
|
+
# Run example:
|
|
103
|
+
poetry run python examples/pyside/layout-example.py
|
|
104
|
+
# Run test suite:
|
|
105
|
+
poetry run pytest
|
|
106
|
+
# Install git pre-commit hooks to make sure tests/linting passes before committing
|
|
107
|
+
poetry run pre-commit install
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
### Syntax Highlighting
|
|
112
|
+
|
|
113
|
+
Syntax highlighting for single-file components (`.cgx`) is supported for VSCode and Sublime Text:
|
|
114
|
+
|
|
115
|
+
* [CGX syntax highlight for Sublime Text](https://github.com/fork-tongue/cgx-syntax-highlight-sublime)
|
|
116
|
+
* [CGX syntax highlight for VSCode](https://github.com/fork-tongue/cgx-syntax-highlight-vscode)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
### Formatting and linting
|
|
120
|
+
|
|
121
|
+
Linting cgx files is possible with a flake8 plugin: [flake8-cgx](https://github.com/fork-tongue/flake8-cgx).
|
|
122
|
+
Formatting the contents of the script tag can be done with [black-cgx](https://github.com/fork-tongue/black-cgx).
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import importlib
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from observ import reactive
|
|
7
|
+
|
|
8
|
+
import collagraph as cg
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def available_renderers():
|
|
12
|
+
result = set()
|
|
13
|
+
for renderer_type, name in {
|
|
14
|
+
"PySideRenderer": "pyside",
|
|
15
|
+
"PygfxRenderer": "pygfx",
|
|
16
|
+
"DictRenderer": "dict",
|
|
17
|
+
# TODO: add support for DomRenderer
|
|
18
|
+
# "DomRenderer": "dom",
|
|
19
|
+
}.items():
|
|
20
|
+
try:
|
|
21
|
+
importlib.import_module("collagraph", renderer_type)
|
|
22
|
+
result.add(name)
|
|
23
|
+
except ImportError:
|
|
24
|
+
continue
|
|
25
|
+
return result
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def init_collagraph(renderer_type: str, component_path: Path, state: dict = None):
|
|
29
|
+
Component, _ = cg.cgx.cgx.load(component_path)
|
|
30
|
+
props = reactive(state or {})
|
|
31
|
+
|
|
32
|
+
if renderer_type == "pygfx":
|
|
33
|
+
import pygfx as gfx
|
|
34
|
+
from wgpu.gui.auto import run, WgpuCanvas
|
|
35
|
+
|
|
36
|
+
canvas = WgpuCanvas(size=(600, 400))
|
|
37
|
+
wgpu_renderer = gfx.renderers.WgpuRenderer(canvas)
|
|
38
|
+
|
|
39
|
+
camera = gfx.PerspectiveCamera(70, 16 / 9)
|
|
40
|
+
camera.position.z = 15
|
|
41
|
+
|
|
42
|
+
controls = gfx.OrbitController(camera.position.clone())
|
|
43
|
+
controls.add_default_event_handlers(wgpu_renderer, camera)
|
|
44
|
+
|
|
45
|
+
container = gfx.Scene()
|
|
46
|
+
|
|
47
|
+
def animate():
|
|
48
|
+
controls.update_camera(camera)
|
|
49
|
+
wgpu_renderer.render(container, camera)
|
|
50
|
+
|
|
51
|
+
gui = cg.Collagraph(renderer=cg.PygfxRenderer())
|
|
52
|
+
gui.render(
|
|
53
|
+
cg.h(Component, props),
|
|
54
|
+
container,
|
|
55
|
+
callback=lambda: canvas.request_draw(animate),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
run()
|
|
59
|
+
elif renderer_type == "pyside":
|
|
60
|
+
from PySide6 import QtWidgets
|
|
61
|
+
|
|
62
|
+
app = QtWidgets.QApplication()
|
|
63
|
+
gui = cg.Collagraph(renderer=cg.PySideRenderer())
|
|
64
|
+
gui.render(cg.h(Component, props), app)
|
|
65
|
+
app.exec()
|
|
66
|
+
elif renderer_type == "dict":
|
|
67
|
+
container = {"root": None}
|
|
68
|
+
gui = cg.Collagraph(
|
|
69
|
+
renderer=cg.DictRenderer(),
|
|
70
|
+
event_loop_type=cg.EventLoopType.SYNC,
|
|
71
|
+
)
|
|
72
|
+
gui.render(cg.h(Component, props), container)
|
|
73
|
+
# Start debugger to allow for inspection of container
|
|
74
|
+
# and manipulation of props
|
|
75
|
+
breakpoint()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def existing_component_file(value):
|
|
79
|
+
path = Path(value)
|
|
80
|
+
if not path.exists():
|
|
81
|
+
raise argparse.ArgumentTypeError(f"{value} does not exist")
|
|
82
|
+
if not path.is_file():
|
|
83
|
+
raise argparse.ArgumentTypeError(f"{value} is not a file")
|
|
84
|
+
if path.suffix != ".cgx":
|
|
85
|
+
raise argparse.ArgumentTypeError(f"{value} is not a collagraph component")
|
|
86
|
+
return path
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def json_contents(value):
|
|
90
|
+
path = Path(value)
|
|
91
|
+
if path.is_file():
|
|
92
|
+
with path.open(mode="r", encoding="utf-8") as fh:
|
|
93
|
+
try:
|
|
94
|
+
return json.load(fh)
|
|
95
|
+
except Exception:
|
|
96
|
+
raise argparse.ArgumentTypeError(f"{value} is not valid json")
|
|
97
|
+
else:
|
|
98
|
+
try:
|
|
99
|
+
return json.loads(value)
|
|
100
|
+
except Exception:
|
|
101
|
+
raise argparse.ArgumentTypeError(f"{value} is not valid json")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def run():
|
|
105
|
+
parser = argparse.ArgumentParser(
|
|
106
|
+
description="Run collagraph components directly",
|
|
107
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
108
|
+
)
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
"--renderer",
|
|
111
|
+
default="pyside",
|
|
112
|
+
choices=available_renderers(),
|
|
113
|
+
help="The type of renderer to use",
|
|
114
|
+
)
|
|
115
|
+
parser.add_argument(
|
|
116
|
+
"--state",
|
|
117
|
+
type=json_contents,
|
|
118
|
+
help="Optional state/props to load (json file or string)",
|
|
119
|
+
)
|
|
120
|
+
parser.add_argument(
|
|
121
|
+
"component",
|
|
122
|
+
type=existing_component_file,
|
|
123
|
+
help="Path to component to render",
|
|
124
|
+
)
|
|
125
|
+
args = parser.parse_args()
|
|
126
|
+
|
|
127
|
+
init_collagraph(args.renderer, args.component, args.state)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
if __name__ == "__main__":
|
|
131
|
+
run()
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from PyInstaller.utils.hooks import collect_data_files
|
|
5
|
+
|
|
6
|
+
from collagraph.cgx.cgx import CGXParser, get_script_ast
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def hook(hook_api):
|
|
10
|
+
collagraph_uses = hook_api.analysis.graph.get_code_using("collagraph")
|
|
11
|
+
|
|
12
|
+
hidden_imports = set()
|
|
13
|
+
datas = []
|
|
14
|
+
for package, code in collagraph_uses.items():
|
|
15
|
+
filename = Path(code.co_filename)
|
|
16
|
+
hidden_imports |= collect_hidden_imports(filename.parent)
|
|
17
|
+
datas += collect_data_files(package, includes=["**/*.cgx"])
|
|
18
|
+
|
|
19
|
+
hook_api.add_imports(*hidden_imports)
|
|
20
|
+
hook_api.add_datas(datas)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def collect_hidden_imports(folder):
|
|
24
|
+
folder = Path(folder)
|
|
25
|
+
|
|
26
|
+
hidden_imports = set()
|
|
27
|
+
for path in folder.glob("**/*.cgx"):
|
|
28
|
+
template = path.read_text()
|
|
29
|
+
# Parse the file component into a tree of Node instances
|
|
30
|
+
parser = CGXParser()
|
|
31
|
+
parser.feed(template)
|
|
32
|
+
|
|
33
|
+
# Get the AST from the script tag
|
|
34
|
+
script_tree = get_script_ast(parser, path)
|
|
35
|
+
|
|
36
|
+
# Find a list of imported names (or aliases, if any)
|
|
37
|
+
# Those names don't have to be wrapped by `_lookup`
|
|
38
|
+
imported_names = ImportsCollector()
|
|
39
|
+
imported_names.visit(script_tree)
|
|
40
|
+
|
|
41
|
+
hidden_imports |= imported_names.names
|
|
42
|
+
|
|
43
|
+
return hidden_imports
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ImportsCollector(ast.NodeVisitor):
|
|
47
|
+
def __init__(self):
|
|
48
|
+
self.names = set()
|
|
49
|
+
|
|
50
|
+
def visit_ImportFrom(self, node):
|
|
51
|
+
for alias in node.names:
|
|
52
|
+
self.names.add(".".join([node.module, alias.name]))
|
|
53
|
+
self.names.add(node.module)
|
|
54
|
+
|
|
55
|
+
def visit_Import(self, node):
|
|
56
|
+
for alias in node.names:
|
|
57
|
+
self.names.add(alias.name)
|