Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cucumber Expressions for Python #65

Merged
merged 51 commits into from
Mar 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
36613c8
First commit for python cucumber expressions
jsa34 Jan 15, 2022
fa6821a
module naming and test dir location update from feedback - thanks, @j…
jsa34 Jan 16, 2022
1bafbfa
Fix broken test
jsa34 Jan 17, 2022
1dc0d6c
Remove expression_factory.py - regexps are raw strings...
jsa34 Jan 18, 2022
2a3e625
Remove expression_factory.py - regexps are raw strings...
jsa34 Jan 18, 2022
633e097
Update CHANGELOG.md
jsa34 Jan 18, 2022
1df0953
Update test to pass class not object
jsa34 Jan 18, 2022
48ca909
Update README.md
jsa34 Jan 18, 2022
033a650
Update README.md
jsa34 Jan 18, 2022
5cc9502
Merge remote-tracking branch 'origin/python-wip' into python-wip
jsa34 Jan 18, 2022
ce62403
Merge branch 'main' into python-wip
jsa34 Jan 18, 2022
25d354c
Updating docs to reference type parameter
jsa34 Jan 19, 2022
2b9ce47
Making more "pythonic" - improvements to logic and using more pythoni…
jsa34 Jan 25, 2022
bb2ca3c
Merge remote-tracking branch 'origin/python-wip' into python-wip
jsa34 Jan 25, 2022
873b49b
Responding to some feedback and added missing data types from dev wor…
jsa34 Jan 31, 2022
4d34d67
Created test-python.yaml
jsa34 Jan 31, 2022
dfb6f28
Remove commented out code
jsa34 Jan 31, 2022
384fb40
Superfluous return
jsa34 Jan 31, 2022
4975c4c
Merge branch 'cucumber:main' into python-wip
jsa34 Jan 31, 2022
f047c06
Path issue
jsa34 Jan 31, 2022
f7042a8
Forgot relative to project root not python module
jsa34 Jan 31, 2022
3285f78
Resolve compat issues with python < 3.8 regarding type hints and walr…
jsa34 Jan 31, 2022
618e4eb
Merge remote-tracking branch 'origin/python-wip' into python-wip
jsa34 Jan 31, 2022
18894fc
Remove 3.6 - no longer supported...
jsa34 Jan 31, 2022
aa94c42
Clean up test docs
jsa34 Jan 31, 2022
7876d18
Merge remote-tracking branch 'origin/python-wip' into python-wip
jsa34 Jan 31, 2022
9b0a7da
Replace param_type with type, with caveat that it may shadow built-in
jsa34 Feb 1, 2022
89921cc
Added link to changes for python
jsa34 Feb 1, 2022
65172b5
Coverage of other os combos?
jsa34 Feb 1, 2022
dfca1c3
Precommit lint test job
jsa34 Feb 1, 2022
eaf521b
Remove precommit running
jsa34 Feb 1, 2022
99a15a1
Remove references to param_type
jsa34 Feb 1, 2022
6977183
Reinstate precommit hook as part of ci
jsa34 Feb 1, 2022
02eae09
Fix spacing
jsa34 Feb 1, 2022
954a654
Black fixes
jsa34 Feb 1, 2022
bd9ec26
Merge remote-tracking branch 'origin/python-wip' into python-wip
jsa34 Feb 1, 2022
4e285c1
pylint fixes
jsa34 Feb 2, 2022
b84b65c
Add poetry files
jsa34 Feb 2, 2022
5288233
Migrating to poetry
jsa34 Feb 2, 2022
9611111
Not sure why I ever name the tests module "test"...
jsa34 Feb 2, 2022
e611db4
Merge remote-tracking branch 'origin/python-wip' into python-wip
jsa34 Feb 2, 2022
d6d701b
No need to cd to python anymore
jsa34 Feb 2, 2022
64751cc
Replaced os.path with Path (following feedback from @blaisep - thanks!)
jsa34 Feb 2, 2022
1a038b1
Merge remote-tracking branch 'origin/python-wip' into python-wip
jsa34 Feb 2, 2022
fe9a822
Try and fix windows...
jsa34 Feb 2, 2022
8211bb1
Wrong os name used...
jsa34 Feb 2, 2022
dcc91e5
Feedback updates
jsa34 Feb 3, 2022
94de29e
Merge remote-tracking branch 'origin/python-wip' into python-wip
jsa34 Feb 3, 2022
fb9fbce
Release mechanism
jsa34 Feb 3, 2022
18c7482
Merge branch 'cucumber:main' into python-wip
jsa34 Feb 3, 2022
17ad065
Forgot to add check version for poetry
jsa34 Feb 3, 2022
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
49 changes: 49 additions & 0 deletions .github/workflows/release-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Release Python

on:
push:
branches: [release/*]

jobs:
release:
name: Release
runs-on: ubuntu-latest
defaults:
run:
working-directory: python
steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Python 3.10
uses: actions/setup-python@v2
with:
python-version: "3.10"

- name: Install Poetry
run: python install-poetry.py -y

- name: Update PATH
run: echo "$HOME/.local/bin" >> $GITHUB_PATH

- name: Build project for distribution
run: poetry build

- name: Check Version
id: check-version
run: |
[[ "$(poetry version --short)" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] \
|| echo ::set-output name=prerelease::true

- name: Create Release
uses: ncipollo/release-action@v1
with:
artifacts: "dist/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
prerelease: steps.check-version.outputs.prerelease == 'true'

- name: Publish to PyPI
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }}
run: poetry publish
94 changes: 94 additions & 0 deletions .github/workflows/test-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: test-python

on:
push:
pull_request:
branches:
- main

jobs:
test-python-linting:
defaults:
run:
working-directory: python
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
python-version: ["3.10"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Linting
run: |
python -m pip install pre-commit
pre-commit run --all-files

test-python:
runs-on: ${{ matrix.os }}
defaults:
run:
working-directory: python
shell: bash
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
python-version: ["3.7", "3.8", "3.9", "3.10"]
include:
- os: windows-latest
python-version: "3.10"
- os : macos-latest
python-version: "3.10"
steps:
- uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Get full Python version
id: full-python-version
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")

- name: Bootstrap poetry
run: |
curl -sL https://install.python-poetry.org | python - -y ${{ matrix.bootstrap-args }}

- name: Update PATH
if: ${{ matrix.os != 'windows-latest' }}
run: echo "$HOME/.local/bin" >> $GITHUB_PATH

- name: Update Path for Windows
if: ${{ matrix.os == 'windows-latest' }}
run: echo "$APPDATA\Python\Scripts" >> $GITHUB_PATH

- name: Configure poetry
run: poetry config virtualenvs.in-project true

- name: Set up cache
uses: actions/cache@v2
id: cache
with:
path: .venv
key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }}

- name: Ensure cache is healthy
if: steps.cache.outputs.cache-hit == 'true'
run: timeout 10s poetry rupoen pip --version || rm -rf .venv

- name: Install dependencies
run: poetry install

- name: Install pytest plugin
run: poetry run pip install pytest-github-actions-annotate-failures

- name: Run pytest
run: poetry run python -m pytest -p no:sugar -q tests/
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- [Ruby,JavaScript,Go] Add `bigdecimal`, `biginteger` parameter types ([#42](https://github.com/cucumber/cucumber-expressions/pull/42))
- [.NET] Implementation of Cucumber Expressions by porting the Java parser
([#1743](https://github.com/cucumber/cucumber-expressions/pull/45))
- [Python] Added Python Cucumber Expressions
jsa34 marked this conversation as resolved.
Show resolved Hide resolved
([#65](https://github.com/cucumber/cucumber-expressions/pull/65))

### Changed
- [Go] Parameters of type `{float}` are now parsed as `float32` (previously it was `float64`).
Expand Down
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ a parameter type.
| ------------- | ----------- |
| `name` | The name the parameter type will be recognised by in output parameters.
| `regexp` | A regexp that will match the parameter. May include capture groups.
| `type` | The return type of the transformer {{% stepdef-body %}}.
| `type` | The return type of the transformer.
| `transformer` | A function or method that transforms the match from the regexp. Must have arity 1 if the regexp doesn't have any capture groups. Otherwise the arity must match the number of capture groups in `regexp`. |
| `useForSnippets` / `use_for_snippets` | Defaults to `true`. That means this parameter type will be used to generate snippets for undefined steps. If the `regexp` frequently matches text you don't intend to be used as arguments, disable its use for snippets with `false`. |
| `preferForRegexpMatch` / `prefer_for_regexp_match` | Defaults to `false`. Set to `true` if you have step definitions that use regular expressions, and you want this parameter type to take precedence over others during a match. |
Expand Down Expand Up @@ -155,6 +155,17 @@ public Color ConvertColor(string colorValue)
}
```

#### Python

```python
ParameterType(
name= 'color',
regexp= "red|blue|yellow",
type= Color,
transformer= lambda s: Color(),
)
```

*Note: Currently the parameter name cannot be customized, so the custom parameters can only be used with the type name, e.g. `{Color}`.*

## Optional text
Expand Down
3 changes: 3 additions & 0 deletions python/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
venv/
# Pytest
.pytest_cache
11 changes: 11 additions & 0 deletions python/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
repos:
jsa34 marked this conversation as resolved.
Show resolved Hide resolved
- repo: https://github.com/psf/black
rev: 21.12b0
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
rev: 4.0.1
hooks:
- id: flake8
args: ['--max-line-length=130','--ignore=E203,W503']

21 changes: 21 additions & 0 deletions python/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) Cucumber Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
38 changes: 38 additions & 0 deletions python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Cucumber Expressions for Python

[The main docs are here](https://github.com/cucumber/cucumber-expressions#readme).

## Build system

This project uses [Poetry](https://python-poetry.org/) as its build system.
In order to develop on this project, please install Poetry as per your system's instructions on the link above.

## Tests

The test suite uses `pytest` as its testing Framework.


### Preparing to run the tests

In order to set up your dev environment, run the following command from this project's directory:

``` python
poetry install
```
It will install all package and development requirements, and once that is done it will do a dev-install of the source code.

You only need to run it once, code changes will propagate directly and do not require running the install again.


### Running the tests

`pytest` automatically picks up files in the current directory or any subdirectories that have the prefix or suffix of `test_*.py`.
Test function names must start with `test*`.
Test class names must start with `Test*`.

To run all tests:

``` python
poetry run pytest
```

Empty file.
42 changes: 42 additions & 0 deletions python/cucumber_expressions/argument.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from __future__ import annotations

from typing import Optional, List

from cucumber_expressions.group import Group
from cucumber_expressions.parameter_type import ParameterType
from cucumber_expressions.tree_regexp import TreeRegexp
from cucumber_expressions.errors import CucumberExpressionError


class Argument:
def __init__(self, group, parameter_type):
self._group: Group = group
self.parameter_type: ParameterType = parameter_type

@staticmethod
def build(
tree_regexp: TreeRegexp, text: str, parameter_types: List
) -> Optional[List[Argument]]:
match_group = tree_regexp.match(text)
if not match_group:
return None

arg_groups = match_group.children

if len(arg_groups) != len(parameter_types):
raise CucumberExpressionError(
f"Group has {len(arg_groups)} capture groups, but there were {len(parameter_types)} parameter types"
)

return [
Argument(arg_group, parameter_type)
for parameter_type, arg_group in zip(parameter_types, arg_groups)
]

@property
def value(self):
return self.parameter_type.transform(self.group.values if self.group else None)

@property
def group(self):
return self._group
Loading