Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
# Python Liquid2 Change Log

## Version 0.2.1 (unreleased)
## Version 0.3.0 (unreleased)

**Breaking changes**

- Most built-in expression parsing functions/methods now expect the current `Environment` instance to be passed as the first argument.

**Fixes**

- Fixed `{% for %}` tag expressions with a comma between the iterable and `limit`, `offset` or `reversed`. Previously we were assuming a comma immediately following the iterable would mean we are iterating an array literal. We're also explicitly disallowing `limit`, `offset` and `reversed` arguments after an array literal.

**Features**

- Added optional filter argument validation at template parse time. ([docs](https://jg-rp.github.io/python-liquid2/custom_filters/#filter-argument-validation))
- Added lambda expressions as filter arguments. Both custom and built-in filters can accept arguments of the form `<identifier> => <boolean expression>` or `(<identifier>, <identifier>) => <boolean expression>`.
- Updated filters `map`, `where`, `sort`, `sort_natural`, `uniq`, `compact` and `sum` to accept lambda expression or string arguments.
- Added filters `reject`, `has`, `find` and `find_index`.

## Version 0.2.0

**Features**
Expand Down
1 change: 1 addition & 0 deletions docs/api/expression.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: liquid2.expression.Expression
48 changes: 48 additions & 0 deletions docs/custom_filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,51 @@ del env.filters["safe"]
!!! tip

You can add, remove and replace filters on `liquid2.DEFAULT_ENVIRONMENT` too. Convenience functions [`parse()`](api/convenience.md#liquid2.parse) and [`render()`](api/convenience.md#liquid2.render) use `DEFAULT_ENVIRONMENT`

## Filter argument validation

When implementing a filter as a class, you have the option of implementing a `validate()` method. If present, `validate` will be called when parsing the template, giving you the opportunity to raise an exception if the filter's arguments are not acceptable.

Here's an example of the built-in [`map`](filter_reference.md#map) filter. It uses `validate` to check that if a lambda expression is passed as an argument, that expression is a path to a variable, not a logical expression.

!!! tip

See [map_filter.py](https://github.com/jg-rp/python-liquid2/tree/main/liquid2/builtin/filters/map_filter.py) for the full example.

```python
class MapFilter:
"""An implementation of the `map` filter that accepts lambda expressions."""

with_context = True

def validate(
self,
_env: Environment,
token: TokenT,
name: str,
args: list[KeywordArgument | PositionalArgument],
) -> None:
"""Raise a `LiquidTypeError` if _args_ are not valid."""
if len(args) != 1:
raise LiquidTypeError(
f"{name!r} expects exactly one argument, got {len(args)}",
token=token,
)

if not isinstance(args[0], PositionalArgument):
raise LiquidTypeError(
f"{name!r} takes no keyword arguments",
token=token,
)

arg = args[0].value

if isinstance(arg, LambdaExpression) and not isinstance(arg.expression, Path):
raise LiquidTypeError(
f"{name!r} expects a path to a variable, "
f"got {arg.expression.__class__.__name__}",
token=arg.expression.token,
)

# ...
```
Loading
Loading