Skip to content

Commit 1fd1114

Browse files
committed
v2.5.0 more docs
1 parent 6aa4d5c commit 1fd1114

File tree

10 files changed

+180
-68
lines changed

10 files changed

+180
-68
lines changed

_modules/edifice/engine.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,8 @@ <h1>Source code for edifice.engine</h1><div class="highlight"><pre>
973973
<span class="sd"> The **props** are the arguments passed to the :func:`@component&lt;component&gt;` function.</span>
974974

975975
<span class="sd"> The :func:`@component&lt;component&gt;` will be re-rendered when some of its **props** are not</span>
976-
<span class="sd"> :code:`__eq__` to the **props** from the last time the @component rendered.</span>
976+
<span class="sd"> :code:`__eq__` to the **props** from the last time the</span>
977+
<span class="sd"> :func:`@component&lt;component&gt;` rendered.</span>
977978
<span class="sd"> If the **props** are all :code:`__eq__`, the :func:`@component&lt;component&gt;`</span>
978979
<span class="sd"> will not re-render.</span>
979980

_modules/edifice/hooks.html

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,8 @@ <h1>Source code for edifice.hooks</h1><div class="highlight"><pre>
449449

450450
<span class="sd"> An **initializer function** is a function of no arguments.</span>
451451

452-
<span class="sd"> If an **initializer function** is passed to :func:`use_state`, then the</span>
452+
<span class="sd"> If an **initializer function** is passed to :func:`use_state` instead</span>
453+
<span class="sd"> of an initial value, then the</span>
453454
<span class="sd"> **initializer function** will be called once before</span>
454455
<span class="sd"> this :func:`components`’s first render to get the **initial state**.</span>
455456

@@ -512,11 +513,20 @@ <h1>Source code for edifice.hooks</h1><div class="highlight"><pre>
512513
<span class="sd"> Do not mutate the state variable. The old state variable must be left</span>
513514
<span class="sd"> unmodified so that it can be compared to the new state variable during</span>
514515
<span class="sd"> the next render.</span>
515-
<span class="sd"> Instead create a shallow `copy &lt;https://docs.python.org/3/library/copy.html#copy.copy&gt;`_</span>
516-
<span class="sd"> of the state, modify the copy, then call the **setter function** with the modified copy.</span>
516+
517+
<span class="sd"> If Python does not have an</span>
518+
<span class="sd"> `immutable &lt;https://docs.python.org/3/glossary.html#term-immutable&gt;`_</span>
519+
<span class="sd"> version of your state data structure,</span>
520+
<span class="sd"> like for example the :code:`dict`, then you just have to take care to never</span>
521+
<span class="sd"> mutate it.</span>
522+
523+
<span class="sd"> Instead of mutating a state :code:`list`, create a</span>
524+
<span class="sd"> shallow `copy &lt;https://docs.python.org/3/library/copy.html#copy.copy&gt;`_</span>
525+
<span class="sd"> of the :code:`list`, modify the copy, then call the **setter function**</span>
526+
<span class="sd"> with the modified copy.</span>
517527

518528
<span class="sd"> .. code-block:: python</span>
519-
<span class="sd"> :caption: Updater function with shallow copy</span>
529+
<span class="sd"> :caption: Updater function with shallow copy of a list</span>
520530

521531
<span class="sd"> from copy import copy</span>
522532
<span class="sd"> from typing import cast</span>
@@ -537,12 +547,35 @@ <h1>Source code for edifice.hooks</h1><div class="highlight"><pre>
537547
<span class="sd"> for t in x:</span>
538548
<span class="sd"> Label(text=t)</span>
539549

540-
<span class="sd"> A good technique for declaring immutable state datastructures is to use</span>
541-
<span class="sd"> `frozen dataclasses &lt;https://docs.python.org/3/library/dataclasses.html#frozen-instances&gt;`_.</span>
542-
<span class="sd"> Use the</span>
543-
<span class="sd"> `replace() &lt;https://docs.python.org/3/library/dataclasses.html#dataclasses.replace&gt;`_</span>
544-
<span class="sd"> function to update the dataclass.</span>
550+
<span class="sd"> Techniques for `immutable &lt;https://docs.python.org/3/glossary.html#term-immutable&gt;`_ datastructures in Python</span>
551+
<span class="sd"> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span>
552+
553+
<span class="sd"> - `Shallow copy &lt;https://docs.python.org/3/library/copy.html#copy.copy&gt;`_.</span>
554+
<span class="sd"> We never need a deep copy because all the data structure items are also immutable.</span>
555+
<span class="sd"> - `Frozen dataclasses &lt;https://docs.python.org/3/library/dataclasses.html#frozen-instances&gt;`_.</span>
556+
<span class="sd"> Use the</span>
557+
<span class="sd"> `replace() &lt;https://docs.python.org/3/library/dataclasses.html#dataclasses.replace&gt;`_</span>
558+
<span class="sd"> function to update the dataclass.</span>
559+
<span class="sd"> - Tuples (:code:`my_list:tuple[str, ...]`) instead of lists (:code:`my_list:list[str]`).</span>
560+
561+
<span class="sd"> .. code-block:: python</span>
562+
<span class="sd"> :caption: Updater function with shallow copy of a tuple</span>
563+
564+
<span class="sd"> from typing import cast</span>
565+
566+
<span class="sd"> def Stateful(self):</span>
567+
<span class="sd"> x, x_setter = use_state(cast(tuple[str, ...], ()))</span>
568+
569+
<span class="sd"> def updater(x_previous:tuple[str, ...]) -&gt; tuple[str, ...]:</span>
570+
<span class="sd"> return x_previous + (&quot;Label Text &quot; + str(len(x_previous)),)</span>
545571

572+
<span class="sd"> with View():</span>
573+
<span class="sd"> Button(</span>
574+
<span class="sd"> title=&quot;Add One&quot;,</span>
575+
<span class="sd"> on_click = lambda _event: x_setter(updater)</span>
576+
<span class="sd"> )</span>
577+
<span class="sd"> for t in x:</span>
578+
<span class="sd"> Label(text=t)</span>
546579
<span class="sd"> Args:</span>
547580
<span class="sd"> initial_state: The initial **state value** or **initializer function**.</span>
548581
<span class="sd"> Returns:</span>
@@ -653,19 +686,26 @@ <h1>Source code for edifice.hooks</h1><div class="highlight"><pre>
653686
<span class="sd"> :caption: use_async to fetch from the network</span>
654687

655688
<span class="sd"> @component</span>
656-
<span class="sd"> def Asynchronous(self):</span>
657-
<span class="sd"> myword, myword_set = use_state(&quot;&quot;)</span>
689+
<span class="sd"> def WordDefinition(self, word:str):</span>
690+
<span class="sd"> definition, definition_set = use_state(&quot;&quot;)</span>
658691

659692
<span class="sd"> async def fetcher():</span>
660693
<span class="sd"> try:</span>
661-
<span class="sd"> x = await fetch_word_from_the_internet()</span>
662-
<span class="sd"> myword_set(x)</span>
694+
<span class="sd"> definition_set(&quot;Fetch definition pending&quot;)</span>
695+
<span class="sd"> x = await fetch_definition_from_the_internet(word)</span>
696+
<span class="sd"> definition_set(x)</span>
663697
<span class="sd"> except asyncio.CancelledError:</span>
664-
<span class="sd"> myword_set(&quot;Fetch word cancelled&quot;)</span>
698+
<span class="sd"> definition_set(&quot;Fetch definition cancelled&quot;)</span>
665699
<span class="sd"> raise</span>
700+
<span class="sd"> except BaseException:</span>
701+
<span class="sd"> defintion_set(&quot;Fetch definition failed&quot;)</span>
702+
703+
<span class="sd"> cancel_fetcher = use_async(fetcher, word)</span>
666704

667-
<span class="sd"> _cancel_fetcher = use_async(fetcher, 0)</span>
668-
<span class="sd"> Label(text=myword)</span>
705+
<span class="sd"> with VBoxView():</span>
706+
<span class="sd"> Label(text=word)</span>
707+
<span class="sd"> Label(text=definition)</span>
708+
<span class="sd"> Button(text=&quot;Cancel fetch&quot;, on_click=lambda _:cancel_fetcher())</span>
669709

670710
<span class="sd"> Cancellation</span>
671711
<span class="sd"> ============</span>

_sources/edifice.rst.txt

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,19 @@ Declaring an Element tree in a :func:`@component <component>` Element render fun
5959
like this.
6060
To declare an Element to be the parent of some other
6161
child Elements in the tree, use the parent as a
62-
`with statement context manager <https://docs.python.org/3/reference/datamodel.html#context-managers>`_::
62+
`with statement context manager <https://docs.python.org/3/reference/datamodel.html#context-managers>`_.
63+
64+
.. code-block:: python
6365
6466
@component
6567
def MyApp(self):
6668
with Window():
6769
with VBoxView():
6870
with HBoxView():
69-
Label("Username: ")
71+
Label(text="Username: ")
7072
TextInput()
7173
with HBoxView():
72-
Label("Email: ")
74+
Label(text="Email: ")
7375
TextInput()
7476
7577
In HTML/XML/JSX, this would be written as:
@@ -85,6 +87,7 @@ In HTML/XML/JSX, this would be written as:
8587
<HBoxView>
8688
<Label text="Email: " />
8789
<TextInput />
90+
</HBoxView>
8891
</VBoxView>
8992
</Window>
9093
@@ -225,19 +228,23 @@ Element tree.
225228

226229
Because Element initialization is a render side-effect,
227230
we have to be careful about binding Elements to variables
228-
and passing them around. They will insert themselves at the time they are
229-
created. This code will **NOT** declare the intended Element tree::
231+
and passing them around. They will insert themselves in the tree at the time
232+
they are initialized. This code will **NOT** declare the intended Element tree.
233+
234+
.. code-block:: python
230235
231236
@component
232237
def MySimpleComp(self, prop1, prop2, prop3):
233238
label3 = Label(text=prop3)
234239
with VBoxView():
235240
Label(text=prop1)
236241
Label(text=prop2)
237-
label3
242+
label3 # This will NOT render here as intended
238243
239244
To solve this, defer the construction of the Element with a lambda function.
240-
This code will declare the same intended Element tree as the code above::
245+
This code will declare the same intended Element tree as the code above.
246+
247+
.. code-block:: python
241248
242249
@component
243250
def MySimpleComp(self, prop1, prop2, prop3):
@@ -248,7 +255,9 @@ This code will declare the same intended Element tree as the code above::
248255
label3()
249256
250257
If these component Elements are render functions, then why couldn’t we just write
251-
a normal render function with no decorator instead::
258+
a normal render function with no decorator instead?
259+
260+
.. code-block:: python
252261
253262
# No decorator
254263
def MySimpleComp(prop1, prop2, prop3):

_sources/index.rst.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ Table of Contents
8181
Why Edifice?
8282
------------
8383

84-
**Declarative**
84+
Declarative
85+
^^^^^^^^^^^
8586

8687
Most existing GUI libraries in Python, such as Tkinter and Qt, operate imperatively.
8788
To create a dynamic application using these libraries,
@@ -112,14 +113,16 @@ a button and a label with the current value of :code:`number`.
112113
Clicking the button will add 5 to the :code:`number`.
113114
If the :code:`number` is “mid” then another label will reveal that fact.
114115

115-
**Developer Tools**
116+
Developer Tools
117+
^^^^^^^^^^^^^^^
116118

117119
- Dynamic hot-reloading of source code changes.
118120
- Element Inspector.
119121

120122
See :doc:`developer_tools` for more details.
121123

122-
**Edifice vs. Qt Quick**
124+
Edifice vs. Qt Quick
125+
^^^^^^^^^^^^^^^^^^^^
123126

124127
`Qt Quick <https://doc.qt.io/qtforpython-6/PySide6/QtQuick/>`_ is Qt’s declarative GUI framework for Qt.
125128

@@ -139,7 +142,8 @@ they require imperative logic in another language for dynamism.
139142
Edifice and React allow fully dynamic applications to be specified
140143
declaratively in one language.
141144

142-
**Extendable**
145+
Extendable
146+
^^^^^^^^^^
143147

144148
Edifice does not support every feature of Qt,
145149
but it is easy to interface with Qt, either :ref:`incorporating a Qt Widget<custom_widget>` into an Edifice component,

edifice.html

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -440,16 +440,16 @@ <h2>Declaring Element Trees<a class="headerlink" href="#declaring-element-trees"
440440
like this.
441441
To declare an Element to be the parent of some other
442442
child Elements in the tree, use the parent as a
443-
<a class="reference external" href="https://docs.python.org/3/reference/datamodel.html#context-managers">with statement context manager</a>:</p>
444-
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@component</span>
443+
<a class="reference external" href="https://docs.python.org/3/reference/datamodel.html#context-managers">with statement context manager</a>.</p>
444+
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@component</span>
445445
<span class="k">def</span> <span class="nf">MyApp</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
446446
<span class="k">with</span> <span class="n">Window</span><span class="p">():</span>
447447
<span class="k">with</span> <span class="n">VBoxView</span><span class="p">():</span>
448448
<span class="k">with</span> <span class="n">HBoxView</span><span class="p">():</span>
449-
<span class="n">Label</span><span class="p">(</span><span class="s2">&quot;Username: &quot;</span><span class="p">)</span>
449+
<span class="n">Label</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="s2">&quot;Username: &quot;</span><span class="p">)</span>
450450
<span class="n">TextInput</span><span class="p">()</span>
451451
<span class="k">with</span> <span class="n">HBoxView</span><span class="p">():</span>
452-
<span class="n">Label</span><span class="p">(</span><span class="s2">&quot;Email: &quot;</span><span class="p">)</span>
452+
<span class="n">Label</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="s2">&quot;Email: &quot;</span><span class="p">)</span>
453453
<span class="n">TextInput</span><span class="p">()</span>
454454
</pre></div>
455455
</div>
@@ -463,6 +463,7 @@ <h2>Declaring Element Trees<a class="headerlink" href="#declaring-element-trees"
463463
<span class="w"> </span><span class="nt">&lt;HBoxView&gt;</span>
464464
<span class="w"> </span><span class="nt">&lt;Label</span><span class="w"> </span><span class="na">text=</span><span class="s">&quot;Email: &quot;</span><span class="w"> </span><span class="nt">/&gt;</span>
465465
<span class="w"> </span><span class="nt">&lt;TextInput</span><span class="w"> </span><span class="nt">/&gt;</span>
466+
<span class="w"> </span><span class="nt">&lt;/HBoxView&gt;</span>
466467
<span class="w"> </span><span class="nt">&lt;/VBoxView&gt;</span>
467468
<span class="nt">&lt;/Window&gt;</span>
468469
</pre></div>
@@ -588,20 +589,20 @@ <h2>Element initialization is a render side-effect<a class="headerlink" href="#e
588589
Element tree.</p>
589590
<p>Because Element initialization is a render side-effect,
590591
we have to be careful about binding Elements to variables
591-
and passing them around. They will insert themselves at the time they are
592-
created. This code will <strong>NOT</strong> declare the intended Element tree:</p>
593-
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@component</span>
592+
and passing them around. They will insert themselves in the tree at the time
593+
they are initialized. This code will <strong>NOT</strong> declare the intended Element tree.</p>
594+
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@component</span>
594595
<span class="k">def</span> <span class="nf">MySimpleComp</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">prop1</span><span class="p">,</span> <span class="n">prop2</span><span class="p">,</span> <span class="n">prop3</span><span class="p">):</span>
595596
<span class="n">label3</span> <span class="o">=</span> <span class="n">Label</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="n">prop3</span><span class="p">)</span>
596597
<span class="k">with</span> <span class="n">VBoxView</span><span class="p">():</span>
597598
<span class="n">Label</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="n">prop1</span><span class="p">)</span>
598599
<span class="n">Label</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="n">prop2</span><span class="p">)</span>
599-
<span class="n">label3</span>
600+
<span class="n">label3</span> <span class="c1"># This will NOT render here as intended</span>
600601
</pre></div>
601602
</div>
602603
<p>To solve this, defer the construction of the Element with a lambda function.
603-
This code will declare the same intended Element tree as the code above:</p>
604-
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@component</span>
604+
This code will declare the same intended Element tree as the code above.</p>
605+
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@component</span>
605606
<span class="k">def</span> <span class="nf">MySimpleComp</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">prop1</span><span class="p">,</span> <span class="n">prop2</span><span class="p">,</span> <span class="n">prop3</span><span class="p">):</span>
606607
<span class="n">label3</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">Label</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="n">prop3</span><span class="p">)</span>
607608
<span class="k">with</span> <span class="n">VBoxView</span><span class="p">():</span>
@@ -611,8 +612,8 @@ <h2>Element initialization is a render side-effect<a class="headerlink" href="#e
611612
</pre></div>
612613
</div>
613614
<p>If these component Elements are render functions, then why couldn’t we just write
614-
a normal render function with no decorator instead:</p>
615-
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># No decorator</span>
615+
a normal render function with no decorator instead?</p>
616+
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># No decorator</span>
616617
<span class="k">def</span> <span class="nf">MySimpleComp</span><span class="p">(</span><span class="n">prop1</span><span class="p">,</span> <span class="n">prop2</span><span class="p">,</span> <span class="n">prop3</span><span class="p">):</span>
617618
<span class="k">with</span> <span class="n">VBoxView</span><span class="p">():</span>
618619
<span class="n">Label</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="n">prop1</span><span class="p">)</span>

0 commit comments

Comments
 (0)