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
17 changes: 8 additions & 9 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,23 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: '3.10'
architecture: 'x64'
python-version: '3.x'

- name: Install dependencies and package
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install ".[build]"

- name: Build source and binary distribution package
run: |
python setup.py sdist bdist_wheel
env:
PACKAGE_VERSION: ${{ github.ref }}
python -m build

- name: Check distribution package
run: |
Expand Down
56 changes: 24 additions & 32 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,39 @@ name: Run linter and tests
on: [push, pull_request]

jobs:
test:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- '3.10'
- '3.11'
- '3.12'
- '3.13'
- '3.14'

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

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

- name: Install dependencies and package
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Install dependencies and package
run: |
python -m pip install --upgrade pip
pip install -e ".[test,dev]"

- name: Check formatting with black
run: |
black --check './param_parser'
- name: Run lint and code review
run: |
pre-commit run --all-files

- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 './param_parser' --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 './param_parser' --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Run tests with coverage
run: |
coverage run --source='./param_parser' -m pytest
coverage xml

- name: Run tests
run: |
# run tests with coverage
coverage run --source='./param_parser' -m pytest
coverage xml

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ coverage.xml
*.egg-info
*.pyc
*.pyo
*.sqlite*
build/
dist/
27 changes: 27 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-merge-conflict
- id: end-of-file-fixer
- id: requirements-txt-fixer
- id: trailing-whitespace
args: ["--markdown-linebreak-ext=md"]

- repo: https://github.com/asottile/pyupgrade
rev: v3.21.2
hooks:
- id: pyupgrade
args: ["--py310-plus"]

- repo: https://github.com/asottile/add-trailing-comma
rev: v4.0.0
hooks:
- id: add-trailing-comma

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.14
hooks:
- id: ruff
args: [ --fix ]
- id: ruff-format
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License
The MIT License (MIT)

Copyright (c) 2022 ANEXIA Internetdienstleistungs GmbH
Copyright (c) 2022-2026 Anexia

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ param-parser
[![Test Status](https://github.com/anexia/python-param-parser/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/anexia/python-param-parser/actions/workflows/test.yml)
[![Codecov](https://codecov.io/gh/anexia/python-param-parser/branch/main/graph/badge.svg)](https://codecov.io/gh/anexia/python-param-parser)

`param-parser` is a parser library for a param string expression. Those expressions are arbitrary strings with
`param-parser` is a parser library for a param string expression. Those expressions are arbitrary strings with
placeholders in it, where a placeholder consists of a name, an optional type and a list of options.

# Installation
Expand All @@ -32,8 +32,8 @@ this-is-a-{param:string}-expression
this-is-a-{param}-expression
```

As you see, a param is introduced by an opening curly bracket, followed by the name of the param, a colon, the type of
the param, another colon and a comma separated list of options. The param configuration gets terminated by a closing
As you see, a param is introduced by an opening curly bracket, followed by the name of the param, a colon, the type of
the param, another colon and a comma separated list of options. The param configuration gets terminated by a closing
curly bracket. Note that the type and option configuration are optional, but the name is mandatory.

To parse an expression shown above, use the Python code as follows:
Expand Down Expand Up @@ -70,6 +70,7 @@ result[0].sequence_value # Gets `"this-is-a-{param:string:option1,option2,optio

| This Project | Python Version |
|--------------|----------------|
| 1.2.* | 3.10-3.14 |
| 1.1.* | 3.9-3.13 |
| 1.0.* | 3.7-3.11 |

Expand Down
7 changes: 7 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Reporting Security Issues

Please report any security issues you discovered to opensource[at]anexia-it[dot]com

We will assess the risk, plus make a fix available before we create a GitHub issue.

Thank you for your contribution.
5 changes: 1 addition & 4 deletions param_parser/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,4 @@ def __init__(self, message: str):
super().__init__(self._message)

def __repr__(self) -> str:
return "{}({})".format(
self.__class__.__name__,
repr(self._message),
)
return f"{self.__class__.__name__}({repr(self._message)})"
15 changes: 7 additions & 8 deletions param_parser/lexer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import abc
import typing

from .token import *
from .token import Token


__all__ = [
Expand Down Expand Up @@ -39,7 +38,7 @@ def get_next_token(self) -> Token:
pass

@property
def current_character(self) -> typing.Optional[str]:
def current_character(self) -> str | None:
"""
Gets the current character the position pointer points to on the expression. If the position
pointer exceeds the length of the expression, :data:`None` gets returned.
Expand Down Expand Up @@ -68,7 +67,10 @@ def read_single(self, token_type: str) -> Token:
:return: The produced token instance.
"""
token = Token(
self._position, token_type, self.current_character, self.current_character
self._position,
token_type,
self.current_character,
self.current_character,
)
self.advance()

Expand Down Expand Up @@ -102,10 +104,7 @@ def read_sequence(self, token_type: str, until: list = None) -> Token:
return Token(position, token_type, sequence, raw_sequence)

def __repr__(self) -> str:
return "{}({})".format(
self.__class__.__name__,
repr(self._expression),
)
return f"{self.__class__.__name__}({repr(self._expression)})"


class ParamLexer(Lexer):
Expand Down
29 changes: 9 additions & 20 deletions param_parser/node.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import abc
import typing


__all__ = [
Expand All @@ -16,9 +15,7 @@ class Node(abc.ABC):
"""

def __repr__(self) -> str:
return "{}()".format(
self.__class__.__name__,
)
return f"{self.__class__.__name__}()"


class ParamNode(Node):
Expand All @@ -30,8 +27,8 @@ class ParamNode(Node):
def __init__(
self,
param_name: str,
param_type: typing.Optional[str],
param_options: typing.Optional[list],
param_type: str | None,
param_options: list | None,
):
"""
Init method for the class.
Expand All @@ -41,8 +38,8 @@ def __init__(
:param param_options: The list of options of the param. Becomes an empty list if passed :data:`None`.
"""
self._param_name: str = param_name
self._param_type: typing.Optional[str] = param_type or None
self._param_options: typing.List[str] = param_options or []
self._param_type: str | None = param_type or None
self._param_options: list[str] = param_options or []

@property
def param_name(self) -> str:
Expand All @@ -54,7 +51,7 @@ def param_name(self) -> str:
return self._param_name

@property
def param_type(self) -> typing.Optional[str]:
def param_type(self) -> str | None:
"""
Gets the type of the param.

Expand All @@ -63,7 +60,7 @@ def param_type(self) -> typing.Optional[str]:
return self._param_type

@property
def param_options(self) -> typing.List[str]:
def param_options(self) -> list[str]:
"""
Gets the list of options of the param. Each option is a string.

Expand All @@ -72,12 +69,7 @@ def param_options(self) -> typing.List[str]:
return self._param_options

def __repr__(self) -> str:
return "{}({}, {}, {})".format(
self.__class__.__name__,
repr(self._param_name),
repr(self._param_type),
repr(self._param_options),
)
return f"{self.__class__.__name__}({repr(self._param_name)}, {repr(self._param_type)}, {repr(self._param_options)})"


class SequenceNode(Node):
Expand All @@ -103,7 +95,4 @@ def sequence_value(self) -> str:
return self._sequence_value

def __repr__(self) -> str:
return "{}({})".format(
self.__class__.__name__,
repr(self._sequence_value),
)
return f"{self.__class__.__name__}({repr(self._sequence_value)})"
Loading
Loading