Skip to content

Commit 2a2ded5

Browse files
authored
Make it compatible with standard liquid (#28)
* Construct a scalefold to remodel using lark-parser * Remove old codes, implement tag relationship handling. * Start adding tests for standard liquid mode * Fix top-level tokenization with compact tags * Complete all functionalities of shopify's liquid * Update pyproject.toml * Update .travis.yml * Update pyproject.toml * Add dateutil to dev deps * Better debug message with parsed tree and rendered fragments for Tags. * Update README * Finish implementation * Add ternary filter in grammar * Add dot, subscript, star, keyword and complex filters * Add tag from, import and python * Fix linting styles * Add type hints * Add part of docs. * Complete docs. * Fix typos in docs. * Fix docs. * Update README * Update README
1 parent 828d67d commit 2a2ded5

File tree

138 files changed

+8412
-8579
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

138 files changed

+8412
-8579
lines changed

.github/workflows/build.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Build and Deploy
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
7+
build:
8+
runs-on: ubuntu-latest
9+
strategy:
10+
matrix:
11+
python-version: [3.6, 3.7, 3.8]
12+
13+
steps:
14+
- uses: actions/checkout@v2
15+
- name: Setup Python # Set Python version
16+
uses: actions/setup-python@v2
17+
with:
18+
python-version: ${{ matrix.python-version }}
19+
- name: Install dependencies
20+
run: |
21+
python -m pip install --upgrade pip
22+
python -m pip install pylint
23+
python -m pip install poetry
24+
poetry install -v
25+
- name: Run pylint
26+
run: pylint liquid
27+
- name: Test with pytest
28+
run: poetry run pytest tests/ --junitxml=junit/test-results-${{ matrix.python-version }}.xml
29+
- name: Upload pytest test results
30+
uses: actions/upload-artifact@v2
31+
with:
32+
name: pytest-results-${{ matrix.python-version }}
33+
path: junit/test-results-${{ matrix.python-version }}.xml
34+
# Use always() to always run this step to publish test results when there are test failures
35+
if: ${{ always() }}
36+
- name: Run codacy-coverage-reporter
37+
uses: codacy/codacy-coverage-reporter-action@master
38+
if: matrix.python-version == 3.8
39+
with:
40+
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
41+
coverage-reports: .coverage.xml
42+
43+
deploy:
44+
needs: build
45+
runs-on: ubuntu-latest
46+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
47+
strategy:
48+
matrix:
49+
python-version: [3.8]
50+
steps:
51+
- uses: actions/checkout@v2
52+
- name: Setup Python # Set Python version
53+
uses: actions/setup-python@v2
54+
- name: Install dependencies
55+
run: |
56+
python -m pip install --upgrade pip
57+
python -m pip install poetry
58+
- name: Publish to PyPI
59+
run: poetry publish --build -u ${{ secrets.PYPI_USER }} -p ${{ secrets.PYPI_PASSWORD }}
60+
if: success()

.github/workflows/docs.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Build Docs
2+
3+
on: [push]
4+
5+
jobs:
6+
docs:
7+
runs-on: ubuntu-latest
8+
strategy:
9+
matrix:
10+
python-version: [3.8]
11+
steps:
12+
- uses: actions/checkout@v2
13+
- name: Setup Python # Set Python version
14+
uses: actions/setup-python@v2
15+
with:
16+
python-version: ${{ matrix.python-version }}
17+
- name: Install dependencies
18+
run: |
19+
python -m pip install --upgrade pip
20+
python -m pip install poetry
21+
poetry install -v
22+
- name: Update docs
23+
run: |
24+
poetry run python -m pip install mkdocs
25+
poetry run python -m pip install -r docs/requirements.txt
26+
cd docs
27+
cp ../README.md index.md
28+
cd ..
29+
poetry run mkdocs gh-deploy --clean --force
30+
if: success()
31+
32+
fix-index:
33+
needs: docs
34+
runs-on: ubuntu-latest
35+
strategy:
36+
matrix:
37+
python-version: [3.8]
38+
steps:
39+
- uses: actions/checkout@v2
40+
with:
41+
ref: gh-pages
42+
- name: Fix index.html
43+
run: |
44+
echo ':: head of index.html - before ::'
45+
head index.html
46+
sed -i '1,5{/^$/d}' index.html
47+
echo ':: head of index.html - after ::'
48+
head index.html
49+
if: success()
50+
- name: Commit changes
51+
run: |
52+
git config --local user.email "[email protected]"
53+
git config --local user.name "GitHub Action"
54+
git commit -m "Add changes" -a
55+
if: success()
56+
- name: Push changes
57+
uses: ad-m/github-push-action@master
58+
with:
59+
github_token: ${{ secrets.GITHUB_TOKEN }}
60+
branch: gh-pages
61+
if: success()

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,4 @@ poetry.lock
111111
*.bak
112112

113113
.vscode
114+
docs/api/

.pre-commit-config.yaml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ repos:
1515
- id: masterpylintrc
1616
name: Overwrite local .pylintrc by master one
1717
entry: cp ../.pylintrc ./.pylintrc
18+
files: ./.pylintrc
1819
pass_filenames: false
1920
always_run: true
2021
language: system
@@ -40,13 +41,6 @@ repos:
4041
language: system
4142
files: pyproject.toml
4243
pass_filenames: false
43-
- id: api
44-
name: Generate API documentation
45-
entry: bash -c
46-
args: ['python api.py > docs/api.md']
47-
language: system
48-
pass_filenames: false
49-
files: ^liquid/.+$
5044
- id: pytest
5145
name: Run pytest
5246
entry: pytest

.pylintrc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,10 @@ disable=print-statement,
145145
no-name-in-module,
146146
no-member,
147147
broad-except,
148-
cyclic-import
148+
cyclic-import,
149+
too-few-public-methods,
150+
unbalanced-tuple-unpacking,
151+
no-self-use
149152

150153
# Enable the message, report, category or checker with the given id(s). You can
151154
# either give multiple identifier separated by comma (,) or put this option
@@ -211,7 +214,7 @@ ignore-comments=yes
211214
ignore-docstrings=yes
212215

213216
# Ignore imports when computing similarities.
214-
ignore-imports=no
217+
ignore-imports=yes
215218

216219
# Minimum lines number of a similarity.
217220
min-similarity-lines=4
@@ -298,18 +301,21 @@ good-names=i,
298301
j,
299302
k,
300303
x,
301-
y,
304+
y,
302305
z,
303306
np,
304307
nn,
308+
ns,
305309
t,
306310
t0,
311+
to,
307312
ex,
308313
rc,
309314
eq,
310315
do,
311316
by,
312317
tf,
318+
op,
313319
Run,
314320
_
315321

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ matrix:
44
include:
55
- python: 3.6
66
- python: 3.7
7+
- python: 3.8
78
dist: xenial
89
before_install:
910
- pip install poetry

README.md

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,68 @@
11
# liquidpy
22
A port of [liquid][1] template engine for python
33

4-
[![Pypi][2]][9] [![Github][3]][10] [![PythonVers][4]][9] [![ReadTheDocs building][13]][8] [![Travis building][5]][11] [![Codacy][6]][12] [![Codacy coverage][7]][12]
4+
[![Pypi][2]][9] [![Github][3]][10] [![PythonVers][4]][9] [![Codacy][6]][12] [![Codacy coverage][7]][12] ![Docs building][13] ![Building][5]
5+
6+
This is compatible with [standard Liquid][1] template engine. Variations, such as Shopify and Jekyll are not fully supported yet.
57

68
## Install
79
```shell
8-
pip install liquidpy
10+
pip install -U liquidpy
911
```
1012

11-
## Current status and plans
12-
- Note that this branch is not fully compatible with shopify's liquid. For compatible versions, please check branches [lark][14] and [larkone][15].
13-
- This branch is current NOT safe agaist malicious input ([#22][16]), so we tried to re-implement the engine using `lark-parser`. However, both versions were very slow for lexer.
14-
- With branch `lark`, we tried to tokenize each tag and parse the content of the tags later using independent parsers, while with `larkone`, we tried to put all grammars together, and made it into a universal parser. However, both of them are slow, due to tokenization of whole tags (`raw` and `comment`) and literals (See `grammar.lark` in the code).
15-
- If you have a better grammar or idea for tokenization, you are very welcome to submit issues or PRs (writing naive lexer is just too much work).
16-
- We left some APIs to extend the `lark` ones with some functions from `master`. However, it won't happen before we find a faster lexer.
17-
- A temporary plan for the `master` branch is to do some security check to address [#22][16].
18-
19-
## Full Documentation
20-
[ReadTheDocs][8]
21-
2213
## Baisic usage
2314
```python
2415
from liquid import Liquid
2516
liq = Liquid('{{a}}')
26-
ret = liq.render(a = 1)
17+
ret = liq.render(a=1)
2718
# ret == '1'
2819

29-
# load template from a file
30-
liq = Liquid('/path/to/template', liquid_from_file=True)
20+
# with environments pre-loaded
21+
liq = Liquid('{{a}}', a=1)
22+
ret = liq.render()
23+
# ret == '1'
24+
25+
# With debug on:
26+
liq = Liquid('{{a}}', liquid_config={'debug': True})
27+
```
28+
29+
## Python mode
30+
31+
We also support a python mode template engine, which acts more pythonic and powerful.
32+
```python
33+
from liquid import Liquid
34+
# standard liquid doesn't support this
35+
liq = Liquid('{{a + 1}}', {'mode': 'python'})
36+
ret = liq.render(a=1)
37+
# ret == '2'
3138
```
32-
With environments:
39+
40+
Both modes can accept a path, a file-like object or a stream for the template:
3341
```python
34-
liq = Liquid('{{a | os.path.basename}}', os=__import__('os'))
35-
ret = liq.render(a="path/to/file.txt")
36-
# ret == 'file.txt'
42+
Liquid('/path/to/template')
43+
# or
44+
with open('/path/to/template') as f:
45+
Liquid(f)
3746
```
3847

48+
## Full Documentation
49+
- Liquid's [documentation][1]
50+
- Liquidpy's [documentation][14]
51+
52+
## Backward compatiblility warning
53+
54+
`v0.6.0+` is a remodeled version to make it compatible with standard liquid engine. If you are using a previous version, stick with it. `0.6.0+` is not fully compatible with previous versions.
55+
3956
[1]: https://shopify.github.io/liquid/
4057
[2]: https://img.shields.io/pypi/v/liquidpy.svg?style=flat-square
4158
[3]: https://img.shields.io/github/tag/pwwang/liquidpy.svg?style=flat-square
4259
[4]: https://img.shields.io/pypi/pyversions/liquidpy.svg?style=flat-square
43-
[5]: https://img.shields.io/travis/pwwang/liquidpy.svg?style=flat-square
60+
[5]: https://img.shields.io/github/workflow/status/pwwang/liquidpy/Build%20and%20Deploy?style=flat-square
4461
[6]: https://img.shields.io/codacy/grade/aed04c099cbe42dabda2b42bae557fa4?style=flat-square
4562
[7]: https://img.shields.io/codacy/coverage/aed04c099cbe42dabda2b42bae557fa4?style=flat-square
4663
[8]: https://liquidpy.readthedocs.io/en/latest/
4764
[9]: https://pypi.org/project/liquidpy/
4865
[10]: https://github.com/pwwang/liquidpy
49-
[11]: https://travis-ci.org/pwwang/liquidpy
5066
[12]: https://app.codacy.com/manual/pwwang/liquidpy/dashboard
51-
[13]: https://img.shields.io/readthedocs/liquidpy?style=flat-square
52-
[14]: https://github.com/pwwang/liquidpy/tree/lark
53-
[15]: https://github.com/pwwang/liquidpy/tree/larkone
54-
[16]: https://github.com/pwwang/liquidpy/issues/22
67+
[13]: https://img.shields.io/github/workflow/status/pwwang/liquidpy/Build%20Docs?label=docs&style=flat-square
68+
[14]: https://pwwang.github.io/liquidpy/

README.rst

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,35 +34,58 @@ A port of `liquid <https://shopify.github.io/liquid/>`_ template engine for pyth
3434
:alt: Codacy coverage
3535
<https://app.codacy.com/manual/pwwang/liquidpy/dashboard>`_
3636

37+
This is compatible with `standard Liquid <https://shopify.github.io/liquid/>`_ template engine. Variations, such as Shopify and Jekyll are not fully supported yet.
38+
3739
Install
3840
-------
3941

4042
.. code-block:: shell
4143
4244
pip install liquidpy
4345
44-
Full Documentation
45-
------------------
46-
47-
`ReadTheDocs <https://liquidpy.readthedocs.io/en/latest/>`_
48-
4946
Baisic usage
5047
------------
5148

5249
.. code-block:: python
5350
5451
from liquid import Liquid
5552
liq = Liquid('{{a}}')
56-
ret = liq.render(a = 1)
53+
ret = liq.render(a=1)
5754
# ret == '1'
5855
59-
# load template from a file
60-
liq = Liquid('/path/to/template', liquid_from_file=True)
56+
# with environments pre-loaded
57+
liq = Liquid('{{a}}', a=1)
58+
ret = liq.render()
59+
# ret == '1'
60+
61+
# With debug on:
62+
liq = Liquid('{{a}}', liquid_config={'debug': True})
63+
64+
Python mode
65+
-----------
66+
67+
We also support a python mode template engine, which acts more pythonic and powerful.
6168

62-
With environments:
69+
.. code-block:: python
70+
71+
from liquid import Liquid
72+
# standard liquid doesn't support this
73+
liq = Liquid('{{a + 1}}', {'mode': 'python'})
74+
ret = liq.render(a=1)
75+
# ret == '2'
76+
77+
Both modes can accept a path, a file-like object or a stream for the template:
6378

6479
.. code-block:: python
6580
66-
liq = Liquid('{{a | os.path.basename}}', os=__import__('os'))
67-
ret = liq.render(a="path/to/file.txt")
68-
# ret == 'file.txt'
81+
Liquid('/path/to/template')
82+
# or
83+
with open('/path/to/template') as f:
84+
Liquid(f)
85+
86+
Full Documentation
87+
------------------
88+
89+
90+
* Liquid's `documentation <https://shopify.github.io/liquid/>`_
91+
* Liquidpy's `documentation <https://pwwang.github.io/liquidpy/>`_

0 commit comments

Comments
 (0)