Skip to content

Commit

Permalink
docs: Update Python docstrings
Browse files Browse the repository at this point in the history
- Correct docstrings
  - Remove non-existant `parser_class` arg in API
  - Simplify with REPL examples and cleaner APIs
  - Assertions fail when running due to formatting
    - e.g. `assert "( a and ( b or not (c) ) )"` == str(expression)
  - Typos e.g. `These` over `Theses`
- Test docstrings with pytest
- Correct relative cucumber issue link #406 -> cucumber/common#406
- Drop dead Behave gherkin philosophy link: https://behave.readthedocs.io/en/latest/philosophy.html#the-gherkin-language
  • Loading branch information
kieran-ryan committed Jan 12, 2025
1 parent 8b1c8ff commit a2e1279
Show file tree
Hide file tree
Showing 7 changed files with 284 additions and 125 deletions.
4 changes: 2 additions & 2 deletions python/DEVELOPMENT.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ PROCEDURE: By using "make" (on UNIX platforms, like: Linux, macOS, ...)
# * Runs the tests
$ make
# -- STEP: Install/Update all Python packages (explicitely).
# -- STEP: Install/Update all Python packages (explicitly).
# ALTERNATIVE: make update-dependencies
$ make install-packages
Expand Down Expand Up @@ -129,7 +129,7 @@ Afterwards:
$ source .venv/bin/activate
$ pip install -r py.requirements/all.txt
# -- HINT: Afterwards, to deactivate the virtual-enviroment, use:
# -- HINT: Afterwards, to deactivate the virtual-environment, use:
$ deactivate
SEE ALSO:
Expand Down
17 changes: 7 additions & 10 deletions python/cucumber_tag_expressions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
# -*- coding: UTF-8 -*-
"""
Python implementation of `cucumber tag-expressions`_.
"""Python implementation of `Cucumber Tag Expressions`_.
Tag-expressions are used in cucumber, behave and other BDD frameworks
Tag expressions are used in cucumber, behave and other BDD frameworks
to select features, scenarios, etc. in `Gherkin`_ files.
Theses selected items are normally included in a test run.
These selected items are normally included in a test run.
.. see also:: https://cucumber.io/docs/cucumber/api/#tag-expressions
.. _Cucumber Tag Expressions:
https://cucumber.io/docs/cucumber/api/#tag-expressions
# pylint: disable=line-too-long
.. _`cucumber tag-expressions`: https://cucumber.io/docs/cucumber/api/#tag-expressions
.. _`Gherkin`: https://cucumber.io/docs/gherkin/reference/
# pylint: disable=line-too-long
.. _`behave: Gherkin`: https://behave.readthedocs.io/en/latest/philosophy.html#the-gherkin-language
.. _Gherkin:
https://cucumber.io/docs/gherkin/reference/
"""

from __future__ import absolute_import
Expand Down
124 changes: 92 additions & 32 deletions python/cucumber_tag_expressions/model.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,41 @@
# -*- coding: UTF-8 -*-
# pylint: disable=missing-docstring
"""
Provides model classes to evaluate parsed boolean tag expressions.
.. code-block:: python
# -- Expression := a and b
expression = And(Literal("a"), Literal("b"))
assert True == expression.evaluate(["a", "b"])
assert False == expression.evaluate(["a"])
assert False == expression.evaluate([])
# -- Expression := a or b
expression = Or(Literal("a"), Literal("b"))
assert True == expression.evaluate(["a", "b"])
assert True == expression.evaluate(["a"])
assert False == expression.evaluate([])
# -- Expression := not a
expression = Not(Literal("a"))
assert False == expression.evaluate(["a"])
assert True == expression.evaluate(["other"])
assert True == expression.evaluate([])
# -- Expression := (a or b) and c
expression = And(Or(Literal("a"), Literal("b")), Literal("c"))
assert True == expression.evaluate(["a", "c"])
assert False == expression.evaluate(["c", "other"])
assert False == expression.evaluate([])
"""Model classes to evaluate parsed boolean tag expressions.
Examples:
>>> expression = And(Literal("a"), Literal("b"))
>>> expression(["a", "b"])
True
>>> expression(["a", "b"])
True
>>> expression(["a"])
False
>>> expression([])
False
>>> expression = Or(Literal("a"), Literal("b"))
>>> expression(["a", "b"])
True
>>> expression(["a"])
True
>>> expression([])
False
>>> expression = Not(Literal("a"))
>>> expression(["a"])
False
>>> expression(["other"])
True
>>> expression([])
True
>>> expression = And(Or(Literal("a"), Literal("b")), Literal("c"))
>>> expression(["a", "c"])
True
>>> expression(["c", "other"])
False
>>> expression([])
False
"""

import re
Expand All @@ -37,23 +45,43 @@
# TAG-EXPRESSION MODEL CLASSES:
# -----------------------------------------------------------------------------
class Expression(object):
"""Abstract base class for boolean expression terms of a tag-expression
(or representing a parsed tag-expression (evaluation-tree)).
"""Abstract base class for boolean expression terms of a tag expression
(or representing a parsed tag expression (evaluation-tree)).
"""
# pylint: disable=too-few-public-methods

def evaluate(self, values):
"""Evaluate whether expression matches values.
Args:
values (Iterable[str]): Tag names to evaluate.
Returns:
bool: Whether expression evaluates with values.
"""
raise NotImplementedError()

def __call__(self, values):
"""Call operator to make an expression-object callable."""
"""Call operator to make an expression object callable.
Args:
values (Iterable[str]): Tag names to evaluate.
Returns:
bool: True if expression is true, False otherwise
"""
return bool(self.evaluate(values))


class Literal(Expression):
"""Used as placeholder for a tag in a boolean tag-expression."""
"""Used as placeholder for a tag in a boolean tag expression."""
# pylint: disable=too-few-public-methods
def __init__(self, name):
"""Initialie literal with tag name.
Args:
name (str): Tag name to represent as literal.
"""
super(Literal, self).__init__()
self.name = name

Expand All @@ -77,6 +105,14 @@ class And(Expression):
"""
# pylint: disable=too-few-public-methods
def __init__(self, *terms):
"""Create Boolean-AND expression.
Args:
terms (Iterable[Expression]): List of boolean expressions to AND.
Returns:
None
"""
super(And, self).__init__()
self.terms = terms

Expand Down Expand Up @@ -110,6 +146,14 @@ class Or(Expression):
# pylint: disable=too-few-public-methods

def __init__(self, *terms):
"""Create Boolean-OR expression.
Args:
terms (Iterable[Expression]): List of boolean expressions to OR.
Returns:
None
"""
super(Or, self).__init__()
self.terms = terms

Expand Down Expand Up @@ -140,6 +184,14 @@ class Not(Expression):
# pylint: disable=too-few-public-methods

def __init__(self, term):
"""Create Boolean-AND expression.
Args:
term (Expression): Boolean expression.
Returns:
None
"""
super(Not, self).__init__()
self.term = term

Expand All @@ -163,6 +215,14 @@ class True_(Expression): # pylint: disable=invalid-name
# pylint: disable=too-few-public-methods

def evaluate(self, values):
"""Evaluates to True.
Args:
values (Any): Required by API though not used.
Returns:
Literal[True]
"""
return True

def __str__(self):
Expand Down
Loading

0 comments on commit a2e1279

Please sign in to comment.