Skip to content

Commit

Permalink
Merge pull request #184 from wimglenn/hyphen-minus
Browse files Browse the repository at this point in the history
allow hyphen in field name. closes #86
  • Loading branch information
wimglenn committed Jun 11, 2024
2 parents e0c19dc + 3698ea8 commit 334db14
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 6 deletions.
18 changes: 17 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ jobs:
run-test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version:
- "3.7"
- "3.8"
- "3.9"
- "3.10"
Expand All @@ -35,6 +35,22 @@ jobs:
with:
token: ${{ secrets.CODECOV_TOKEN }}

tests-37:
name: Python 3.7 on ubuntu-20.04
runs-on: ubuntu-20.04
container:
image: python:3.7
steps:
- uses: actions/checkout@v3
- name: Run tests
run: |
pip install -r tests/requirements.txt
python -m pytest
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}

tests-27:
name: Python 2.7 on ubuntu-20.04
runs-on: ubuntu-20.04
Expand Down
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ To run the tests locally:
Changelog
---------

- 1.20.2 Template field names can now contain - character i.e. HYPHEN-MINUS, chr(0x2d)
- 1.20.1 The `%f` directive accepts 1-6 digits, like strptime (thanks @bbertincourt)
- 1.20.0 Added support for strptime codes (thanks @bendichter)
- 1.19.1 Added support for sign specifiers in number formats (thanks @anntzer)
Expand Down
12 changes: 7 additions & 5 deletions parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from functools import partial


__version__ = "1.20.1"
__version__ = "1.20.2"
__all__ = ["parse", "search", "findall", "with_pattern"]

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -398,7 +398,7 @@ def extract_format(format, extra_types):
return locals()


PARSE_RE = re.compile(r"({{|}}|{\w*(?:\.\w+|\[[^]]+])*(?::[^}]+)?})")
PARSE_RE = re.compile(r"({{|}}|{[\w-]*(?:\.[\w-]+|\[[^]]+])*(?::[^}]+)?})")


class Parser(object):
Expand Down Expand Up @@ -476,11 +476,11 @@ def _match_re(self):

@property
def named_fields(self):
return self._named_fields.copy()
return self._named_fields[:]

@property
def fixed_fields(self):
return self._fixed_fields.copy()
return self._fixed_fields[:]

@property
def format(self):
Expand Down Expand Up @@ -619,7 +619,7 @@ def _generate_expression(self):
def _to_group_name(self, field):
# return a version of field which can be used as capture group, even
# though it might contain '.'
group = field.replace(".", "_").replace("[", "_").replace("]", "_")
group = field.replace(".", "_").replace("[", "_").replace("]", "_").replace("-", "_")

# make sure we don't collide ("a.b" colliding with "a_b")
n = 1
Expand All @@ -629,6 +629,8 @@ def _to_group_name(self, field):
group = field.replace(".", "_" * n)
elif "_" in field:
group = field.replace("_", "_" * n)
elif "-" in field:
group = field.replace("-", "_" * n)
else:
raise KeyError("duplicated group name %r" % (field,))

Expand Down
20 changes: 20 additions & 0 deletions tests/test_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,3 +763,23 @@ def test_parser_format():
assert parser.format.format("world") == "hello world"
with pytest.raises(AttributeError):
parser.format = "hi {}"


def test_hyphen_inside_field_name():
# https://github.com/r1chardj0n3s/parse/issues/86
# https://github.com/python-openapi/openapi-core/issues/672
template = "/local/sub/{user-id}/duration"
assert parse.Parser(template).named_fields == ["user_id"]
string = "https://dummy_server.com/local/sub/1647222638/duration"
result = parse.search(template, string)
assert result["user-id"] == "1647222638"


def test_hyphen_inside_field_name_collision_handling():
template = "/foo/{user-id}/{user_id}/{user.id}/bar/"
assert parse.Parser(template).named_fields == ["user_id", "user__id", "user___id"]
string = "/foo/1/2/3/bar/"
result = parse.search(template, string)
assert result["user-id"] == "1"
assert result["user_id"] == "2"
assert result["user.id"] == "3"

0 comments on commit 334db14

Please sign in to comment.