# `Otera.Value`
[🔗](https://github.com/georgeguimaraes/otera/blob/v0.1.0/lib/otera/value.ex#L1)

The Python semantics of template values.

Templates see Elixir values as these Python values:

| Elixir                            | Python                |
| --------------------------------- | --------------------- |
| `nil`, `true`, `false`            | `None`, `True`, `False` |
| integer, float                    | `int`, `float`        |
| binary                            | `str`                 |
| list, tuple                       | `list`, `tuple`       |
| map, `Otera.Dict`                 | `dict`                |
| other atom                        | `str`                 |
| function                          | a callable            |

`from_elixir/1` converts the variables of a render to these values. A map becomes an `Otera.Dict` with its keys in sorted order, and atom keys become strings.

This module gives the rules that Jinja2 takes from Python: truthiness, `str()` and `repr()`, equality and ordering, arithmetic, iteration, and attribute and item lookup in the immutable sandbox of transformers.

# `binary_op`

```elixir
@spec binary_op(atom(), term(), term()) :: term()
```

Applies a Python binary operator: `:add`, `:sub`, `:mul`, `:div`, `:floordiv`, `:mod` or `:pow`.

# `compare`

```elixir
@spec compare(atom(), term(), term()) :: boolean()
```

Compares two values with a Python ordering operator: `:lt`, `:lteq`, `:gt` or `:gteq`.

# `contains?`

```elixir
@spec contains?(term(), term()) :: boolean()
```

Returns true if `item in container` in Python.

# `decimal_exponent`

```elixir
@spec decimal_exponent(float()) :: integer()
```

Returns the decimal exponent of the first significant digit of a positive float, like `floor(log10(value))`.

# `equal?`

```elixir
@spec equal?(term(), term()) :: boolean()
```

Returns true if `left == right` in Python.

# `format_float`

```elixir
@spec format_float(float()) :: String.t()
```

Formats a float like Python `repr()`: the shortest digits that give the same float, in fixed notation from `1e-4` to below `1e16`, else in scientific notation.

# `from_elixir`

```elixir
@spec from_elixir(term()) :: term()
```

Converts an Elixir value to a template value. See the module documentation.

# `getattr`

```elixir
@spec getattr(term(), String.t()) :: term()
```

Looks up `x.name`, like the immutable sandbox of Jinja2: a Python attribute first, then an item.

# `getitem`

```elixir
@spec getitem(term(), term()) :: term()
```

Looks up `x[key]`, like the immutable sandbox of Jinja2: an item first, then a Python attribute.

# `hashable!`

```elixir
@spec hashable!(term()) :: :ok
```

Raises the Python `TypeError` for a dict key or a set item that is a list or a dict.

# `iterable?`

```elixir
@spec iterable?(term()) :: boolean()
```

Returns true if Python can iterate over `value`.

# `length`

```elixir
@spec length(term()) :: non_neg_integer()
```

Returns the length of `value`, like Python `len()`.

# `object_type_repr`

```elixir
@spec object_type_repr(term()) :: String.t()
```

Describes the type of `value` as Jinja2 does in undefined messages, for example `dict object`.

# `repr`

```elixir
@spec repr(term()) :: String.t()
```

Returns the Python `repr()` of `value`.

# `slice`

```elixir
@spec slice(term(), term(), term(), term()) :: term()
```

Returns `sequence[start:stop:step]` with the Python rules for missing and negative bounds.

# `str_length`

```elixir
@spec str_length(String.t()) :: non_neg_integer()
```

Returns the number of code points in `string`, the length of a Python `str`.

# `strip`

```elixir
@spec strip(String.t(), String.t() | nil, :both | :leading | :trailing) :: String.t()
```

Strips `chars` from one or both ends of `string`, like Python `str.strip()`. With `nil`, strips whitespace.

# `to_list`

```elixir
@spec to_list(term()) :: list()
```

Returns the items of `value` as a list, like Python `iter()`. A dict gives its keys, and a string its characters.

# `to_str`

```elixir
@spec to_str(term()) :: String.t()
```

Converts `value` to a string, like Python `str()`.

# `truthy?`

```elixir
@spec truthy?(term()) :: boolean()
```

Returns the truth value of `value`, like Python `bool()`.

# `type_name`

```elixir
@spec type_name(term()) :: String.t()
```

Returns the name of the Python type of `value`, as in Python error messages.

# `unary_op`

```elixir
@spec unary_op(:neg | :pos, term()) :: term()
```

Applies unary minus or plus.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
