pypage 2.0.8__tar.gz → 2.1.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.
@@ -1,15 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pypage
3
- Version: 2.0.8
3
+ Version: 2.1.0
4
4
  Summary: Light-weight Python Templating Engine
5
5
  Home-page: https://github.com/arjun-menon/pypage
6
- Download-URL: https://github.com/arjun-menon/pypage/archive/v2.0.8.tar.gz
6
+ Download-URL: https://github.com/arjun-menon/pypage/archive/v2.1.0.tar.gz
7
7
  Author: Arjun G. Menon
8
8
  Author-email: contact@arjungmenon.com
9
- License: Apache
10
- Keywords: templating enigne text processing static generator
9
+ License: Apache-2.0
10
+ Keywords: templating engine text processing static generator,templating engine,text processing,template,templates
11
11
  Classifier: Topic :: Text Processing
12
+ Classifier: Intended Audience :: Developers
12
13
  Classifier: Topic :: Internet :: WWW/HTTP
14
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
13
15
  Classifier: Topic :: Text Processing :: Markup :: HTML
14
16
  Classifier: License :: OSI Approved :: Apache Software License
15
17
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -20,26 +22,22 @@ Classifier: Operating System :: OS Independent
20
22
  Classifier: Programming Language :: Python :: Implementation :: CPython
21
23
  Classifier: Programming Language :: Python :: Implementation :: PyPy
22
24
  Classifier: Programming Language :: Python :: 2
23
- Classifier: Programming Language :: Python :: 2.7
24
25
  Classifier: Programming Language :: Python :: 3
25
- Classifier: Programming Language :: Python :: 3.2
26
- Classifier: Programming Language :: Python :: 3.3
27
- Classifier: Programming Language :: Python :: 3.4
28
- Classifier: Programming Language :: Python :: 3.5
29
26
  License-File: LICENSE.txt
30
27
 
31
- pypage |pypi| |docs|
32
- ====================
28
+ PyPage |pypi| |docs| |test|
29
+ ===========================
33
30
 
34
- pypage is a document template engine for Python programmers with a
31
+ PyPage is a document template engine for Python programmers with a
35
32
  short learning curve.
36
33
 
37
- **Why use pypage?**
34
+ **Why use PyPage?**
38
35
 
39
36
  - Easy to pick up. Syntax similar to Python's.
40
37
  - You need an eval-based template engine.
41
38
 
42
- pypage supports Python 3.x and 2.7, and has been on CPython and PyPy.
39
+ PyPage supports Python 3.x and 2.7, and has been tested
40
+ (using `test_cmd <https://github.com/arjun-menon/test_cmd>`_) on CPython and PyPy.
43
41
 
44
42
  **What does it look like?**
45
43
 
@@ -56,7 +54,7 @@ pypage supports Python 3.x and 2.7, and has been on CPython and PyPy.
56
54
 
57
55
  **Installation**
58
56
 
59
- You can `install <https://docs.python.org/3/installing/>`_ pypage easily with `pip <https://pip.pypa.io/en/stable/>`_:
57
+ You can `install <https://docs.python.org/3/installing/>`_ PyPage easily with `pip <https://pip.pypa.io/en/stable/>`_:
60
58
 
61
59
  .. code::
62
60
 
@@ -64,6 +62,29 @@ You can `install <https://docs.python.org/3/installing/>`_ pypage easily with `p
64
62
 
65
63
  Try running ``pypage -h`` to see the command-line options available.
66
64
 
65
+
66
+ **Why another templating language?**
67
+
68
+ PyPage is lets you embed Python code easily and flexibly in textual documents (such as Markdown_, HTML, reStructuredText_, plain text, etc). It lets you construct powerful programmatically-generated documents by embedding Python code in an elegant and flexible manner. Its syntax is similar to and partially inspired by the templating languages Jinja_ and Liquid_.
69
+
70
+ While there are many templating engines out there, the primarily advantage of PyPage is the fact that its syntax is very close to Python's, and therefore the learning curve is very short for Python programmers.
71
+
72
+ Rather than create a new mini domain-specific language for constructs such as ``for`` and ``if``, PyPage does a teeny tiny bit of obvious string manipulation, and passes your logical directives unaltered to the Python interpreter. As such, PyPage inherits Python's syntax for the most part. For example, ``for`` loops in PyPage get converted into Python's generator expressions. The ``for`` loop in a Python generator expression (or list comprehension) is far more powerful than its regular ``for`` loop. This means that PyPage ``for`` loops are richer and more expressive than you'd otherwise expect, while the learning curve is nearly non-existent.
73
+
74
+ The primary disadvantage of using PyPage instead of a templating engine like Liquid is that PyPage does not operate on a restricted non-Turing-complete subset of programming languages, as Liquid for instance does. Liquid allows untrusted users to write and upload their own templates, because the expressiveness of Liquid is limited such that there is an implicit guarantee that the template will be processed in a reasonable (probably linear) amount of time using a reasonable amount of system resources. As such, Liquid's templating language is rather limited -- it offers a limited number of pre-defined functions/filters, and the overall flexibility of the language has been constrained in order to guarantee termination in a reasonable amount of time.
75
+
76
+ PyPage, on the other hand gives the template writer full unfettered access to the Python interpreter. As such, PyPage is meant only for use in trusted contexts (or containers), and in some ways it's similar to PHP in that a you're mixing a full-blown programming language (Python) and text that could be HTML.
77
+
78
+ This brings us to another topic: mixing code and UI. It is generally frowned upon to mix logic/code and the UI (or "view"). So it is good practise to not do any intelligent processing within your PyPage template. Instead, you can do it in a separate program, and pass an *environment* containing the results, to PyPage. An environment is a dictionary of variables that is passed to Python's ``exec``, and is therefore accessible from all of the code in the PyPage template. From within your template you can focus solely on how to transform these input variables into the HTML/rST/other page you're building.
79
+
80
+ A pleasant aspect of PyPage, in comparison to other templating languages is that you don't have to learn much new syntax. It's probably the easiest to learn and most *flexible* templating language out there. It is highly flexible because of the plethora of easy-to-use powerful constructs that PyPage offers.
81
+
82
+ .. _Markdown: https://en.wikipedia.org/wiki/Markdown
83
+ .. _reStructuredText: http://docutils.sourceforge.net/docs/user/rst/quickref.html
84
+ .. _Liquid: https://github.com/Shopify/liquid/wiki/Liquid-for-Designers
85
+ .. _Jinja: https://github.com/pallets/jinja
86
+
87
+
67
88
  .. contents:: **Table of Contents**
68
89
 
69
90
 
@@ -85,7 +106,7 @@ example of an inline code tag:
85
106
 
86
107
  There are {{ 5 + 2 }} days in a week.
87
108
 
88
- The above, when processed by pypage, yields:
109
+ The above, when processed by PyPage, yields:
89
110
 
90
111
  ::
91
112
 
@@ -127,7 +148,7 @@ for all code tags in the same file.
127
148
 
128
149
  As such, a variable instantiated in a code tag at the
129
150
  beginning of the document, will be available to all other code tags in
130
- the document. When pypage is invoked as library, an initial seed
151
+ the document. When PyPage is invoked as library, an initial seed
131
152
  environment consisting of a Python dictionary mapping variable names to
132
153
  values, can be provided.
133
154
 
@@ -198,7 +219,7 @@ It's best to explain this with an example:
198
219
  {% %}
199
220
 
200
221
  When the above template is run, the resulting page will contain a
201
- randomly chosen greeting. As is evident, pypage syntax for if/elif/else
222
+ randomly chosen greeting. As is evident, PyPage syntax for if/elif/else
202
223
  conditions closely mirrors Python's. The terminal ``{% %}`` can be
203
224
  replaced with an ``{% endif %}`` with no change in meaning (as with any
204
225
  block tag).
@@ -214,7 +235,7 @@ Let's start with a simple example:
214
235
 
215
236
  This will print out the vowels with a space after every character.
216
237
 
217
- Now that's an ordinary for loop. pypage permits for loops that are more
238
+ Now that's an ordinary for loop. PyPage permits for loops that are more
218
239
  expressive than traditional Python for loops, by leveraging Python's
219
240
  *generator expressions*.
220
241
 
@@ -241,7 +262,7 @@ The above loop would result in:
241
262
  3 ~ b
242
263
  3 ~ c
243
264
 
244
- *Internally*, pypage morphs the expression
265
+ *Internally*, PyPage morphs the expression
245
266
  ``for x in [1,2,3] for y in ['a','b','c']`` into the generator
246
267
  expression ``(x, y) for x in [1,2,3] for y in ['a','b','c']``. It
247
268
  exposes the the loop variables ``x`` and ``y`` by injecting them into
@@ -249,7 +270,7 @@ your namespace.
249
270
 
250
271
  *Note:* Injected loop variables replace variables with the same name for
251
272
  the duration of the loop. After the loop, the old variables with the
252
- identical names are restored (pypage backs them up).
273
+ identical names are restored (PyPage backs them up).
253
274
 
254
275
  While Loops
255
276
  ^^^^^^^^^^^
@@ -289,13 +310,13 @@ evaluated.
289
310
  Long Loops
290
311
  ''''''''''
291
312
 
292
- If a loop runs *for more than 2 seconds*, pypage stops executing it, and
313
+ If a loop runs *for more than 2 seconds*, PyPage stops executing it, and
293
314
  writes an error message to ``stdout`` saying that the loop had been
294
- terminated. As pypage is mostly intended to be used as a templatig
315
+ terminated. As PyPage is mostly intended to be used as a templating
295
316
  language, loops generally shouldn't be running for longer than two
296
317
  seconds, and this timeout was added to make it easier to catch accidental
297
318
  infinite loops. If you actually need a loop to run for longer than 2
298
- seoncds, you can add the keyword ``slow`` right after the condition expression
319
+ seconds, you can add the keyword ``slow`` right after the condition expression
299
320
  (``{{% while condition slow %}}``), and that would suppress this 2-second timeout.
300
321
 
301
322
  Capture Blocks
@@ -320,10 +341,10 @@ Finer Details
320
341
  Inheritance (with inject and exists)
321
342
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
322
343
 
323
- The approach taken by pypage toward template inheritance is quite distinct from that of other
344
+ The approach taken by PyPage toward template inheritance is quite distinct from that of other
324
345
  templating engines (`like Jinja's <http://jinja.pocoo.org/docs/2.10/templates/#template-inheritance>`_).
325
- It's a lot simpler. You call a pypage-provided function ``inject`` with the path of a *pypage template* you want
326
- to inject (i.e. "*extend*" in Jinja parlance), and pypage will process that template under the current scope (with all
346
+ It's a lot simpler. You call a PyPage-provided function ``inject`` with the path of a *PyPage template* you want
347
+ to inject (i.e. "*extend*" in Jinja parlance), and PyPage will process that template under the current scope (with all
327
348
  previously defined variables being available to the injected template), and the ``inject`` function will return its output.
328
349
 
329
350
  A base template could look like this:
@@ -367,7 +388,7 @@ and is not present. The output of the "dervied" template is clear and obvious, w
367
388
  The include function
368
389
  ''''''''''''''''''''
369
390
 
370
- If you want to include (as in, substitute) a file directly without processing it with pypage, you can use the
391
+ If you want to include (as in, substitute) a file directly without processing it with PyPage, you can use the
371
392
  ``include`` function. It functions like the ``inject`` function, taking the path to a file as argument, and
372
393
  returning the contents of the file unprocessed.
373
394
 
@@ -424,7 +445,7 @@ whitespace in the generated document.
424
445
  Automatic Indentation
425
446
  '''''''''''''''''''''
426
447
 
427
- pypage smartly handles indentation for you. In a multi-line code tag, if
448
+ PyPage smartly handles indentation for you. In a multi-line code tag, if
428
449
  you consistently indent your Python code with a specific amount of
429
450
  whitespace, that indentation will be stripped off before executing the
430
451
  code block (as Python is indentation-sensitive), and the resulting
@@ -467,7 +488,7 @@ would produce the following output:
467
488
  Note that the ``Hello!`` was indented with same whitespace that the code
468
489
  in the code block was.
469
490
 
470
- pypage automatically intends the output of a multi-line tag to match the
491
+ PyPage automatically intends the output of a multi-line tag to match the
471
492
  indentation level of the code tag. The number of whitespace characters
472
493
  at the beginning of the second line of the code block determines the
473
494
  indentation level for the whole block. All lines of code following the
@@ -484,3 +505,5 @@ License
484
505
  :target: https://pypi.python.org/pypi/pypage
485
506
  .. |docs| image:: https://readthedocs.org/projects/pypage/badge/?version=latest&style=flat
486
507
  :target: https://pypage.readthedocs.io/en/latest/
508
+ .. |test| image:: https://github.com/arjun-menon/pypage/actions/workflows/test.yml/badge.svg
509
+ :target: https://github.com/arjun-menon/pypage/actions/workflows/test.yml/
@@ -1,15 +1,16 @@
1
- pypage |pypi| |docs|
2
- ====================
1
+ PyPage |pypi| |docs| |test|
2
+ ===========================
3
3
 
4
- pypage is a document template engine for Python programmers with a
4
+ PyPage is a document template engine for Python programmers with a
5
5
  short learning curve.
6
6
 
7
- **Why use pypage?**
7
+ **Why use PyPage?**
8
8
 
9
9
  - Easy to pick up. Syntax similar to Python's.
10
10
  - You need an eval-based template engine.
11
11
 
12
- pypage supports Python 3.x and 2.7, and has been on CPython and PyPy.
12
+ PyPage supports Python 3.x and 2.7, and has been tested
13
+ (using `test_cmd <https://github.com/arjun-menon/test_cmd>`_) on CPython and PyPy.
13
14
 
14
15
  **What does it look like?**
15
16
 
@@ -26,7 +27,7 @@ pypage supports Python 3.x and 2.7, and has been on CPython and PyPy.
26
27
 
27
28
  **Installation**
28
29
 
29
- You can `install <https://docs.python.org/3/installing/>`_ pypage easily with `pip <https://pip.pypa.io/en/stable/>`_:
30
+ You can `install <https://docs.python.org/3/installing/>`_ PyPage easily with `pip <https://pip.pypa.io/en/stable/>`_:
30
31
 
31
32
  .. code::
32
33
 
@@ -34,6 +35,29 @@ You can `install <https://docs.python.org/3/installing/>`_ pypage easily with `p
34
35
 
35
36
  Try running ``pypage -h`` to see the command-line options available.
36
37
 
38
+
39
+ **Why another templating language?**
40
+
41
+ PyPage is lets you embed Python code easily and flexibly in textual documents (such as Markdown_, HTML, reStructuredText_, plain text, etc). It lets you construct powerful programmatically-generated documents by embedding Python code in an elegant and flexible manner. Its syntax is similar to and partially inspired by the templating languages Jinja_ and Liquid_.
42
+
43
+ While there are many templating engines out there, the primarily advantage of PyPage is the fact that its syntax is very close to Python's, and therefore the learning curve is very short for Python programmers.
44
+
45
+ Rather than create a new mini domain-specific language for constructs such as ``for`` and ``if``, PyPage does a teeny tiny bit of obvious string manipulation, and passes your logical directives unaltered to the Python interpreter. As such, PyPage inherits Python's syntax for the most part. For example, ``for`` loops in PyPage get converted into Python's generator expressions. The ``for`` loop in a Python generator expression (or list comprehension) is far more powerful than its regular ``for`` loop. This means that PyPage ``for`` loops are richer and more expressive than you'd otherwise expect, while the learning curve is nearly non-existent.
46
+
47
+ The primary disadvantage of using PyPage instead of a templating engine like Liquid is that PyPage does not operate on a restricted non-Turing-complete subset of programming languages, as Liquid for instance does. Liquid allows untrusted users to write and upload their own templates, because the expressiveness of Liquid is limited such that there is an implicit guarantee that the template will be processed in a reasonable (probably linear) amount of time using a reasonable amount of system resources. As such, Liquid's templating language is rather limited -- it offers a limited number of pre-defined functions/filters, and the overall flexibility of the language has been constrained in order to guarantee termination in a reasonable amount of time.
48
+
49
+ PyPage, on the other hand gives the template writer full unfettered access to the Python interpreter. As such, PyPage is meant only for use in trusted contexts (or containers), and in some ways it's similar to PHP in that a you're mixing a full-blown programming language (Python) and text that could be HTML.
50
+
51
+ This brings us to another topic: mixing code and UI. It is generally frowned upon to mix logic/code and the UI (or "view"). So it is good practise to not do any intelligent processing within your PyPage template. Instead, you can do it in a separate program, and pass an *environment* containing the results, to PyPage. An environment is a dictionary of variables that is passed to Python's ``exec``, and is therefore accessible from all of the code in the PyPage template. From within your template you can focus solely on how to transform these input variables into the HTML/rST/other page you're building.
52
+
53
+ A pleasant aspect of PyPage, in comparison to other templating languages is that you don't have to learn much new syntax. It's probably the easiest to learn and most *flexible* templating language out there. It is highly flexible because of the plethora of easy-to-use powerful constructs that PyPage offers.
54
+
55
+ .. _Markdown: https://en.wikipedia.org/wiki/Markdown
56
+ .. _reStructuredText: http://docutils.sourceforge.net/docs/user/rst/quickref.html
57
+ .. _Liquid: https://github.com/Shopify/liquid/wiki/Liquid-for-Designers
58
+ .. _Jinja: https://github.com/pallets/jinja
59
+
60
+
37
61
  .. contents:: **Table of Contents**
38
62
 
39
63
 
@@ -55,7 +79,7 @@ example of an inline code tag:
55
79
 
56
80
  There are {{ 5 + 2 }} days in a week.
57
81
 
58
- The above, when processed by pypage, yields:
82
+ The above, when processed by PyPage, yields:
59
83
 
60
84
  ::
61
85
 
@@ -97,7 +121,7 @@ for all code tags in the same file.
97
121
 
98
122
  As such, a variable instantiated in a code tag at the
99
123
  beginning of the document, will be available to all other code tags in
100
- the document. When pypage is invoked as library, an initial seed
124
+ the document. When PyPage is invoked as library, an initial seed
101
125
  environment consisting of a Python dictionary mapping variable names to
102
126
  values, can be provided.
103
127
 
@@ -168,7 +192,7 @@ It's best to explain this with an example:
168
192
  {% %}
169
193
 
170
194
  When the above template is run, the resulting page will contain a
171
- randomly chosen greeting. As is evident, pypage syntax for if/elif/else
195
+ randomly chosen greeting. As is evident, PyPage syntax for if/elif/else
172
196
  conditions closely mirrors Python's. The terminal ``{% %}`` can be
173
197
  replaced with an ``{% endif %}`` with no change in meaning (as with any
174
198
  block tag).
@@ -184,7 +208,7 @@ Let's start with a simple example:
184
208
 
185
209
  This will print out the vowels with a space after every character.
186
210
 
187
- Now that's an ordinary for loop. pypage permits for loops that are more
211
+ Now that's an ordinary for loop. PyPage permits for loops that are more
188
212
  expressive than traditional Python for loops, by leveraging Python's
189
213
  *generator expressions*.
190
214
 
@@ -211,7 +235,7 @@ The above loop would result in:
211
235
  3 ~ b
212
236
  3 ~ c
213
237
 
214
- *Internally*, pypage morphs the expression
238
+ *Internally*, PyPage morphs the expression
215
239
  ``for x in [1,2,3] for y in ['a','b','c']`` into the generator
216
240
  expression ``(x, y) for x in [1,2,3] for y in ['a','b','c']``. It
217
241
  exposes the the loop variables ``x`` and ``y`` by injecting them into
@@ -219,7 +243,7 @@ your namespace.
219
243
 
220
244
  *Note:* Injected loop variables replace variables with the same name for
221
245
  the duration of the loop. After the loop, the old variables with the
222
- identical names are restored (pypage backs them up).
246
+ identical names are restored (PyPage backs them up).
223
247
 
224
248
  While Loops
225
249
  ^^^^^^^^^^^
@@ -259,13 +283,13 @@ evaluated.
259
283
  Long Loops
260
284
  ''''''''''
261
285
 
262
- If a loop runs *for more than 2 seconds*, pypage stops executing it, and
286
+ If a loop runs *for more than 2 seconds*, PyPage stops executing it, and
263
287
  writes an error message to ``stdout`` saying that the loop had been
264
- terminated. As pypage is mostly intended to be used as a templatig
288
+ terminated. As PyPage is mostly intended to be used as a templating
265
289
  language, loops generally shouldn't be running for longer than two
266
290
  seconds, and this timeout was added to make it easier to catch accidental
267
291
  infinite loops. If you actually need a loop to run for longer than 2
268
- seoncds, you can add the keyword ``slow`` right after the condition expression
292
+ seconds, you can add the keyword ``slow`` right after the condition expression
269
293
  (``{{% while condition slow %}}``), and that would suppress this 2-second timeout.
270
294
 
271
295
  Capture Blocks
@@ -290,10 +314,10 @@ Finer Details
290
314
  Inheritance (with inject and exists)
291
315
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
292
316
 
293
- The approach taken by pypage toward template inheritance is quite distinct from that of other
317
+ The approach taken by PyPage toward template inheritance is quite distinct from that of other
294
318
  templating engines (`like Jinja's <http://jinja.pocoo.org/docs/2.10/templates/#template-inheritance>`_).
295
- It's a lot simpler. You call a pypage-provided function ``inject`` with the path of a *pypage template* you want
296
- to inject (i.e. "*extend*" in Jinja parlance), and pypage will process that template under the current scope (with all
319
+ It's a lot simpler. You call a PyPage-provided function ``inject`` with the path of a *PyPage template* you want
320
+ to inject (i.e. "*extend*" in Jinja parlance), and PyPage will process that template under the current scope (with all
297
321
  previously defined variables being available to the injected template), and the ``inject`` function will return its output.
298
322
 
299
323
  A base template could look like this:
@@ -337,7 +361,7 @@ and is not present. The output of the "dervied" template is clear and obvious, w
337
361
  The include function
338
362
  ''''''''''''''''''''
339
363
 
340
- If you want to include (as in, substitute) a file directly without processing it with pypage, you can use the
364
+ If you want to include (as in, substitute) a file directly without processing it with PyPage, you can use the
341
365
  ``include`` function. It functions like the ``inject`` function, taking the path to a file as argument, and
342
366
  returning the contents of the file unprocessed.
343
367
 
@@ -394,7 +418,7 @@ whitespace in the generated document.
394
418
  Automatic Indentation
395
419
  '''''''''''''''''''''
396
420
 
397
- pypage smartly handles indentation for you. In a multi-line code tag, if
421
+ PyPage smartly handles indentation for you. In a multi-line code tag, if
398
422
  you consistently indent your Python code with a specific amount of
399
423
  whitespace, that indentation will be stripped off before executing the
400
424
  code block (as Python is indentation-sensitive), and the resulting
@@ -437,7 +461,7 @@ would produce the following output:
437
461
  Note that the ``Hello!`` was indented with same whitespace that the code
438
462
  in the code block was.
439
463
 
440
- pypage automatically intends the output of a multi-line tag to match the
464
+ PyPage automatically intends the output of a multi-line tag to match the
441
465
  indentation level of the code tag. The number of whitespace characters
442
466
  at the beginning of the second line of the code block determines the
443
467
  indentation level for the whole block. All lines of code following the
@@ -454,3 +478,5 @@ License
454
478
  :target: https://pypi.python.org/pypi/pypage
455
479
  .. |docs| image:: https://readthedocs.org/projects/pypage/badge/?version=latest&style=flat
456
480
  :target: https://pypage.readthedocs.io/en/latest/
481
+ .. |test| image:: https://github.com/arjun-menon/pypage/actions/workflows/test.yml/badge.svg
482
+ :target: https://github.com/arjun-menon/pypage/actions/workflows/test.yml/
@@ -1,15 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pypage
3
- Version: 2.0.8
3
+ Version: 2.1.0
4
4
  Summary: Light-weight Python Templating Engine
5
5
  Home-page: https://github.com/arjun-menon/pypage
6
- Download-URL: https://github.com/arjun-menon/pypage/archive/v2.0.8.tar.gz
6
+ Download-URL: https://github.com/arjun-menon/pypage/archive/v2.1.0.tar.gz
7
7
  Author: Arjun G. Menon
8
8
  Author-email: contact@arjungmenon.com
9
- License: Apache
10
- Keywords: templating enigne text processing static generator
9
+ License: Apache-2.0
10
+ Keywords: templating engine text processing static generator,templating engine,text processing,template,templates
11
11
  Classifier: Topic :: Text Processing
12
+ Classifier: Intended Audience :: Developers
12
13
  Classifier: Topic :: Internet :: WWW/HTTP
14
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
13
15
  Classifier: Topic :: Text Processing :: Markup :: HTML
14
16
  Classifier: License :: OSI Approved :: Apache Software License
15
17
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -20,26 +22,22 @@ Classifier: Operating System :: OS Independent
20
22
  Classifier: Programming Language :: Python :: Implementation :: CPython
21
23
  Classifier: Programming Language :: Python :: Implementation :: PyPy
22
24
  Classifier: Programming Language :: Python :: 2
23
- Classifier: Programming Language :: Python :: 2.7
24
25
  Classifier: Programming Language :: Python :: 3
25
- Classifier: Programming Language :: Python :: 3.2
26
- Classifier: Programming Language :: Python :: 3.3
27
- Classifier: Programming Language :: Python :: 3.4
28
- Classifier: Programming Language :: Python :: 3.5
29
26
  License-File: LICENSE.txt
30
27
 
31
- pypage |pypi| |docs|
32
- ====================
28
+ PyPage |pypi| |docs| |test|
29
+ ===========================
33
30
 
34
- pypage is a document template engine for Python programmers with a
31
+ PyPage is a document template engine for Python programmers with a
35
32
  short learning curve.
36
33
 
37
- **Why use pypage?**
34
+ **Why use PyPage?**
38
35
 
39
36
  - Easy to pick up. Syntax similar to Python's.
40
37
  - You need an eval-based template engine.
41
38
 
42
- pypage supports Python 3.x and 2.7, and has been on CPython and PyPy.
39
+ PyPage supports Python 3.x and 2.7, and has been tested
40
+ (using `test_cmd <https://github.com/arjun-menon/test_cmd>`_) on CPython and PyPy.
43
41
 
44
42
  **What does it look like?**
45
43
 
@@ -56,7 +54,7 @@ pypage supports Python 3.x and 2.7, and has been on CPython and PyPy.
56
54
 
57
55
  **Installation**
58
56
 
59
- You can `install <https://docs.python.org/3/installing/>`_ pypage easily with `pip <https://pip.pypa.io/en/stable/>`_:
57
+ You can `install <https://docs.python.org/3/installing/>`_ PyPage easily with `pip <https://pip.pypa.io/en/stable/>`_:
60
58
 
61
59
  .. code::
62
60
 
@@ -64,6 +62,29 @@ You can `install <https://docs.python.org/3/installing/>`_ pypage easily with `p
64
62
 
65
63
  Try running ``pypage -h`` to see the command-line options available.
66
64
 
65
+
66
+ **Why another templating language?**
67
+
68
+ PyPage is lets you embed Python code easily and flexibly in textual documents (such as Markdown_, HTML, reStructuredText_, plain text, etc). It lets you construct powerful programmatically-generated documents by embedding Python code in an elegant and flexible manner. Its syntax is similar to and partially inspired by the templating languages Jinja_ and Liquid_.
69
+
70
+ While there are many templating engines out there, the primarily advantage of PyPage is the fact that its syntax is very close to Python's, and therefore the learning curve is very short for Python programmers.
71
+
72
+ Rather than create a new mini domain-specific language for constructs such as ``for`` and ``if``, PyPage does a teeny tiny bit of obvious string manipulation, and passes your logical directives unaltered to the Python interpreter. As such, PyPage inherits Python's syntax for the most part. For example, ``for`` loops in PyPage get converted into Python's generator expressions. The ``for`` loop in a Python generator expression (or list comprehension) is far more powerful than its regular ``for`` loop. This means that PyPage ``for`` loops are richer and more expressive than you'd otherwise expect, while the learning curve is nearly non-existent.
73
+
74
+ The primary disadvantage of using PyPage instead of a templating engine like Liquid is that PyPage does not operate on a restricted non-Turing-complete subset of programming languages, as Liquid for instance does. Liquid allows untrusted users to write and upload their own templates, because the expressiveness of Liquid is limited such that there is an implicit guarantee that the template will be processed in a reasonable (probably linear) amount of time using a reasonable amount of system resources. As such, Liquid's templating language is rather limited -- it offers a limited number of pre-defined functions/filters, and the overall flexibility of the language has been constrained in order to guarantee termination in a reasonable amount of time.
75
+
76
+ PyPage, on the other hand gives the template writer full unfettered access to the Python interpreter. As such, PyPage is meant only for use in trusted contexts (or containers), and in some ways it's similar to PHP in that a you're mixing a full-blown programming language (Python) and text that could be HTML.
77
+
78
+ This brings us to another topic: mixing code and UI. It is generally frowned upon to mix logic/code and the UI (or "view"). So it is good practise to not do any intelligent processing within your PyPage template. Instead, you can do it in a separate program, and pass an *environment* containing the results, to PyPage. An environment is a dictionary of variables that is passed to Python's ``exec``, and is therefore accessible from all of the code in the PyPage template. From within your template you can focus solely on how to transform these input variables into the HTML/rST/other page you're building.
79
+
80
+ A pleasant aspect of PyPage, in comparison to other templating languages is that you don't have to learn much new syntax. It's probably the easiest to learn and most *flexible* templating language out there. It is highly flexible because of the plethora of easy-to-use powerful constructs that PyPage offers.
81
+
82
+ .. _Markdown: https://en.wikipedia.org/wiki/Markdown
83
+ .. _reStructuredText: http://docutils.sourceforge.net/docs/user/rst/quickref.html
84
+ .. _Liquid: https://github.com/Shopify/liquid/wiki/Liquid-for-Designers
85
+ .. _Jinja: https://github.com/pallets/jinja
86
+
87
+
67
88
  .. contents:: **Table of Contents**
68
89
 
69
90
 
@@ -85,7 +106,7 @@ example of an inline code tag:
85
106
 
86
107
  There are {{ 5 + 2 }} days in a week.
87
108
 
88
- The above, when processed by pypage, yields:
109
+ The above, when processed by PyPage, yields:
89
110
 
90
111
  ::
91
112
 
@@ -127,7 +148,7 @@ for all code tags in the same file.
127
148
 
128
149
  As such, a variable instantiated in a code tag at the
129
150
  beginning of the document, will be available to all other code tags in
130
- the document. When pypage is invoked as library, an initial seed
151
+ the document. When PyPage is invoked as library, an initial seed
131
152
  environment consisting of a Python dictionary mapping variable names to
132
153
  values, can be provided.
133
154
 
@@ -198,7 +219,7 @@ It's best to explain this with an example:
198
219
  {% %}
199
220
 
200
221
  When the above template is run, the resulting page will contain a
201
- randomly chosen greeting. As is evident, pypage syntax for if/elif/else
222
+ randomly chosen greeting. As is evident, PyPage syntax for if/elif/else
202
223
  conditions closely mirrors Python's. The terminal ``{% %}`` can be
203
224
  replaced with an ``{% endif %}`` with no change in meaning (as with any
204
225
  block tag).
@@ -214,7 +235,7 @@ Let's start with a simple example:
214
235
 
215
236
  This will print out the vowels with a space after every character.
216
237
 
217
- Now that's an ordinary for loop. pypage permits for loops that are more
238
+ Now that's an ordinary for loop. PyPage permits for loops that are more
218
239
  expressive than traditional Python for loops, by leveraging Python's
219
240
  *generator expressions*.
220
241
 
@@ -241,7 +262,7 @@ The above loop would result in:
241
262
  3 ~ b
242
263
  3 ~ c
243
264
 
244
- *Internally*, pypage morphs the expression
265
+ *Internally*, PyPage morphs the expression
245
266
  ``for x in [1,2,3] for y in ['a','b','c']`` into the generator
246
267
  expression ``(x, y) for x in [1,2,3] for y in ['a','b','c']``. It
247
268
  exposes the the loop variables ``x`` and ``y`` by injecting them into
@@ -249,7 +270,7 @@ your namespace.
249
270
 
250
271
  *Note:* Injected loop variables replace variables with the same name for
251
272
  the duration of the loop. After the loop, the old variables with the
252
- identical names are restored (pypage backs them up).
273
+ identical names are restored (PyPage backs them up).
253
274
 
254
275
  While Loops
255
276
  ^^^^^^^^^^^
@@ -289,13 +310,13 @@ evaluated.
289
310
  Long Loops
290
311
  ''''''''''
291
312
 
292
- If a loop runs *for more than 2 seconds*, pypage stops executing it, and
313
+ If a loop runs *for more than 2 seconds*, PyPage stops executing it, and
293
314
  writes an error message to ``stdout`` saying that the loop had been
294
- terminated. As pypage is mostly intended to be used as a templatig
315
+ terminated. As PyPage is mostly intended to be used as a templating
295
316
  language, loops generally shouldn't be running for longer than two
296
317
  seconds, and this timeout was added to make it easier to catch accidental
297
318
  infinite loops. If you actually need a loop to run for longer than 2
298
- seoncds, you can add the keyword ``slow`` right after the condition expression
319
+ seconds, you can add the keyword ``slow`` right after the condition expression
299
320
  (``{{% while condition slow %}}``), and that would suppress this 2-second timeout.
300
321
 
301
322
  Capture Blocks
@@ -320,10 +341,10 @@ Finer Details
320
341
  Inheritance (with inject and exists)
321
342
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
322
343
 
323
- The approach taken by pypage toward template inheritance is quite distinct from that of other
344
+ The approach taken by PyPage toward template inheritance is quite distinct from that of other
324
345
  templating engines (`like Jinja's <http://jinja.pocoo.org/docs/2.10/templates/#template-inheritance>`_).
325
- It's a lot simpler. You call a pypage-provided function ``inject`` with the path of a *pypage template* you want
326
- to inject (i.e. "*extend*" in Jinja parlance), and pypage will process that template under the current scope (with all
346
+ It's a lot simpler. You call a PyPage-provided function ``inject`` with the path of a *PyPage template* you want
347
+ to inject (i.e. "*extend*" in Jinja parlance), and PyPage will process that template under the current scope (with all
327
348
  previously defined variables being available to the injected template), and the ``inject`` function will return its output.
328
349
 
329
350
  A base template could look like this:
@@ -367,7 +388,7 @@ and is not present. The output of the "dervied" template is clear and obvious, w
367
388
  The include function
368
389
  ''''''''''''''''''''
369
390
 
370
- If you want to include (as in, substitute) a file directly without processing it with pypage, you can use the
391
+ If you want to include (as in, substitute) a file directly without processing it with PyPage, you can use the
371
392
  ``include`` function. It functions like the ``inject`` function, taking the path to a file as argument, and
372
393
  returning the contents of the file unprocessed.
373
394
 
@@ -424,7 +445,7 @@ whitespace in the generated document.
424
445
  Automatic Indentation
425
446
  '''''''''''''''''''''
426
447
 
427
- pypage smartly handles indentation for you. In a multi-line code tag, if
448
+ PyPage smartly handles indentation for you. In a multi-line code tag, if
428
449
  you consistently indent your Python code with a specific amount of
429
450
  whitespace, that indentation will be stripped off before executing the
430
451
  code block (as Python is indentation-sensitive), and the resulting
@@ -467,7 +488,7 @@ would produce the following output:
467
488
  Note that the ``Hello!`` was indented with same whitespace that the code
468
489
  in the code block was.
469
490
 
470
- pypage automatically intends the output of a multi-line tag to match the
491
+ PyPage automatically intends the output of a multi-line tag to match the
471
492
  indentation level of the code tag. The number of whitespace characters
472
493
  at the beginning of the second line of the code block determines the
473
494
  indentation level for the whole block. All lines of code following the
@@ -484,3 +505,5 @@ License
484
505
  :target: https://pypi.python.org/pypi/pypage
485
506
  .. |docs| image:: https://readthedocs.org/projects/pypage/badge/?version=latest&style=flat
486
507
  :target: https://pypage.readthedocs.io/en/latest/
508
+ .. |test| image:: https://github.com/arjun-menon/pypage/actions/workflows/test.yml/badge.svg
509
+ :target: https://github.com/arjun-menon/pypage/actions/workflows/test.yml/
@@ -18,7 +18,7 @@
18
18
  from __future__ import print_function
19
19
  import string, sys, time, os, json
20
20
 
21
- pypage_version = '2.0.8'
21
+ pypage_version = '2.1.0'
22
22
 
23
23
  class RootNode(object):
24
24
  """
@@ -62,7 +62,7 @@ class TagNode(object):
62
62
  open_delim: string containig the opening delimiter
63
63
  close_delim: string containig the closing delimiter
64
64
  """
65
- escape_delims = {'\{':'{', '\}':'}'}
65
+ escape_delims = {('\\' + '{'):'{', ('\\' + '}'):'}'}
66
66
 
67
67
  def __init__(self, loc):
68
68
  self.src = str()
@@ -383,7 +383,13 @@ class EndBlockTag(BlockTag):
383
383
  def __repr__(self):
384
384
  return 'EndBlockTag.\n'
385
385
 
386
- class PypageSyntaxError(Exception):
386
+ class PypageError(Exception):
387
+ def __init__(self, description='undefined'):
388
+ self.description = description
389
+ def __str__(self):
390
+ return "Error: " + self.description
391
+
392
+ class PypageSyntaxError(PypageError):
387
393
  def __init__(self, description='undefined'):
388
394
  self.description = description
389
395
  def __str__(self):
@@ -832,10 +838,9 @@ def read_file(filepath):
832
838
  with open(filepath, 'r') as source_file:
833
839
  return source_file.read()
834
840
  else:
835
- print("File %s does not exist." % repr(filepath), file=sys.stderr)
836
- sys.exit(1)
841
+ raise PypageError("File %s does not exist. CWD: %s" % (repr(filepath), os.getcwd()))
837
842
 
838
- __all__ = ['pypage', 'pypage_version']
843
+ __all__ = ['pypage', 'pypage_version', PypageError, PypageSyntaxError]
839
844
 
840
845
  def main():
841
846
  import argparse
@@ -3,9 +3,11 @@
3
3
  from setuptools import setup
4
4
 
5
5
  from pypage import pypage_version as version
6
+
6
7
  repo_url = 'https://github.com/arjun-menon/pypage'
7
8
  download_url = '%s/archive/v%s.tar.gz' % (repo_url, version)
8
9
 
10
+
9
11
  def get_long_desc():
10
12
  doc_file_name = 'README.rst'
11
13
  exclude_lines_with_words = ['toctree', 'maxdepth']
@@ -14,6 +16,7 @@ def get_long_desc():
14
16
  lines = f.readlines()
15
17
  return ''.join(line for line in lines if not any(word in line for word in exclude_lines_with_words))
16
18
 
19
+
17
20
  setup(name='pypage',
18
21
  version=version,
19
22
  description=' Light-weight Python Templating Engine',
@@ -22,15 +25,23 @@ setup(name='pypage',
22
25
  download_url=download_url,
23
26
  author='Arjun G. Menon',
24
27
  author_email='contact@arjungmenon.com',
25
- keywords='templating enigne text processing static generator',
26
- license='Apache',
28
+ keywords=[
29
+ 'templating engine text processing static generator',
30
+ 'templating engine',
31
+ 'text processing',
32
+ 'template',
33
+ 'templates'
34
+ ],
35
+ license='Apache-2.0',
27
36
  py_modules=['pypage'],
28
37
  entry_points={
29
38
  'console_scripts': ['pypage=pypage:main'],
30
39
  },
31
40
  classifiers=[
32
41
  'Topic :: Text Processing',
42
+ 'Intended Audience :: Developers',
33
43
  'Topic :: Internet :: WWW/HTTP',
44
+ 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
34
45
  'Topic :: Text Processing :: Markup :: HTML',
35
46
  'License :: OSI Approved :: Apache Software License',
36
47
  'Topic :: Software Development :: Libraries :: Python Modules',
@@ -41,10 +52,5 @@ setup(name='pypage',
41
52
  'Programming Language :: Python :: Implementation :: CPython',
42
53
  'Programming Language :: Python :: Implementation :: PyPy',
43
54
  'Programming Language :: Python :: 2',
44
- 'Programming Language :: Python :: 2.7',
45
55
  'Programming Language :: Python :: 3',
46
- 'Programming Language :: Python :: 3.2',
47
- 'Programming Language :: Python :: 3.3',
48
- 'Programming Language :: Python :: 3.4',
49
- 'Programming Language :: Python :: 3.5',
50
56
  ])
File without changes
File without changes