Skip to content

Add ability to select path segments using Python re regexprs #146

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

Closed
wants to merge 14 commits into from
Closed
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
56 changes: 56 additions & 0 deletions .github/workflows/linterTest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: LinterTest
# ------------------------------------------------------------
# (C) Alain Lichnewsky, 2021
#
# For running under Github's Actions
#
# Script performs basic static test of the package under Python-3,
# including added functionality.
# ------------------------------------------------------------

# Controls when the action will run.
on:
#
## Not enabled, would triggers the workflow on push or pull request events but
## only for the AL-addRegexp branch.
#push:
# branches: [ AL-addRegexp ]

# Allows to run this workflow manually from the Github Actions tab
workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in
# parallel
jobs:
# This workflow contains a single job called "super-lint"
super-lint:
# Steps represent a sequence of tasks that will be executed by the job
# Name the Job
name: Lint code base
# Set the type of machine to run on
runs-on: ubuntu-latest

steps:
# Checks out a copy of your repository on the ubuntu-latest machine
- name: Checkout code
uses: actions/checkout@v2

# Runs a single command using the runners shell, in practice it is useful
# to figure out some of the environment setup
- name: Use shell to figure out environment
run: echo Hello from Github Actions !!;
bash --version | head -1 ;
echo LANG=${LANG} SHELL=${SHELL} ;
echo PATH=${PATH} ;
pwd;
ls -ltha;

# Runs the Super-Linter action
- name: Run Super-Linter
uses: github/super-linter@v3
#
# this script requires some environment variables
#
env:
DEFAULT_BRANCH: AL-addRegexp
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
105 changes: 105 additions & 0 deletions .github/workflows/python3-pypy-Test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: Test python package dpath-python
# ------------------------------------------------------------
# (C) Alain Lichnewsky, 2021
#
# For running under Github's Actions
#
# Here the idea is to use tox for testing and test on python 3.8 and
# pypy-3.7.
#
# There are numerous issues that must be understood with the predefined
# features of Github's preloaded containers.
# Here :
# - try and load in 2 separate steps
# - probably not optimal in viexw of preloaded configurations
#
# ------------------------------------------------------------

on:
# manual dispatch, this script will not be started automagically
workflow_dispatch:

jobs:
test-python3:

timeout-minutes: 60

runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: '3.8'
architecture: 'x64'

- name: Set up Pypy 3.7
uses: actions/setup-python@v2
with:
python-version: 'pypy-3.7'
architecture: 'x64'


- name: Ascertain configuration
#
# Collect information concerning $HOME and the location of
# file(s) loaded from Github/
run: |
echo Working dir: $(pwd)
echo Files at this location:
ls -ltha
echo HOME: ${HOME}
echo LANG: ${LANG} SHELL: ${SHELL}
which python
echo LD_LIBRARY_PATH: ${LD_LIBRARY_PATH}
echo PYTHONPATH: \'${PYTHONPATH}\'

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# ** here (it is expected that) **
# pythonLocation: /opt/hostedtoolcache/Python/3.8.8/x64
# LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.8.8/x64/lib
# Working dir /home/runner/work/dpath-python/dpath-python
# HOME: /home/runner
# LANG: C.UTF-8
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

- name: Install dependencies

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# requirements install the test framework, which is not
# required by the package in setup.py
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
run: |
python -m pip install --upgrade pip setuptools wheel
if [ -f requirements.txt ]; then
pip install -r requirements.txt;
fi
python setup.py install
echo which nose :$(which nose)
echo which nose2: $(which nose2)
echo which nose2-3.6: $(which nose2-3.6)
echo which nose2-3.8: $(which nose2-3.8)

- name: Tox testing

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# move to tox testing, otherwise will have to parametrize
# nose in more details; here tox.ini will apply
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
run: |
pip install tox
echo "Installed tox"
tox
echo "Ran tox"

- name: Nose2 testing

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Last try... with a nose2.cfg file
#
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
run: |
nose2 -c nose2.cfg
92 changes: 92 additions & 0 deletions .github/workflows/python3Test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Test python package dpath-python
# ------------------------------------------------------------
# (C) Alain Lichnewsky, 2021
#
# For running under Github's Actions
#
# Script performs basic test of the Python-3 version of the package
# including added functionality.
# ------------------------------------------------------------

on:
# [push]

workflow_dispatch:

jobs:
test-python3:

timeout-minutes: 60

runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: [ '3.8' , 'pypy-3.7' ]
architecture: 'x64'

- name: Ascertain configuration
#
# Collect information concerning $HOME and the location of
# file(s) loaded from Github/
run: |
echo Working dir: $(pwd)
echo Files at this location:
ls -ltha
echo HOME: ${HOME}
echo LANG: ${LANG} SHELL: ${SHELL}
which python
echo LD_LIBRARY_PATH: ${LD_LIBRARY_PATH}
echo PYTHONPATH: \'${PYTHONPATH}\'

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# ** here (it is expected that) **
# pythonLocation: /opt/hostedtoolcache/Python/3.8.8/x64
# LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.8.8/x64/lib
# Working dir /home/runner/work/dpath-python/dpath-python
# HOME: /home/runner
# LANG: C.UTF-8
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

- name: Install dependencies

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# requirements install the test framework, which is not
# required by the package in setup.py
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
run: |
python -m pip install --upgrade pip setuptools wheel
if [ -f requirements.txt ]; then
pip install -r requirements.txt;
fi
python setup.py install
echo which nose :$(which nose)
echo which nose2: $(which nose2)
echo which nose2-3.6: $(which nose2-3.6)
echo which nose2-3.8: $(which nose2-3.8)

- name: Tox testing

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# move to tox testing, otherwise will have to parametrize
# nose in more details; here tox.ini will apply
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
run: |
pip install tox
echo "Installed tox"
tox
echo "Ran tox"

- name: Nose2 testing

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Last try... with a nose2.cfg file
#
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
run: |
nose2 -c nose2.cfg
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
/build
/env
*.pyc
*~
.githubLogs/
51 changes: 51 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ It allows you to specify globs (ala the bash eglob syntax, through some
advanced fnmatch.fnmatch magic) to access dictionary elements, and
provides some facility for filtering those results.

An extension is proposed :ref:`regexprs`
that permits to use Python's
re regular expressions for globing matches.

sdists are available on pypi: http://pypi.python.org/pypi/dpath

DPATH NEEDS NEW MAINTAINERS. SEE https://github.com/akesterson/dpath-python/issues/136
Expand Down Expand Up @@ -439,6 +443,53 @@ To get around this, you can sidestep the whole "filesystem path" style, and aban
>>> dpath.util.get(['a', 'b/c'])
0

.. :: _regexprs:

Need more expressive regular expressions in paths ?
===================================================

We propose the following:
- a path component may also be specified as ::
{<re.regexpr>}

where `<re.regexpr>` is a regular expression accepted by the standard Python module `re`

- when using the list form for a path, a list element can also
be expressed as

- a string as above

- the output of ::

re.compile( args )

- for backwards compatibility, this facility must be enabled ::

import dpath
dpath.options.DPATH_ACCEPT_RE_REGEXP = True

Example:

.. code-block:: python

import dpath
dpath.options.DPATH_ACCEPT_RE_REGEXP = True

js = loadJson()
selPath = 'Config/{(Env|Cmd)}'
x = dpath.util.search(js.lod, selPath)
print(x)

selPath = [ re.compile('(Config|Graph)') , re.compile('(Env|Cmd|Data)') ]
x = dpath.util.search(js.lod, selPath)
print(x)

selPath = '{(Config|Graph)}/{(Env|Cmd|Data)}'
x = dpath.util.search(js.lod, selPath)
print(x)



dpath.segments : The Low-Level Backend
======================================

Expand Down
1 change: 1 addition & 0 deletions dpath/options.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ALLOW_EMPTY_STRING_KEYS = False
DPATH_ACCEPT_RE_REGEXP = False
21 changes: 19 additions & 2 deletions dpath/segments.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
from dpath.exceptions import InvalidGlob, InvalidKeyName, PathNotFound
from dpath import options
from fnmatch import fnmatchcase
import sys


import re
try:
RE_PATTERN_TYPE = re.Pattern
except AttributeError:
RE_PATTERN_TYPE = re._pattern_type


def kvs(node):
Expand All @@ -22,7 +30,12 @@ def leaf(thing):

leaf(thing) -> bool
'''
leaves = (bytes, str, int, float, bool, type(None))
# resolve unicode issue in Python2.7, see test/test_unicode.py
# (TestEncoding.test_reproduce*)
if sys.version_info < (3, 0):
leaves = (bytes, str, unicode, int, float, bool, type(None))
else:
leaves = (bytes, str, int, float, bool, type(None))

return isinstance(thing, leaves)

Expand Down Expand Up @@ -226,7 +239,11 @@ def match(segments, glob):
# exception while attempting to match into a False for the
# match.
try:
if not fnmatchcase(s, g):
if isinstance(g, RE_PATTERN_TYPE):
mobj = g.match(s)
if mobj is None:
return False
elif not fnmatchcase(s, g):
return False
except:
return False
Expand Down
Loading