diff --git a/.github/workflows/linterTest.yml b/.github/workflows/linterTest.yml new file mode 100644 index 0000000..c741e55 --- /dev/null +++ b/.github/workflows/linterTest.yml @@ -0,0 +1,56 @@ +name: LinterTest + # ------------------------------------------------------------ + # (C) Alain Lichnewsky, 2021, 2022 + # + # 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@latest + # + # this script requires some environment variables + # + env: + DEFAULT_BRANCH: AL-master4merge + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/python3-pypy-Test.yml b/.github/workflows/python3-pypy-Test.yml new file mode 100644 index 0000000..0ffd1dc --- /dev/null +++ b/.github/workflows/python3-pypy-Test.yml @@ -0,0 +1,121 @@ +name: Test python package dpath-python with regexp ext and pypy + # ------------------------------------------------------------ + # (C) Alain Lichnewsky, 2021, 2022 + # + # 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. + # + # ------------------------------------------------------------ + +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@main + + - name: Set up Python 3.10 + uses: actions/setup-python@main + with: + python-version: '3.10' + architecture: 'x64' + + - name: Set up Pypy + uses: actions/setup-python@main + with: + python-version: 'pypy3.9' + architecture: 'x64' + + + - name: Ascertain configuration + shell: bash + # + # 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 + # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + shell: bash + run: | + python -m pip install --upgrade pip setuptools wheel + if [ -f requirements.txt ]; then + pip install -r requirements.txt; + fi + python -m pip install --upgrade nose2 hypothesis + 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: Check path preparing for pypy (1) + shell: bash + if: always() + run: | + test-utils/py_path_checker -M nose2 -U + + - name: Check path preparing for pypy (2) + shell: bash + if: always() + run: | + pypy3 test-utils/py_path_checker -M nose2 -U + + - name: Perform python tests + shell: bash + if: always() + run: | + PYTHONPATH="." test-utils/nose_runner -E -s tests + + - name: Perform pypy tests + shell: bash + if: always() + run: | + PYTHONPATH=".:/usr/local/lib/python3.10/dist-packages/" \ + pypy3 test-utils/nose_runner -E -s tests + + + - name: Tox testing + + # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # move to tox testing, otherwise will have to parametrize + # nose in more details; here tox.ini will apply + # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + shell: bash + if: always() + run: | + pip install tox + echo "Installed tox" + tox + echo "Ran tox" diff --git a/.github/workflows/python3Test.yml b/.github/workflows/python3Test.yml new file mode 100644 index 0000000..d524c0d --- /dev/null +++ b/.github/workflows/python3Test.yml @@ -0,0 +1,98 @@ +name: Test python package dpath-python with regexp extension + # ------------------------------------------------------------ + # (C) Alain Lichnewsky, 2021, 2022 + # + # For running under Github's Actions + # + # Script performs basic test of the Python-3 version of the package + # including added functionality (regexp in search paths). + # ------------------------------------------------------------ + +on: + workflow_dispatch: + # Allows manual dispatch from the Actions tab + +jobs: + test-python3: + + timeout-minutes: 60 + + runs-on: ubuntu-latest + + strategy: + matrix: + # Match versions specified in tox.ini + python-version: ['3.10', 'pypy3.9'] + + steps: + - name: Checkout code + uses: actions/checkout@main + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@main + with: + python-version: ${{ matrix.python-version }} + 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 \ + nose2 hypothesis + 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: nose_runner testing + + # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # This is the nose2 wrapper that allows to set pgm. parms + # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + run: | + echo running the nose2 wrapper + PYTHONPATH="." test-utils/nose_runner -E -s tests + + - 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" diff --git a/.gitignore b/.gitignore index 52fd738..93ad9ce 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,14 @@ venv_39 .idea/ dpath.egg-info/ dist/ -tests/.hypothesis \ No newline at end of file +tests/.hypothesis + +# Github logs +.githubLogs + +# Test etc +.coverage + +# Editor temporaries +*~ + \ No newline at end of file diff --git a/README.rst b/README.rst index 0ad3ad2..506db32 100644 --- a/README.rst +++ b/README.rst @@ -111,6 +111,9 @@ elements in ``x['a']['b']`` where the key is equal to the glob ``'[cd]'``. Okay. } } +**Note** : Using Python's `re` regular expressions instead of globs is explained +below re_regexp_. + ... Wow that was easy. What if I want to iterate over the results, and not get a merged view? @@ -438,6 +441,77 @@ To get around this, you can sidestep the whole "filesystem path" style, and aban >>> dpath.get(['a', 'b/c']) 0 +.. _re_regexp: + +Globs too imprecise? Use Python's `re` Regular Expressions +========================================================== + +Python's `re` regular expressions PythonRe_ may be used as follows: + + .. _PythonRe: https://docs.python.org/3/library/re.html + + - This facility must be enabled (for backwards compatibility): + + .. code-block:: python + + >>> import dpath + >>> dpath.options.DPATH_ACCEPT_RE_REGEXP = True + + - Now a path component may also be specified : + + - in a path expression, as {} where `` is a regular expression + accepted by the standard Python module `re`. For example: + + .. code-block:: python + + >>> selPath = 'Config/{(Env|Cmd)}' + >>> x = dpath.util.search(js.lod, selPath) + + .. code-block:: python + + >>> selPath = '{(Config|Graph)}/{(Env|Cmd|Data)}' + >>> x = dpath.util.search(js.lod, selPath) + + - 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 )`` + + An example: + + .. code-block:: python + + >>> selPath = [ re.compile('(Config|Graph)') , re.compile('(Env|Cmd|Data)') ] + >>> x = dpath.util.search(js.lod, selPath) + + More examples from a realistic json context: + + +-----------------------------------------+--------------------------------------+ + + **Extended path glob** | **Designates** + + +-----------------------------------------+--------------------------------------+ + + "\*\*/{[^A-Za-z]{2}$}" | "Id" + + +-----------------------------------------+--------------------------------------+ + + r"\*/{[A-Z][A-Za-z\\d]*$}" | "Name","Id","Created", "Scope",... + + +-----------------------------------------+--------------------------------------+ + + r"\*\*/{[A-Z][A-Za-z\\d]*\d$}" | EnableIPv6" + + +-----------------------------------------+--------------------------------------+ + + r"\*\*/{[A-Z][A-Za-z\\d]*Address$}" | "Containers/199c5/MacAddress" + + +-----------------------------------------+--------------------------------------+ + + With Python's chararcter string conventions, required backslashes in the `re` syntax + can be entered either in raw strings or using double backslashes, thus + the following are equivalent: + + +-----------------------------------------+----------------------------------------+ + + *with raw strings* | *equivalent* with double backslash + + +-----------------------------------------+----------------------------------------+ + + r"\*\*/{[A-Z][A-Za-z\\d]*\\d$}" | "\*\*/{[A-Z][A-Za-z\\\\d]*\\\\d$}" + + +-----------------------------------------+----------------------------------------+ + + r"\*\*/{[A-Z][A-Za-z\\d]*Address$}" | "\*\*/{[A-Z][A-Za-z\\\\d]*Address$}" + + +-----------------------------------------+----------------------------------------+ + + dpath.segments : The Low-Level Backend ====================================== diff --git a/buildTools/pypy-test b/buildTools/pypy-test new file mode 100755 index 0000000..b059b42 --- /dev/null +++ b/buildTools/pypy-test @@ -0,0 +1,125 @@ +#!/usr/bin/env bash + +# ...................................................................... +# Function : +# - check pypy installation +# - run pypy test +# +# +# Normally used/called by devel-Steps -y. +# +# Generalization; +# This proc does not know about installation parameters... files +# and directories need to be passes explicitely +# ...................................................................... +# +# (C) Alain Lichnewsky, 2022 +# +# ...................................................................... +trap 'status=$?; echo "error status is $status"; trap - EXIT; exit $status' ERR +SCRIPTPATH=$(dirname $(realpath $0)) +SCRIPTNAME=$(basename $(realpath $0)) + +# ...................................................................... +# Configurables +# ...................................................................... +PYPY=pypy3 +# ...................................................................... + + +function requireApproval () { + question="$1" + ok="YyOo" + notOK="nN" + pattern="[oOyY]" + prompt="Answer [${ok}]? " + count=0 + + echo "$question" + read -p "${prompt}" -n 1 inchar + while (( $count < 4 )) ; do + if [[ "$inchar" =~ $pattern ]] ; then + echo "" + return + else + exit 1 + fi + count=$(( 1 + $count)) + done + exit 1 +} + +function run_pypy () { + declare -r target="$1" + declare -r pythonpath="$2" + + declare -r pythonpath2="${pythonpath}:${HOME}/.local/lib/python3.10/site-packages/:/usr/local/lib/python3.10/dist-packages/" + export PYTHONPATH="${pythonpath2}" + + echo ${ECHO} PYTHONPATH="${pythonpath2}" + ${ECHO} ${PYPY} ${target} ${@: 3} +} + +function usage() { + less >/dev/stderr <] [-r