pypage 2.0.8__py3-none-any.whl → 2.1.0__py3-none-any.whl

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/
@@ -0,0 +1,7 @@
1
+ pypage.py,sha256=oEEr3pCIbKbDoAIYL8vANUtRb4Wbll9IvYMWID0xEng,29037
2
+ pypage-2.1.0.dist-info/LICENSE.txt,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
3
+ pypage-2.1.0.dist-info/METADATA,sha256=TvOBibltTKqFxxy_4-sZ0Y8lHIrZVPo2wX0do03nVF4,18152
4
+ pypage-2.1.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
5
+ pypage-2.1.0.dist-info/entry_points.txt,sha256=iHPN6EfIUdv-njh8GV04yDTzkcCLGNcXvdbA43s_8mo,39
6
+ pypage-2.1.0.dist-info/top_level.txt,sha256=8AAB15dVQEt9xcwH_eLcVUZEbFlc__81RA5mOrYtJiQ,7
7
+ pypage-2.1.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.2)
2
+ Generator: setuptools (72.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
pypage.py CHANGED
@@ -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
@@ -1,7 +0,0 @@
1
- pypage.py,sha256=nqAmcmFEUWK51VcO5dBPtyA4C-KyYH_2M_aVOhYUUJo,28803
2
- pypage-2.0.8.dist-info/LICENSE.txt,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
3
- pypage-2.0.8.dist-info/METADATA,sha256=xItbpHOXIxsOCQECZ5SQz69Px-XFJMU2eS83pveVXDM,14473
4
- pypage-2.0.8.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
5
- pypage-2.0.8.dist-info/entry_points.txt,sha256=iHPN6EfIUdv-njh8GV04yDTzkcCLGNcXvdbA43s_8mo,39
6
- pypage-2.0.8.dist-info/top_level.txt,sha256=8AAB15dVQEt9xcwH_eLcVUZEbFlc__81RA5mOrYtJiQ,7
7
- pypage-2.0.8.dist-info/RECORD,,