From 20471504c7f1bcb76937caec488583f74c578f1f Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 3 Oct 2024 18:37:25 -0400 Subject: [PATCH 01/40] Start separting code into verison branches --- admin-tools/merge-for-2.4.sh | 9 +++++++++ admin-tools/merge-for-3.0.sh | 11 +++++++++++ admin-tools/merge-for-3.3.sh | 9 +++++++++ admin-tools/merge-for-3.6.sh | 9 +++++++++ admin-tools/pyenv-2.4-2.7-versions | 9 +++++++++ admin-tools/pyenv-3.0-3.2-versions | 9 +++++++++ admin-tools/pyenv-3.3-3.5-versions | 8 ++++++++ admin-tools/pyenv-3.6-3.10-versions | 8 ++++++++ admin-tools/setup-python-3.0.sh | 10 ++++++++++ admin-tools/setup-python-3.3.sh | 10 ++++++++++ admin-tools/setup-python-3.6.sh | 10 ++++++++++ 11 files changed, 102 insertions(+) create mode 100755 admin-tools/merge-for-2.4.sh create mode 100755 admin-tools/merge-for-3.0.sh create mode 100755 admin-tools/merge-for-3.3.sh create mode 100755 admin-tools/merge-for-3.6.sh create mode 100644 admin-tools/pyenv-2.4-2.7-versions create mode 100644 admin-tools/pyenv-3.0-3.2-versions create mode 100644 admin-tools/pyenv-3.3-3.5-versions create mode 100644 admin-tools/pyenv-3.6-3.10-versions create mode 100755 admin-tools/setup-python-3.0.sh create mode 100755 admin-tools/setup-python-3.3.sh create mode 100755 admin-tools/setup-python-3.6.sh diff --git a/admin-tools/merge-for-2.4.sh b/admin-tools/merge-for-2.4.sh new file mode 100755 index 0000000..ef0766b --- /dev/null +++ b/admin-tools/merge-for-2.4.sh @@ -0,0 +1,9 @@ +#/bin/bash +# Setup for running Python 2.4 .. 2.7, merging python-3.0-to-3.2 into this branch +spark_24_owd=$(pwd) +cd $(dirname ${BASH_SOURCE[0]}) +(cd .. && PYTHON_VERSION=2.4 && pyenv local $PYTHON_VERSION) +if . ./setup-python-2.4.sh; then + git merge python-3.0-to-3.2 +fi +cd $spark_24_owd diff --git a/admin-tools/merge-for-3.0.sh b/admin-tools/merge-for-3.0.sh new file mode 100755 index 0000000..a381599 --- /dev/null +++ b/admin-tools/merge-for-3.0.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Setup for running Python 3.0 .. 3.2, merging 3.3-3.5 into this branch +spark_30_owd=$(pwd) +PYTHON_VERSION=3.1 +pyenv local $PYTHON_VERSION +cd $(dirname ${BASH_SOURCE[0]}) +(cd .. && PYTHON_VERSION=3.1 && pyenv local $PYTHON_VERSION) +if . ./setup-python-3.0.sh; then + git merge python-3.3-to-3.5 +fi +cd $spark_30_owd diff --git a/admin-tools/merge-for-3.3.sh b/admin-tools/merge-for-3.3.sh new file mode 100755 index 0000000..b6a45f0 --- /dev/null +++ b/admin-tools/merge-for-3.3.sh @@ -0,0 +1,9 @@ +#/bin/bash +# Setup for running Python 3.3 .. 3.5, merging Python 3.6-to-3.10 into this branch +spark_33_owd=$(pwd) +cd $(dirname ${BASH_SOURCE[0]}) +(cd .. && PYTHON_VERSION=3.3 && pyenv local $PYTHON_VERSION) +if . ./setup-python-3.3.sh; then + git merge python-3.6-to-3.10 +fi +cd $spark_33_owd diff --git a/admin-tools/merge-for-3.6.sh b/admin-tools/merge-for-3.6.sh new file mode 100755 index 0000000..babd24f --- /dev/null +++ b/admin-tools/merge-for-3.6.sh @@ -0,0 +1,9 @@ +#/bin/bash +# Setup for running Python 3.6 .. 3.10, merging master into this branch +spark_36_owd=$(pwd) +cd $(dirname ${BASH_SOURCE[0]}) +(cd .. && PYTHON_VERSION=3.6 && pyenv local $PYTHON_VERSION) +if . ./setup-python-3.6.sh; then + git merge master +fi +cd $spark_36_owd diff --git a/admin-tools/pyenv-2.4-2.7-versions b/admin-tools/pyenv-2.4-2.7-versions new file mode 100644 index 0000000..c513cb8 --- /dev/null +++ b/admin-tools/pyenv-2.4-2.7-versions @@ -0,0 +1,9 @@ +# -*- shell-script -*- +# Sets PYVERSIONS to be pyenv versions that +# we can use in the python-2.4-to-2.7 branch. + +if [[ $0 == ${BASH_SOURCE[0]} ]] ; then + echo "This script should be *sourced* rather than run directly through bash" + exit 1 +fi +export PYVERSIONS='2.4 2.5 2.6 pypy2.7-7.3.8 2.7' diff --git a/admin-tools/pyenv-3.0-3.2-versions b/admin-tools/pyenv-3.0-3.2-versions new file mode 100644 index 0000000..7410049 --- /dev/null +++ b/admin-tools/pyenv-3.0-3.2-versions @@ -0,0 +1,9 @@ +# -*- shell-script -*- +# Sets PYVERSIONS to be pyenv versions that +# we can use in the python-3.1-to-3.2 branch. + +if [[ $0 == ${BASH_SOURCE[0]} ]] ; then + echo "This script should be *sourced* rather than run directly through bash" + exit 1 +fi +export PYVERSIONS='3.0.1 3.1.5 3.2.6' diff --git a/admin-tools/pyenv-3.3-3.5-versions b/admin-tools/pyenv-3.3-3.5-versions new file mode 100644 index 0000000..e5792c2 --- /dev/null +++ b/admin-tools/pyenv-3.3-3.5-versions @@ -0,0 +1,8 @@ +# -*- shell-script -*- +# Sets PYVERSIONS to be pyenv versions that +# we can use in the python-3.3-to-3.5 branch. +if [[ $0 == ${BASH_SOURCE[0]} ]] ; then + echo "This script should be *sourced* rather than run directly through bash" + exit 1 +fi +export PYVERSIONS='3.5 3.3 3.4 pypy3.5-7.0.0' diff --git a/admin-tools/pyenv-3.6-3.10-versions b/admin-tools/pyenv-3.6-3.10-versions new file mode 100644 index 0000000..0a4bcdf --- /dev/null +++ b/admin-tools/pyenv-3.6-3.10-versions @@ -0,0 +1,8 @@ +# -*- shell-script -*- +# Sets PYVERSIONS to be pyenv versions that +# we can use in the python-3.6-to-3.10 branch. +if [[ $0 == ${BASH_SOURCE[0]} ]] ; then + echo "This script should be *sourced* rather than run directly through bash" + exit 1 +fi +export PYVERSIONS='3.6 pypy3.6-7.3.1 3.7 pypy3.7-7.3.9 pypy3.8-7.3.11 pypy3.9-7.3.13 3.8 pyston-2.3.5 3.9 3.10' diff --git a/admin-tools/setup-python-3.0.sh b/admin-tools/setup-python-3.0.sh new file mode 100755 index 0000000..89c8789 --- /dev/null +++ b/admin-tools/setup-python-3.0.sh @@ -0,0 +1,10 @@ +#!/bin/bash +if [[ $0 == $${BASH_SOURCE[0]} ]] ; then + echo "This script should be *sourced* rather than run directly through bash" + exit 1 +fi + +PYTHON_VERSION=3.0.1 +pyenv local $PYTHON_VERSION + +git checkout python-3.0-to-3.2 && git pull && pyenv local $PYTHON_VERSION diff --git a/admin-tools/setup-python-3.3.sh b/admin-tools/setup-python-3.3.sh new file mode 100755 index 0000000..a48d3f5 --- /dev/null +++ b/admin-tools/setup-python-3.3.sh @@ -0,0 +1,10 @@ +#!/bin/bash +PYTHON_VERSION=3.3.7 +pyenv local $PYTHON_VERSION + +if [[ $0 == $${BASH_SOURCE[0]} ]] ; then + echo "This script should be *sourced* rather than run directly through bash" + exit 1 +fi + +git checkout python-3.3-to-3.5 && git pull && pyenv local $PYTHON_VERSION diff --git a/admin-tools/setup-python-3.6.sh b/admin-tools/setup-python-3.6.sh new file mode 100755 index 0000000..92781ac --- /dev/null +++ b/admin-tools/setup-python-3.6.sh @@ -0,0 +1,10 @@ +#!/bin/bash +if [[ $0 == $${BASH_SOURCE[0]} ]] ; then + echo "This script should be *sourced* rather than run directly through bash" + exit 1 +fi + +PYTHON_VERSION=3.6 +pyenv local $PYTHON_VERSION + +git checkout python-3.6-to-3.10 && git pull && pyenv local $PYTHON_VERSION From 67492dbbbe1fc6b4b14dd6e03a63322a59d35fcf Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 3 Oct 2024 22:05:32 -0400 Subject: [PATCH 02/40] Adjust example tests for 3.10 vs pre 3.10 --- example/python2/py2_format.py | 19 ++++++++----------- example/python2/py2_parser.py | 9 ++++++--- example/python2/py2_scan.py | 9 ++++++--- example/python2/test/helper.py | 5 ++++- example/python2/test/test_parse.py | 7 ++++++- example/python2/test/test_scan.py | 8 +++++++- 6 files changed, 37 insertions(+), 20 deletions(-) diff --git a/example/python2/py2_format.py b/example/python2/py2_format.py index 35c6ec2..eb1dd85 100644 --- a/example/python2/py2_format.py +++ b/example/python2/py2_format.py @@ -96,22 +96,19 @@ import re import sys +from io import StringIO +from sys import version_info -from example.python2.py2_parser import parse_python2 from spark_parser import GenericASTTraversal # , DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG -PYTHON3 = sys.version_info >= (3, 0) - -if PYTHON3: - from io import StringIO - - minint = -sys.maxsize - 1 - maxint = sys.maxsize +if version_info[:2] < (3, 10): + from py2_parser import parse_python2 else: - from StringIO import StringIO + from example.python2.py2_parser import parse_python2 + - minint = -sys.maxint - 1 - maxint = sys.maxint +minint = -sys.maxsize - 1 +maxint = sys.maxsize TAB = " " * 4 # is less spacy than "\t" INDENT_PER_LEVEL = " " # additional intent per pretty-print level diff --git a/example/python2/py2_parser.py b/example/python2/py2_parser.py index 4753c99..50cdc00 100644 --- a/example/python2/py2_parser.py +++ b/example/python2/py2_parser.py @@ -3,14 +3,17 @@ More complex expression parsing """ -# from __future__ import print_function - import sys +from sys import version_info -from example.python2.py2_scan import ENDMARKER, Python2Scanner from spark_parser import GenericASTBuilder from spark_parser.ast import AST +if version_info[:2] < (3, 10): + from py2_scan import ENDMARKER, Python2Scanner +else: + from example.python2.py2_scan import ENDMARKER, Python2Scanner + DEFAULT_DEBUG = { "rules": False, "transition": False, diff --git a/example/python2/py2_scan.py b/example/python2/py2_scan.py index 5ed1ce2..f36aa0b 100644 --- a/example/python2/py2_scan.py +++ b/example/python2/py2_scan.py @@ -1,13 +1,16 @@ """ Simple SPARK-style scanner -Copyright (c) 2016 Rocky Bernstein +Copyright (c) 2016, 2024 Rocky Bernstein """ import re +from sys import version_info -from example.python2.py2_token import PythonToken +if version_info[:2] < (3, 10): + from py2_token import PythonToken +else: + from example.python2.py2_token import PythonToken -# from __future__ import print_function from spark_parser.scanner import GenericScanner RESERVED_WORDS = re.split( diff --git a/example/python2/test/helper.py b/example/python2/test/helper.py index 4c06a96..b831e47 100644 --- a/example/python2/test/helper.py +++ b/example/python2/test/helper.py @@ -12,7 +12,10 @@ def helper_init(file, subdir): def compare_one(func, python_file, verbose=True): - from example.python2.py2_scan import ENDMARKER + if sys.version_info[:2] < (3, 10): + from py2_scan import ENDMARKER + else: + from example.python2.py2_scan import ENDMARKER right_file = python_file[:-2] + "right" got_file = python_file[:-2] + "got" diff --git a/example/python2/test/test_parse.py b/example/python2/test/test_parse.py index 311ff9c..069a8ca 100755 --- a/example/python2/test/test_parse.py +++ b/example/python2/test/test_parse.py @@ -1,11 +1,16 @@ #!/usr/bin/env python +import sys import unittest from helper import helper_init, run_tests_unit parse_dir = helper_init(__file__, "parse") -from example.python2.py2_parser import parse_python2 + +if sys.version_info[:2] < (3, 11): + from example.python2.py2_parser import parse_python2 +else: + from py2_parser import parse_python2 def run_parse(python2_stmts): diff --git a/example/python2/test/test_scan.py b/example/python2/test/test_scan.py index ed2f517..33d0621 100755 --- a/example/python2/test/test_scan.py +++ b/example/python2/test/test_scan.py @@ -1,11 +1,17 @@ #!/usr/bin/env python import unittest +from sys import version_info from helper import helper_init, run_tests_unit +if version_info[:2] < (3, 10): + from py2_scan import Python2Scanner +else: + from example.python2.py2_scan import Python2Scanner + + scan_dir = helper_init(__file__, "scan") -from example.python2.py2_scan import Python2Scanner def run_scan(python_file): From 830f679d50d2c8f6c59e2466e7adb196b87a5156 Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 3 Oct 2024 22:17:27 -0400 Subject: [PATCH 03/40] Adjust how to run tests on various Python versions --- admin-tools/.gitignore | 1 + admin-tools/check-2.4-2.7-versions.sh | 23 +++++++++++++++++++++++ admin-tools/check-3.3-3.5-versions.sh | 24 ++++++++++++++++++++++++ admin-tools/check-3.6-3.10-versions.sh | 24 ++++++++++++++++++++++++ admin-tools/check-newest-versions.sh | 25 +++++++++++++++++++++++++ admin-tools/pyenv-3.6-3.10-versions | 2 +- admin-tools/pyenv-older-versions | 6 ------ example/__init__.py | 0 example/python2/py2_format.py | 2 +- example/python2/py2_parser.py | 2 +- example/python2/py2_scan.py | 2 +- example/python2/test/__init__.py | 0 example/python2/test/helper.py | 2 +- example/python2/test/test_format.py | 7 ++++++- example/python2/test/test_parse.py | 6 +++--- example/python2/test/test_scan.py | 7 +++---- 16 files changed, 114 insertions(+), 19 deletions(-) create mode 100644 admin-tools/.gitignore create mode 100755 admin-tools/check-2.4-2.7-versions.sh create mode 100755 admin-tools/check-3.3-3.5-versions.sh create mode 100755 admin-tools/check-3.6-3.10-versions.sh create mode 100755 admin-tools/check-newest-versions.sh delete mode 100644 admin-tools/pyenv-older-versions create mode 100644 example/__init__.py create mode 100644 example/python2/test/__init__.py diff --git a/admin-tools/.gitignore b/admin-tools/.gitignore new file mode 100644 index 0000000..183700b --- /dev/null +++ b/admin-tools/.gitignore @@ -0,0 +1 @@ +/.python-version diff --git a/admin-tools/check-2.4-2.7-versions.sh b/admin-tools/check-2.4-2.7-versions.sh new file mode 100755 index 0000000..1125147 --- /dev/null +++ b/admin-tools/check-2.4-2.7-versions.sh @@ -0,0 +1,23 @@ +#!/bin/bash +check_spark_24_owd=$(pwd) + +cd $(dirname ${BASH_SOURCE[0]}) +if ! source ./pyenv-2.4-2.7-versions ; then + exit $? +fi +if ! source ./setup-python-2.4.sh ; then + exit $? +fi + +cd .. +for version in $PYVERSIONS; do + if ! pyenv local $version ; then + exit $? + fi + make clean && python setup.py develop + if ! make check ; then + exit $? + fi + echo === $version === +done +cd $check_spark_24_owd diff --git a/admin-tools/check-3.3-3.5-versions.sh b/admin-tools/check-3.3-3.5-versions.sh new file mode 100755 index 0000000..ec5bd51 --- /dev/null +++ b/admin-tools/check-3.3-3.5-versions.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +check_spark_33_owd=$(pwd) + +cd $(dirname ${BASH_SOURCE[0]}) +if ! source ./pyenv-3.3-3.5-versions ; then + exit $? +fi +if ! source ./setup-python-3.3.sh ; then + exit $? +fi +cd .. +for version in $PYVERSIONS; do + echo --- $version --- + if ! pyenv local $version ; then + exit $? + fi + make clean && pip install -e . + if ! make check; then + exit $? + fi + echo === $version === +done +cd $check_spark_33_owd diff --git a/admin-tools/check-3.6-3.10-versions.sh b/admin-tools/check-3.6-3.10-versions.sh new file mode 100755 index 0000000..3d7115b --- /dev/null +++ b/admin-tools/check-3.6-3.10-versions.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +check_spark_36_owd=$(pwd) + +cd $(dirname ${BASH_SOURCE[0]}) +if ! source ./pyenv-3.6-3.10-versions ; then + exit $? +fi +if ! source ./setup-python-3.6.sh ; then + exit $? +fi +cd .. +for version in $PYVERSIONS; do + echo --- $version --- + if ! pyenv local $version ; then + exit $? + fi + make clean && pip install -e . + if ! make check; then + exit $? + fi + echo === $version === +done +cd $check_spark_36_owd diff --git a/admin-tools/check-newest-versions.sh b/admin-tools/check-newest-versions.sh new file mode 100755 index 0000000..73b3e8e --- /dev/null +++ b/admin-tools/check-newest-versions.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# FIXME put some of the below in a common routine +spark_check_newest_owd=$(pwd) + +cd $(dirname ${BASH_SOURCE[0]}) +if ! source ./pyenv-newest-versions ; then + exit $? +fi +if ! source ./setup-master.sh ; then + exit $? +fi +cd .. +for version in $PYVERSIONS; do + echo --- $version --- + if ! pyenv local $version ; then + exit $? + fi + make clean && pip install -e . + if ! make check; then + exit $? + fi + echo === $version === +done +cd $spark_check_newest_owd diff --git a/admin-tools/pyenv-3.6-3.10-versions b/admin-tools/pyenv-3.6-3.10-versions index 0a4bcdf..236aa96 100644 --- a/admin-tools/pyenv-3.6-3.10-versions +++ b/admin-tools/pyenv-3.6-3.10-versions @@ -5,4 +5,4 @@ if [[ $0 == ${BASH_SOURCE[0]} ]] ; then echo "This script should be *sourced* rather than run directly through bash" exit 1 fi -export PYVERSIONS='3.6 pypy3.6-7.3.1 3.7 pypy3.7-7.3.9 pypy3.8-7.3.11 pypy3.9-7.3.13 3.8 pyston-2.3.5 3.9 3.10' +export PYVERSIONS='3.6 3.7 3.8 pyston-2.3.5 3.9 3.10' diff --git a/admin-tools/pyenv-older-versions b/admin-tools/pyenv-older-versions deleted file mode 100644 index 63e4e20..0000000 --- a/admin-tools/pyenv-older-versions +++ /dev/null @@ -1,6 +0,0 @@ -# -*- shell-script -*- -if [[ $0 == ${BASH_SOURCE[0]} ]] ; then - echo "This script should be *sourced* rather than run directly through bash" - exit 1 -fi -export PYVERSIONS='2.4.6 2.5.6' diff --git a/example/__init__.py b/example/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/example/python2/py2_format.py b/example/python2/py2_format.py index eb1dd85..41b343b 100644 --- a/example/python2/py2_format.py +++ b/example/python2/py2_format.py @@ -101,7 +101,7 @@ from spark_parser import GenericASTTraversal # , DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG -if version_info[:2] < (3, 10): +if version_info[:2] < (3, 9): from py2_parser import parse_python2 else: from example.python2.py2_parser import parse_python2 diff --git a/example/python2/py2_parser.py b/example/python2/py2_parser.py index 50cdc00..856e625 100644 --- a/example/python2/py2_parser.py +++ b/example/python2/py2_parser.py @@ -9,7 +9,7 @@ from spark_parser import GenericASTBuilder from spark_parser.ast import AST -if version_info[:2] < (3, 10): +if version_info[:2] < (3, 9): from py2_scan import ENDMARKER, Python2Scanner else: from example.python2.py2_scan import ENDMARKER, Python2Scanner diff --git a/example/python2/py2_scan.py b/example/python2/py2_scan.py index f36aa0b..0fac7c5 100644 --- a/example/python2/py2_scan.py +++ b/example/python2/py2_scan.py @@ -6,7 +6,7 @@ import re from sys import version_info -if version_info[:2] < (3, 10): +if version_info[:2] < (3, 9): from py2_token import PythonToken else: from example.python2.py2_token import PythonToken diff --git a/example/python2/test/__init__.py b/example/python2/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/example/python2/test/helper.py b/example/python2/test/helper.py index b831e47..90e0ad6 100644 --- a/example/python2/test/helper.py +++ b/example/python2/test/helper.py @@ -12,7 +12,7 @@ def helper_init(file, subdir): def compare_one(func, python_file, verbose=True): - if sys.version_info[:2] < (3, 10): + if sys.version_info[:2] < (3, 9): from py2_scan import ENDMARKER else: from example.python2.py2_scan import ENDMARKER diff --git a/example/python2/test/test_format.py b/example/python2/test/test_format.py index bd2a0a0..947f242 100755 --- a/example/python2/test/test_format.py +++ b/example/python2/test/test_format.py @@ -1,11 +1,16 @@ #!/usr/bin/env python +import sys import unittest from helper import helper_init, run_tests_unit format_dir = helper_init(__file__, "format") -from example.python2.py2_format import format_python2_stmts + +if sys.version_info[:2] < (3, 9): + from py2_format import format_python2_stmts +else: + from example.python2.py2_format import format_python2_stmts def run_format(python2_stmts): diff --git a/example/python2/test/test_parse.py b/example/python2/test/test_parse.py index 069a8ca..225532f 100755 --- a/example/python2/test/test_parse.py +++ b/example/python2/test/test_parse.py @@ -7,10 +7,10 @@ parse_dir = helper_init(__file__, "parse") -if sys.version_info[:2] < (3, 11): - from example.python2.py2_parser import parse_python2 -else: +if sys.version_info[:2] < (3, 9): from py2_parser import parse_python2 +else: + from example.python2.py2_parser import parse_python2 def run_parse(python2_stmts): diff --git a/example/python2/test/test_scan.py b/example/python2/test/test_scan.py index 33d0621..510a6e6 100755 --- a/example/python2/test/test_scan.py +++ b/example/python2/test/test_scan.py @@ -5,15 +5,14 @@ from helper import helper_init, run_tests_unit -if version_info[:2] < (3, 10): +scan_dir = helper_init(__file__, "scan") + +if version_info[:2] < (3, 9): from py2_scan import Python2Scanner else: from example.python2.py2_scan import Python2Scanner -scan_dir = helper_init(__file__, "scan") - - def run_scan(python_file): # Note: need to initialize scanner each time. return Python2Scanner().tokenize(python_file) From a91e2c1aef79635ed68b01bb715edded497f1b0c Mon Sep 17 00:00:00 2001 From: rocky Date: Fri, 4 Oct 2024 21:02:20 -0400 Subject: [PATCH 04/40] More ignore --- admin-tools/.gitignore | 4 ---- 1 file changed, 4 deletions(-) diff --git a/admin-tools/.gitignore b/admin-tools/.gitignore index 81b49c8..183700b 100644 --- a/admin-tools/.gitignore +++ b/admin-tools/.gitignore @@ -1,5 +1 @@ /.python-version -<<<<<<< HEAD -======= -/.python-version ->>>>>>> master From bda77cc9964fe278410be94f5a1b22576d4b9c60 Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 7 Oct 2024 13:01:32 -0400 Subject: [PATCH 05/40] Merge hell --- Makefile | 2 +- pyproject.toml | 66 ------------- setup.py | 98 ++++++++++++++++++- spark_parser/example/python2/py2_format.py | 6 +- spark_parser/example/python2/py2_parser.py | 5 +- spark_parser/example/python2/py2_scan.py | 6 +- spark_parser/example/python2/test/helper.py | 2 +- .../example/python2/test/test_format.py | 2 +- .../example/python2/test/test_parse.py | 2 +- .../example/python2/test/test_scan.py | 2 +- 10 files changed, 104 insertions(+), 87 deletions(-) delete mode 100644 pyproject.toml diff --git a/Makefile b/Makefile index 402ba0b..8694de4 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ all: check #: Run all tests with several Python versions via tox check-full: check flake8 spark_parser && flake8 test \ - && flake8 example \ + && flake8 spark_parser/example \ --exclude spark_parser/example/python2/test \ #: Run tests (one version of Python) diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 4f10bb8..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,66 +0,0 @@ -[build-system] -requires = [ - "setuptools>=61.2", -] -[project] -name = "spark-parser" -authors = [ - {name = "John Aycock"}, - {name = "Rocky Bernstein", email="rocky@gnu.org"} -] - -description = "An Earley-Algorithm Context-free grammar Parser Toolkit" -dependencies = [ - "click", -] -readme = "README.rst" -license = {text = "GPL"} -maintainers = [ - {name = "Rocky Bernstein"}, -] -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python", - "Topic :: Software Development :: Libraries :: Python Modules", - "Programming Language :: Python :: 2.4", - "Programming Language :: Python :: 2.5", - "Programming Language :: Python :: 2.6", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3.0", - "Programming Language :: Python :: 3.1", - "Programming Language :: Python :: 3.2", - "Programming Language :: Python :: 3.3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", -] -dynamic = ["version"] - -[project.urls] -Homepage = "https://github.com/rocky/python-spark" - -[project.optional-dependencies] -dev = [ - "pytest", - "pre-commit", -] - -[tool.setuptools] -packages = [ - "spark_parser", -] - -py-modules = [ - "example", -] - -[tool.setuptools.dynamic] -version = {attr = "spark_parser.version.__version__"} diff --git a/setup.py b/setup.py index c5f365f..f06d617 100755 --- a/setup.py +++ b/setup.py @@ -14,6 +14,100 @@ Copyright (C) 2016, 2022, 2024 Rocky Bernstein . """ -from setuptools import setup +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 2.4", + "Programming Language :: Python :: 2.5", + "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.0", + "Programming Language :: Python :: 3.1", + "Programming Language :: Python :: 3.2", + "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Software Development :: Code Generators", + "Topic :: Software Development :: Libraries :: Python Modules", +] -setup() +# The rest in alphabetic order +author = "John Aycock" +ftp_url = None +license = "MIT" +maintainer = "Rocky Bernstein" +maintainer_email = "rb@dustyfeet.com" +modname = "spark_parser" +name = "spark_parser" +py_modules = ["example",] + +None +short_desc = "An Earley-Algorithm Context-free grammar Parser Toolkit" +web = "https://github.com/rocky/python-spark/" + +# tracebacks in zip files are funky and not debuggable +zip_safe = True + +# Python-version | package | last-version | +# ----------------------------------------- +# 3.2 | click | 4.0 | +# 3.2 | pip | 8.1.2 | +# 3.3 | pip | 10.0.1 | +# 3.4 | pip | 19.1.1 | + +import os.path as osp + + +def get_srcdir(): + filename = osp.normcase(osp.dirname(osp.abspath(__file__))) + return osp.realpath(filename) + + +srcdir = get_srcdir() + + +def read(*rnames): + return open(osp.join(srcdir, *rnames)).read() + + +# Get info from files; set: long_description and VERSION +long_description = read("README.rst") + "\n" +exec(read("spark_parser/version.py")) + +import sys + +if (3, 0) <= sys.version_info[:2] <= (3, 2): + click_version = "<= 4.0" +else: + click_version = "" + +from setuptools import find_packages, setup + +setup( + classifiers=classifiers, + description=short_desc, + install_requires=["click%s" % click_version], + license=license, + long_description=long_description, + long_description_content_type="text/x-rst", + maintainer=maintainer, + maintainer_email=maintainer_email, + packages=find_packages(), + py_modules=py_modules, + name=name, + scripts=["bin/spark-parser-coverage"], + test_suite="nose.collector", + url=web, + tests_require=["nose>=1.0"], + version=__version__, + zip_safe=zip_safe, +) diff --git a/spark_parser/example/python2/py2_format.py b/spark_parser/example/python2/py2_format.py index 7b5d395..fa2368c 100644 --- a/spark_parser/example/python2/py2_format.py +++ b/spark_parser/example/python2/py2_format.py @@ -99,16 +99,12 @@ from io import StringIO from sys import version_info -<<<<<<< HEAD:example/python2/py2_format.py -======= -from spark_parser.example.python2.py2_parser import parse_python2 ->>>>>>> master:spark_parser/example/python2/py2_format.py from spark_parser import GenericASTTraversal # , DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG if version_info[:2] < (3, 9): from py2_parser import parse_python2 else: - from example.python2.py2_parser import parse_python2 + from spark_parser.example.python2.py2_parser import parse_python2 minint = -sys.maxsize - 1 diff --git a/spark_parser/example/python2/py2_parser.py b/spark_parser/example/python2/py2_parser.py index 8b3ec8c..105541e 100644 --- a/spark_parser/example/python2/py2_parser.py +++ b/spark_parser/example/python2/py2_parser.py @@ -6,17 +6,14 @@ import sys from sys import version_info -<<<<<<< HEAD:example/python2/py2_parser.py -======= from spark_parser.example.python2.py2_scan import ENDMARKER, Python2Scanner ->>>>>>> master:spark_parser/example/python2/py2_parser.py from spark_parser import GenericASTBuilder from spark_parser.ast import AST if version_info[:2] < (3, 9): from py2_scan import ENDMARKER, Python2Scanner else: - from example.python2.py2_scan import ENDMARKER, Python2Scanner + from spark_parser.example.python2.py2_scan import ENDMARKER, Python2Scanner DEFAULT_DEBUG = { "rules": False, diff --git a/spark_parser/example/python2/py2_scan.py b/spark_parser/example/python2/py2_scan.py index 96b5145..b6ea0be 100644 --- a/spark_parser/example/python2/py2_scan.py +++ b/spark_parser/example/python2/py2_scan.py @@ -6,14 +6,10 @@ import re from sys import version_info -<<<<<<< HEAD:example/python2/py2_scan.py if version_info[:2] < (3, 9): from py2_token import PythonToken else: - from example.python2.py2_token import PythonToken -======= -from spark_parser.example.python2.py2_token import PythonToken ->>>>>>> master:spark_parser/example/python2/py2_scan.py + from spark_parser.example.python2.py2_token import PythonToken from spark_parser.scanner import GenericScanner diff --git a/spark_parser/example/python2/test/helper.py b/spark_parser/example/python2/test/helper.py index 90e0ad6..20f03cf 100644 --- a/spark_parser/example/python2/test/helper.py +++ b/spark_parser/example/python2/test/helper.py @@ -15,7 +15,7 @@ def compare_one(func, python_file, verbose=True): if sys.version_info[:2] < (3, 9): from py2_scan import ENDMARKER else: - from example.python2.py2_scan import ENDMARKER + from spark_parser.example.python2.py2_scan import ENDMARKER right_file = python_file[:-2] + "right" got_file = python_file[:-2] + "got" diff --git a/spark_parser/example/python2/test/test_format.py b/spark_parser/example/python2/test/test_format.py index 947f242..eeb6649 100755 --- a/spark_parser/example/python2/test/test_format.py +++ b/spark_parser/example/python2/test/test_format.py @@ -10,7 +10,7 @@ if sys.version_info[:2] < (3, 9): from py2_format import format_python2_stmts else: - from example.python2.py2_format import format_python2_stmts + from spark_parser.example.python2.py2_format import format_python2_stmts def run_format(python2_stmts): diff --git a/spark_parser/example/python2/test/test_parse.py b/spark_parser/example/python2/test/test_parse.py index 225532f..3a5ea31 100755 --- a/spark_parser/example/python2/test/test_parse.py +++ b/spark_parser/example/python2/test/test_parse.py @@ -10,7 +10,7 @@ if sys.version_info[:2] < (3, 9): from py2_parser import parse_python2 else: - from example.python2.py2_parser import parse_python2 + from spark_parser.example.python2.py2_parser import parse_python2 def run_parse(python2_stmts): diff --git a/spark_parser/example/python2/test/test_scan.py b/spark_parser/example/python2/test/test_scan.py index 510a6e6..11f86e2 100755 --- a/spark_parser/example/python2/test/test_scan.py +++ b/spark_parser/example/python2/test/test_scan.py @@ -10,7 +10,7 @@ if version_info[:2] < (3, 9): from py2_scan import Python2Scanner else: - from example.python2.py2_scan import Python2Scanner + from spark_parser.example.python2.py2_scan import Python2Scanner def run_scan(python_file): From 9625778025caed6192b917a5fa85b1cae97a389f Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 21 Nov 2016 17:43:10 -0500 Subject: [PATCH 06/40] Try Python 2.4 --- .travis.yml | 18 ------------------ README.rst | 4 +--- README2.rst | 4 ++-- spark_parser/ast.py | 2 +- spark_parser/example/python2/py2_scan.py | 7 +++++-- spark_parser/spark.py | 9 ++++++--- 6 files changed, 15 insertions(+), 29 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8cc5332..0000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: python - -sudo: false - -python: -# - '2.6' - - '3.8' - - '2.7' - - '3.7' - - '3.6' - - '3.5' - - '3.4' - - 'pypy' - - 'pypy3' -# - '3.3' - -script: -- python ./setup.py develop && make check diff --git a/README.rst b/README.rst index 1c3621d..e4288ac 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -|buildstatus| |Pypi Installs| |Latest Version| |Supported Python Versions| +|Supported Python Versions| |packagestatus| @@ -51,8 +51,6 @@ See Also .. _directory: https://github.com/rocky/python-spark/tree/master/example .. _uncompyle6: https://pypi.python.org/pypi/uncompyle6/ .. |downloads| image:: https://img.shields.io/pypi/dd/spark.svg -.. |buildstatus| image:: https://travis-ci.org/rocky/python-spark.svg - :target: https://travis-ci.org/rocky/python-spark .. |Supported Python Versions| image:: https://img.shields.io/pypi/pyversions/spark_parser.svg .. |Latest Version| image:: https://badge.fury.io/py/spark-parser.svg :target: https://badge.fury.io/py/spark-parser diff --git a/README2.rst b/README2.rst index 6ad9831..b54bdf3 100644 --- a/README2.rst +++ b/README2.rst @@ -1,2 +1,2 @@ -The Python 2.3 branch of python-spark is specifically for older Pythons, -namely versions 2.3 - 2.5. +This branch of python-spark is specifically for older Pythons, +namely 2.4 2.5, 2.6 and 2.7. diff --git a/spark_parser/ast.py b/spark_parser/ast.py index 36efdd4..fa74e51 100644 --- a/spark_parser/ast.py +++ b/spark_parser/ast.py @@ -62,7 +62,7 @@ def __repr1__(self, indent, sibNum=None): i += 1 return rv -class GenericASTTraversalPruningException(BaseException): +class GenericASTTraversalPruningException: pass class GenericASTTraversal: diff --git a/spark_parser/example/python2/py2_scan.py b/spark_parser/example/python2/py2_scan.py index efee21b..58b0bf9 100644 --- a/spark_parser/example/python2/py2_scan.py +++ b/spark_parser/example/python2/py2_scan.py @@ -149,8 +149,11 @@ def t_name(self, s): # We can't have two separate defs because then it would be indeterminate # whether we get two single stars or one double star. def t_star_star(self, s): - r"\*\*?" - token_name = "STARSTAR" if len(s) == 2 else "STAR" + r'\*\*?' + if len(s) == 2: + token_name = "STARSTAR" + else: + token_name = 'STAR' self.add_token(token_name, s) # CONSTANTS diff --git a/spark_parser/spark.py b/spark_parser/spark.py index e0fd51c..9778674 100644 --- a/spark_parser/spark.py +++ b/spark_parser/spark.py @@ -430,9 +430,12 @@ def duplicate_rule(self, rule): def error(self, tokens, index): print("Syntax error at or near token %d: `%s'" % (index, tokens[index])) - if "context" in self.debug and self.debug["context"]: - start = index - 2 if index - 2 >= 0 else 0 - tokens = [str(tokens[i]) for i in range(start, index + 1)] + if 'context' in self.debug and self.debug['context']: + if index - 2 >= 0: + start = index - 2 + else: + start = 0 + tokens = [str(tokens[i]) for i in range(start, index+1)] print("Token context:\n\t%s" % ("\n\t".join(tokens))) raise SystemExit From 27e3ed661b05382736b13292ab142fa4d8a040ed Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 23 Nov 2016 09:51:10 -0500 Subject: [PATCH 07/40] Make it work with Python 2.3 --- Makefile | 3 +-- spark_parser/example/python2/py2_format.py | 18 +++++------------- spark_parser/example/python2/py2_parser.py | 2 +- spark_parser/example/python2/py2_scan.py | 4 ++-- spark_parser/example/python2/test/helper.py | 9 ++++++--- .../example/python2/test/test_format.py | 2 +- .../example/python2/test/test_parse.py | 2 +- spark_parser/example/python2/test/test_scan.py | 2 +- spark_parser/spark.py | 8 ++++---- test/test_checker.py | 5 ++++- test/test_grammar.py | 2 +- test/test_misc.py | 2 +- 12 files changed, 28 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index 402ba0b..915cc54 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,6 @@ PHONY=check check-full clean dist distclean test GIT2CL ?= git2cl PYTHON ?= python -PYTHON3 ?= python3 PYTEST_OPTIONS ?= #: the default target - same as running "check" @@ -21,7 +20,7 @@ check-full: check #: Run tests (one version of Python) check: - $(PYTHON3) -m pytest $(PYTEST_OPTIONS) test + $(PYTHON) -m pytest $(PYTEST_OPTIONS) test $(MAKE) -C spark_parser/example/python2 check # $(MAKE) -C spark_parser/example/gdb-loc check diff --git a/spark_parser/example/python2/py2_format.py b/spark_parser/example/python2/py2_format.py index ced2255..ad03cb3 100644 --- a/spark_parser/example/python2/py2_format.py +++ b/spark_parser/example/python2/py2_format.py @@ -1,4 +1,4 @@ -# Copyright (c) 2016-2017 by Rocky Bernstein +# Copyright (c) 2016-2017, 2024 by Rocky Bernstein # Based on decompyle.py # Copyright (c) 1999 John Aycock @@ -97,21 +97,13 @@ import re import sys -from spark_parser.example.python2.py2_parser import parse_python2 +from py2_parser import parse_python2 from spark_parser import GenericASTTraversal # , DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG -PYTHON3 = sys.version_info >= (3, 0) +from StringIO import StringIO -if PYTHON3: - from io import StringIO - - minint = -sys.maxsize - 1 - maxint = sys.maxsize -else: - from StringIO import StringIO - - minint = -sys.maxint - 1 - maxint = sys.maxint +minint = -sys.maxint - 1 +maxint = sys.maxint TAB = " " * 4 # is less spacy than "\t" INDENT_PER_LEVEL = " " # additional intent per pretty-print level diff --git a/spark_parser/example/python2/py2_parser.py b/spark_parser/example/python2/py2_parser.py index 5a832ee..efddc7a 100644 --- a/spark_parser/example/python2/py2_parser.py +++ b/spark_parser/example/python2/py2_parser.py @@ -7,7 +7,7 @@ import sys -from spark_parser.example.python2.py2_scan import ENDMARKER, Python2Scanner +from py2_scan import ENDMARKER, Python2Scanner from spark_parser import GenericASTBuilder from spark_parser.ast import AST diff --git a/spark_parser/example/python2/py2_scan.py b/spark_parser/example/python2/py2_scan.py index 58b0bf9..5cf5ba6 100644 --- a/spark_parser/example/python2/py2_scan.py +++ b/spark_parser/example/python2/py2_scan.py @@ -1,11 +1,11 @@ """ Simple SPARK-style scanner -Copyright (c) 2016 Rocky Bernstein +Copyright (c) 2016 2024 Rocky Bernstein """ import re -from spark_parser.example.python2.py2_token import PythonToken +from py2_token import PythonToken # from __future__ import print_function from spark_parser.scanner import GenericScanner diff --git a/spark_parser/example/python2/test/helper.py b/spark_parser/example/python2/test/helper.py index 64a4fb2..580194b 100644 --- a/spark_parser/example/python2/test/helper.py +++ b/spark_parser/example/python2/test/helper.py @@ -2,7 +2,6 @@ import os import sys - def helper_init(file, subdir): # I hate how clumsy Python is here dirname = os.path.join(".", os.path.dirname(file)) @@ -12,7 +11,7 @@ def helper_init(file, subdir): def compare_one(func, python_file, verbose=True): - from spark_parser.example.python2.py2_scan import ENDMARKER + from py2_scan import ENDMARKER right_file = python_file[:-2] + "right" got_file = python_file[:-2] + "got" @@ -64,7 +63,11 @@ def run_tests_unit(cls, func, test_dir, match_files=None, verbose=False): if python_file.endswith(".py"): print(python_file) if not match_files or python_file in match_files: - cls.assertTrue(compare_one(func, python_file, verbose), python_file) + if sys.version[0:3] <= '2.3': + assert compare_one(func, python_file, verbose), python_file + else: + cls.assertTrue(compare_one(func, python_file, verbose), + python_file) pass pass pass diff --git a/spark_parser/example/python2/test/test_format.py b/spark_parser/example/python2/test/test_format.py index f40a42d..45832ad 100755 --- a/spark_parser/example/python2/test/test_format.py +++ b/spark_parser/example/python2/test/test_format.py @@ -5,7 +5,7 @@ from helper import helper_init, run_tests_unit format_dir = helper_init(__file__, "format") -from spark_parser.example.python2.py2_format import format_python2_stmts +from py2_format import format_python2_stmts def run_format(python2_stmts): diff --git a/spark_parser/example/python2/test/test_parse.py b/spark_parser/example/python2/test/test_parse.py index 71d2896..3b06758 100755 --- a/spark_parser/example/python2/test/test_parse.py +++ b/spark_parser/example/python2/test/test_parse.py @@ -5,7 +5,7 @@ from helper import helper_init, run_tests_unit parse_dir = helper_init(__file__, "parse") -from spark_parser.example.python2.py2_parser import parse_python2 +from py2_parser import parse_python2 def run_parse(python2_stmts): diff --git a/spark_parser/example/python2/test/test_scan.py b/spark_parser/example/python2/test/test_scan.py index 63b54f6..a78df0b 100755 --- a/spark_parser/example/python2/test/test_scan.py +++ b/spark_parser/example/python2/test/test_scan.py @@ -5,7 +5,7 @@ from helper import helper_init, run_tests_unit scan_dir = helper_init(__file__, "scan") -from spark_parser.example.python2.py2_scan import Python2Scanner +from py2_scan import Python2Scanner def run_scan(python_file): diff --git a/spark_parser/spark.py b/spark_parser/spark.py index 9778674..17bee6f 100644 --- a/spark_parser/spark.py +++ b/spark_parser/spark.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2015-2017, 2020, 2023 Rocky Bernstein +Copyright (c) 2015-2017, 2020, 2023-2024 Rocky Bernstein Copyright (c) 1998-2002 John Aycock Permission is hereby granted, free of charge, to any person obtaining @@ -35,7 +35,6 @@ def sorted(iterable): temp.sort() return temp - def _namelist(instance): namelist, namedict, classlist = [], {}, [instance.__class__] for c in classlist: @@ -257,8 +256,9 @@ def addRule(self, doc, func, _preprocess=True): if lhs in self.rules: if rule in self.rules[lhs]: - if "dups" in self.debug and self.debug["dups"]: - self.duplicate_rule(rule) + if 'dups' in self.debug and self.debug['dups']: + print("Duplicate rule:\n\t%s ::= %s" % + (rule[0], ' '.join(rule[1]))) continue self.rules[lhs].append(rule) else: diff --git a/test/test_checker.py b/test/test_checker.py index d7228b8..ea268fc 100755 --- a/test/test_checker.py +++ b/test/test_checker.py @@ -2,9 +2,12 @@ """ SPARK unit unit test grammar checking """ -import unittest +import unittest, sys from spark_parser.spark import GenericParser +if sys.version[0:3] <= '2.3': + from sets import Set as set + class RightRecursive(GenericParser): """A simple expression parser for numbers and arithmetic operators: +, , *, and /. diff --git a/test/test_grammar.py b/test/test_grammar.py index 56d72c2..d97f3c2 100644 --- a/test/test_grammar.py +++ b/test/test_grammar.py @@ -1,7 +1,7 @@ import unittest from spark_parser import GenericParser -from io import StringIO +from StringIO import StringIO class BadExpr(GenericParser): """Testing grammar_checking""" diff --git a/test/test_misc.py b/test/test_misc.py index 79b383b..7292ebb 100644 --- a/test/test_misc.py +++ b/test/test_misc.py @@ -1,7 +1,7 @@ import unittest from spark_parser.spark import GenericParser -from io import StringIO +from StringIO import StringIO class Rules(GenericParser): """Testing duplicate rules""" From c95c8c30ee3ecb8378c5e81c3cc596baa09d0748 Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 23 Nov 2016 10:00:25 -0500 Subject: [PATCH 08/40] Get ready for release 1.9.0 Do some linting too --- README2.rst | 2 +- setup.py | 17 ++++++++++++++++- spark_parser/example/python2/py2_scan.py | 9 +++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/README2.rst b/README2.rst index b54bdf3..9fd094c 100644 --- a/README2.rst +++ b/README2.rst @@ -1,2 +1,2 @@ This branch of python-spark is specifically for older Pythons, -namely 2.4 2.5, 2.6 and 2.7. +namely versions 2.3 through 2.7 diff --git a/setup.py b/setup.py index c5f365f..f4b82e7 100755 --- a/setup.py +++ b/setup.py @@ -15,5 +15,20 @@ """ from setuptools import setup - +classifiers = ['Development Status :: 4 - Beta', + 'Intended Audience :: Developers', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2.3', + 'Programming Language :: Python :: 2.4', + 'Programming Language :: Python :: 2.5', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Topic :: Software Development :: Code Generators', + 'Topic :: Software Development :: Compilers ', + 'Topic :: Software Development :: Libraries :: Python Modules', + ] setup() diff --git a/spark_parser/example/python2/py2_scan.py b/spark_parser/example/python2/py2_scan.py index 5cf5ba6..04106b2 100644 --- a/spark_parser/example/python2/py2_scan.py +++ b/spark_parser/example/python2/py2_scan.py @@ -130,12 +130,21 @@ def t_op(self, s): raise SystemExit def t_linesep(self, s): +<<<<<<< HEAD:spark_parser/example/python2/py2_scan.py r";" self.add_token("SEMICOLON", s) def t_nl(self, s): r"\n" self.add_token("NEWLINE", s, is_newline=True) +======= + r';' + self.add_token('SEMICOLON', s) + + def t_nl(self, s): + r'\n' + self.add_token('NEWLINE', s, is_newline=True) +>>>>>>> 19c6fc4 (Get ready for release 1.4.3):example/python2/py2_scan.py def t_name(self, s): r"[A-Za-z_][A-Za-z_0-9]*" From a11c0f335ea6fa11c6f0d88e86a6aed2c04e4e8e Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 29 Jan 2017 23:39:44 -0500 Subject: [PATCH 09/40] Add grammar coverage code --- spark_parser/example/python2/py2_scan.py | 9 -------- spark_parser/spark.py | 28 +++++++++++++++--------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/spark_parser/example/python2/py2_scan.py b/spark_parser/example/python2/py2_scan.py index 04106b2..5cf5ba6 100644 --- a/spark_parser/example/python2/py2_scan.py +++ b/spark_parser/example/python2/py2_scan.py @@ -130,21 +130,12 @@ def t_op(self, s): raise SystemExit def t_linesep(self, s): -<<<<<<< HEAD:spark_parser/example/python2/py2_scan.py r";" self.add_token("SEMICOLON", s) def t_nl(self, s): r"\n" self.add_token("NEWLINE", s, is_newline=True) -======= - r';' - self.add_token('SEMICOLON', s) - - def t_nl(self, s): - r'\n' - self.add_token('NEWLINE', s, is_newline=True) ->>>>>>> 19c6fc4 (Get ready for release 1.4.3):example/python2/py2_scan.py def t_name(self, s): r"[A-Za-z_][A-Za-z_0-9]*" diff --git a/spark_parser/spark.py b/spark_parser/spark.py index 17bee6f..1b42562 100644 --- a/spark_parser/spark.py +++ b/spark_parser/spark.py @@ -439,7 +439,7 @@ def error(self, tokens, index): print("Token context:\n\t%s" % ("\n\t".join(tokens))) raise SystemExit - def errorstack(self, tokens, i: int, full=False): + def errorstack(self, tokens, i, full=False): """Show the stacks of completed symbols. We get this by inspecting the current transitions possible and from that extracting the set of states @@ -522,7 +522,8 @@ def parse(self, tokens, debug=None): if self.profile_info is not None: self.dump_profile_info() - return self.buildTree(self._START, finalitem, tokens, len(sets) - 2) + return self.buildTree(self._START, finalitem, + tokens, len(sets)-2) def isnullable(self, sym): # For symbols in G_e only. @@ -837,7 +838,10 @@ def buildTree(self, nt, item, tokens, k): # Find applicable rules if not already given if rule is None: choices = [rule for rule in self.states[state].complete if rule[0] == nt] - rule = choices[0] if len(choices) == 1 else self.ambiguity(choices) + if len(choices) == 1: + rule = choices[0] + else: + rule = self.ambiguity(choices) rhs = rule[1] # Process symbols in reverse order, skipping over those already completed @@ -893,7 +897,7 @@ def ambiguity(self, rules): list = [a_b[1] for a_b in sortlist] return rules[name2index[self.resolve(list)]] - def resolve(self, rule: list): + def resolve(self, rule): """ Resolve ambiguity in favor of the shortest RHS. Since we walk the tree from the top down, this @@ -1010,13 +1014,16 @@ def profile_rule(self, rule): def get_profile_info(self): """Show the accumulated results of how many times each rule was used""" - return sorted(self.profile_info.items(), key=lambda kv: kv[1], reverse=False) + return sorted(self.profile_info.items(), + key=lambda kv: kv[1], + reverse=False) return def dump_profile_info(self): if isinstance(self.coverage_path, str): - with open(self.coverage_path, "wb") as fp: - pickle.dump(self.profile_info, fp) + fp = open(self.coverage_path, 'wb') + pickle.dump(self.profile_info, fp) + fp.close() else: for rule, count in self.get_profile_info(): self.coverage_path.write("%s -- %d\n" % (rule, count)) @@ -1057,11 +1064,12 @@ def reduce_ast(self, rule, tokens, item, k, sets): class GenericASTBuilder(GenericParser): def __init__(self, AST, start, debug=DEFAULT_DEBUG): - if "SPARK_PARSER_COVERAGE" in os.environ: - coverage_path = os.environ["SPARK_PARSER_COVERAGE"] + if 'SPARK_PARSER_COVERAGE' in os.environ: + coverage_path = os.environ['SPARK_PARSER_COVERAGE'] else: coverage_path = None - GenericParser.__init__(self, start, debug=debug, coverage_path=coverage_path) + GenericParser.__init__(self, start, debug=debug, + coverage_path=coverage_path) self.AST = AST def preprocess(self, rule, func): From 32da74b107703d67718ddfe187142cae9232834d Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 29 Jan 2017 23:46:41 -0500 Subject: [PATCH 10/40] Add spark-parser-coverage CLI program --- bin/spark-parser-coverage | 77 +++++++++++++++++++-------------------- setup.py | 52 ++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 43 deletions(-) diff --git a/bin/spark-parser-coverage b/bin/spark-parser-coverage index 120c60e..20ebb75 100755 --- a/bin/spark-parser-coverage +++ b/bin/spark-parser-coverage @@ -14,58 +14,55 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from __future__ import print_function -import click -import os -import pickle from spark_parser.version import __version__ +import getopt, os, sys +import pickle def sort_profile_info(path, max_count=1000): - profile_info = pickle.load(open(path, "rb")) + items = sorted(profile_info.items(), + key=lambda kv: kv[1], + reverse=False) + return [item for item in items if item[1] <= max_count] - # Classify unused rules. Some are "unused" because the have nullable - # nonterminals and those show up as a different rule. Sothe rule - # *is* used just not in the form where a nullable symbol hasn't been - # nulled. +program, ext = os.path.splitext(os.path.basename(__file__)) - # And in some cases this is intentional. Uncompyle6 creates such grammar - # rules to ensure that positions of certain nonterminals in semantic - # actions appear in the same place as similar grammar rules +DEFAULT_COVERAGE_FILE = "/tmp/spark-grammar.cover", +DEFAULT_COUNT = 100 +def run(): + Usage_short = """usage: %s --path coverage-file... +Type -h for for full help.""" % program - unused_rules = set() # just the grammar rules - used_rules = [] # (count, grammar rule) - for rule, count in profile_info.items(): - if count == 0: - unused_rules.add(rule) - else: - used_rules.append((count, rule)) - for count, rule in used_rules: - if rule.find("\\e_") > -1: - canonic_rule = rule.replace("\\e_", "", 1000) - if canonic_rule in unused_rules: - unused_rules.remove(canonic_rule) - pass - pass - pass + try: + opts, files = getopt.getopt(sys.argv[1:], 'hVp:m:', + ['help', 'version', 'path=', 'max-count=']) + except getopt.GetoptError(e): + sys.stderr.write('%s: %s\n' % (os.path.basename(sys.argv[0]), e)) + sys.exit(-1) + + max_count = DEFAULT_COUNT + path = DEFAULT_COVERAGE_FILE + for opt, val in opts: + if opt in ('-h', '--help'): + print(__doc__) + sys.exit(1) + elif opt in ('-V', '--version'): + print("%s %s" % (program, __version__)) + sys.exit(0) + elif opt in ('-p', '--path'): + path = val + elif opt in ('-m', '--max_count'): + max_count = int(val) + else: + print(opt) + sys.stderr.write(Usage_short) + sys.exit(1) - unused_items = [(0, item) for item in sorted(unused_rules)] - used_items = sorted(used_rules, reverse=False) - return [item for item in unused_items + used_items - if item[0] <= max_count] -DEFAULT_COVERAGE_FILE =os.environ.get("SPARK_PARSER_COVERAGE", "/tmp/spark-grammar.cover") -DEFAULT_COUNT = 100 -@click.command() -@click.version_option(version=__version__) -@click.option('--max-count', type=int, default=DEFAULT_COUNT, - help=(f"limit output to rules having no more than this many hits (default {DEFAULT_COUNT})")) -@click.argument('path', type=click.Path(), default=DEFAULT_COVERAGE_FILE) -def run(max_count, path: str): """Print grammar reduce statistics for a series of spark-parser parses """ - for count, rule in sort_profile_info(path, max_count): + for rule, count in sort_profile_info(path, max_count): print("%d: %s" % (count, rule)) pass return diff --git a/setup.py b/setup.py index f4b82e7..9f83bc3 100755 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ # Things that change more often go here. copyright = """ -Copyright (C) 2016, 2022, 2024 Rocky Bernstein . +Copyright (C) 2016-2017, 2022, 2024 Rocky Bernstein . """ from setuptools import setup @@ -19,7 +19,6 @@ 'Intended Audience :: Developers', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 2.3', 'Programming Language :: Python :: 2.4', 'Programming Language :: Python :: 2.5', 'Programming Language :: Python :: 2.6', @@ -27,8 +26,55 @@ 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Topic :: Software Development :: Code Generators', 'Topic :: Software Development :: Compilers ', 'Topic :: Software Development :: Libraries :: Python Modules', ] -setup() +# The rest in alphabetic order +author = "John Aycock" +ftp_url = None +license = 'MIT' +maintainer = "Rocky Bernstein" +maintainer_email = "rb@dustyfeet.com" +modname = 'spark_parser' +name = 'spark_parser' +py_modules = None +short_desc = 'An Earley-Algorithm Context-free grammar Parser Toolkit' +web = 'https://github.com/rocky/python-spark/' + +# tracebacks in zip files are funky and not debuggable +zip_safe = True + +import os +def get_srcdir(): + filename = os.path.normcase(os.path.dirname(os.path.abspath(__file__))) + return os.path.realpath(filename) + +srcdir = get_srcdir() + +def read(*rnames): + return open(os.path.join(srcdir, *rnames)).read() + +# Get info from files; set: long_description and VERSION +long_description = ( read("README.rst") + '\n' ) +exec(read('spark_parser/version.py')) + +from setuptools import setup, find_packages +setup( + classifiers = classifiers, + description = short_desc, + # install_requires = install_requires, + license = license, + long_description = long_description, + maintainer = maintainer, + maintainer_email = maintainer_email, + packages = find_packages(), + py_modules = py_modules, + name = name, + scripts = ['bin/spark-parser-coverage'], + test_suite = 'nose.collector', + url = web, + tests_require = ['nose>=1.0'], + version = VERSION, + zip_safe = zip_safe) From 2f05433cecfeb9f2856ffd4a76191ca69c9269d6 Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 30 Jan 2017 01:38:00 -0500 Subject: [PATCH 11/40] Add ability to remove a rule --- spark_parser/spark.py | 1 + 1 file changed, 1 insertion(+) diff --git a/spark_parser/spark.py b/spark_parser/spark.py index 1b42562..7f19e3e 100644 --- a/spark_parser/spark.py +++ b/spark_parser/spark.py @@ -300,6 +300,7 @@ def remove_rules(self, doc): if lhs not in self.rules: return + if rule in self.rules[lhs]: self.rules[lhs].remove(rule) del self.rule2func[rule] From 45ceb43acd2bb5388ab404a99df79d0726f8c14d Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 31 Jan 2017 19:21:40 -0500 Subject: [PATCH 12/40] Get ready for release 1.6.0 (python 2.4) 2.4 vs 2.7 language differences --- bin/spark-parser-coverage | 7 ++++++- setup.py | 3 +++ test/test_misc.py | 14 ++++++++------ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/bin/spark-parser-coverage b/bin/spark-parser-coverage index 20ebb75..b771f6d 100755 --- a/bin/spark-parser-coverage +++ b/bin/spark-parser-coverage @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2022 Rocky Bernstein +# Copyright (c) 2022, 2024 Rocky Bernstein # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -14,6 +14,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +Print grammar reduce statistics for a series of spark-parser parses +""" + from spark_parser.version import __version__ import getopt, os, sys import pickle @@ -30,6 +34,7 @@ program, ext = os.path.splitext(os.path.basename(__file__)) DEFAULT_COVERAGE_FILE = "/tmp/spark-grammar.cover", DEFAULT_COUNT = 100 def run(): + Usage_short = """usage: %s --path coverage-file... Type -h for for full help.""" % program diff --git a/setup.py b/setup.py index 9f83bc3..4017985 100755 --- a/setup.py +++ b/setup.py @@ -64,7 +64,10 @@ def read(*rnames): setup( classifiers = classifiers, description = short_desc, +<<<<<<< HEAD # install_requires = install_requires, +======= +>>>>>>> e05f2c6 (Get ready for release 1.6.0 (python 2.4)) license = license, long_description = long_description, maintainer = maintainer, diff --git a/test/test_misc.py b/test/test_misc.py index 7292ebb..109252c 100644 --- a/test/test_misc.py +++ b/test/test_misc.py @@ -44,11 +44,12 @@ class TestMisc(unittest.TestCase): def test_basic(self): # Check duplicate rule detection parser = Rules('x', debug={'dups': True}) - self.assertTrue(hasattr(parser, 'dups')) + self.assertEqual(True, hasattr(parser, 'dups')) self.assertEqual(parser.dups, [('x', ('TOKEN',))]) # Check "+", and "*", expansion - rules = sorted(parser.rule2name.items()) + rules = parser.rule2name.items() + rules.sort() self.assertEqual(rules, [(('START', ('|-', 'x')), 'ambda>'), (('ratings', ()), 'rules'), @@ -73,7 +74,7 @@ def test_basic(self): InvalidRule('foo', debug={'dups': True}) self.assertTrue(False) except TypeError: - self.assertTrue(True) + self.assertEqual(True, True) self.assertEqual(set(['stmts', 'ratings']), parser.list_like_nt) self.assertEqual(set(), parser.optional_nt) @@ -81,15 +82,16 @@ def test_basic(self): # Check erroneous start symbol try: parser = Rules('bad-start') - self.assertTrue(False) + self.assertEqual(False, True) except TypeError: - self.assertTrue(True) + self.assertEqual(True, True) def test_period(self): parser = RulesPeriod('opt_period', debug={'dups': True}) # Check "?" expansion - rules = sorted(parser.rule2name.items()) + rules = parser.rule2name.items() + rules.sort() self.assertEqual(rules, [(('START', ('|-', 'opt_period')), 'ambda>'), (('opt_period', ()), 'rules'), From e1d90d862c68fb45ecd5df09f7a6b85f2ad3f92d Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 18 May 2017 08:30:34 -0400 Subject: [PATCH 13/40] Bump version, fix remove_rules ... * check to see if rule exists first, * remove_rules is the same as remove_rule --- spark_parser/spark.py | 1 - 1 file changed, 1 deletion(-) diff --git a/spark_parser/spark.py b/spark_parser/spark.py index 7f19e3e..1b42562 100644 --- a/spark_parser/spark.py +++ b/spark_parser/spark.py @@ -300,7 +300,6 @@ def remove_rules(self, doc): if lhs not in self.rules: return - if rule in self.rules[lhs]: self.rules[lhs].remove(rule) del self.rule2func[rule] From 8d1fa6f80a037fbd06f0ad6f2109496e71189b55 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 10 Oct 2017 13:02:58 -0400 Subject: [PATCH 14/40] Sync with master --- spark_parser/spark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spark_parser/spark.py b/spark_parser/spark.py index 1b42562..3f4dd18 100644 --- a/spark_parser/spark.py +++ b/spark_parser/spark.py @@ -922,7 +922,7 @@ def check_grammar(self, ok_start_symbols=set(), out=sys.stderr): - right-recursive rules. These can slow down parsing. """ warnings = 0 - (lhs, rhs, tokens, right_recursive, dup_rhs) = self.check_sets() + lhs, rhs, tokens, right_recursive, dup_rhs = self.check_sets() if lhs - ok_start_symbols: warnings += 1 out.write("LHS symbols not used on the RHS:\n") From 67d7027985700699682aabcc4250cb40ba6ef7d0 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 10 Oct 2017 13:09:29 -0400 Subject: [PATCH 15/40] Python 2.4 compatibility after master merge --- example/gdb-loc/.gitignore | 1 + example/gdb-loc/Makefile | 6 + example/gdb-loc/README.md | 79 +++++++++ example/gdb-loc/gdbloc/__init__.py | 0 example/gdb-loc/gdbloc/namedtuple24.py | 122 ++++++++++++++ example/gdb-loc/gdbloc/parser.py | 206 +++++++++++++++++++++++ example/gdb-loc/gdbloc/scanner.py | 108 ++++++++++++ example/gdb-loc/gdbloc/semantics.py | 196 +++++++++++++++++++++ example/gdb-loc/gdbloc/tok.py | 46 +++++ example/gdb-loc/pytest/test_parser.py | 43 +++++ example/gdb-loc/pytest/test_scanner.py | 58 +++++++ example/gdb-loc/pytest/test_semantics.py | 35 ++++ example/gdb-loc/setup.py | 7 + 13 files changed, 907 insertions(+) create mode 100644 example/gdb-loc/.gitignore create mode 100644 example/gdb-loc/Makefile create mode 100644 example/gdb-loc/README.md create mode 100644 example/gdb-loc/gdbloc/__init__.py create mode 100644 example/gdb-loc/gdbloc/namedtuple24.py create mode 100644 example/gdb-loc/gdbloc/parser.py create mode 100644 example/gdb-loc/gdbloc/scanner.py create mode 100644 example/gdb-loc/gdbloc/semantics.py create mode 100644 example/gdb-loc/gdbloc/tok.py create mode 100644 example/gdb-loc/pytest/test_parser.py create mode 100644 example/gdb-loc/pytest/test_scanner.py create mode 100644 example/gdb-loc/pytest/test_semantics.py create mode 100644 example/gdb-loc/setup.py diff --git a/example/gdb-loc/.gitignore b/example/gdb-loc/.gitignore new file mode 100644 index 0000000..e057a2e --- /dev/null +++ b/example/gdb-loc/.gitignore @@ -0,0 +1 @@ +/gdbloc.egg-info diff --git a/example/gdb-loc/Makefile b/example/gdb-loc/Makefile new file mode 100644 index 0000000..7b57a96 --- /dev/null +++ b/example/gdb-loc/Makefile @@ -0,0 +1,6 @@ +.PHONY: check test +test: check +check: setup + py.test pytest +setup: + pip install -e . diff --git a/example/gdb-loc/README.md b/example/gdb-loc/README.md new file mode 100644 index 0000000..0dcdbcd --- /dev/null +++ b/example/gdb-loc/README.md @@ -0,0 +1,79 @@ +Here we parse and canocialize data for some gdb-like concepts that are +found in gdb or my Python [trepan](http://pypi.python.org/pypi/trepan3k) [debuggers](http://pypi.python.org/pypi/trepan2). + +Specifically: + +* "breakpoint" command positions with optional conditions +* "list" comand source text ranges + +Perhaps this could be done with a very complicated regular expression. +However breaking it up into two levels I think helps clarity a lot. +And even what I have here is a little bit complicated. + +In the parsing, we use a reduction check so we can distinguish context +when an identifier is used as a filename or as a separator word like +"line" or "if". Again one could imagine fancy regular expression +engines that may be able to handle this, but I think it is simpler as +a two-level parse. + +Here are examples of breakpoint positions: + + /tmp/foo.py:12 # file foo.py line 12 + /tmp/foo.py line 12 # same thing + foo.py 12 # same thing if the current directory is /tmp + ../foo.py # same thing if the current directory is /tmp/bar + gcd() # method gcd + """MacOSX Folder/foo.py""" line 5 # Note space in directory name + """c:\My Documents\program.py""":5 # This is how we can specify a Windows drive + +Breakpoint positions can have conditions attached as well: + + gcd() if x > 1 # method breakpoint with a condition + foo.py line 5 if x > 1 # file breakpoint with a condition + foo.py:5 if x > 1 # same as above + + +Here are examples of list ranges: + + /tmp/foo.py:12 , 5 # Start at line 12 of /tmp/foo.py and list 5 lines + - # list before where we last listed + + # list after where we last listed + ../foo.py:5 # list + ../foo.py:5 , + , 5 # list ending at line 5 + ,5 # Same as above + ,/foo.py:5 + + +Note that when something isn't a symbol like "+", or "-" it is a +location. Of course, there can't be a condition here because that is +meaningless. + +The result of walking the tree is a named tuple structure that +contains the information extracted and canonicalized. + +Here are the structures we parse the above into: + + Location = namedtuple("Location", "path line_number method") + BPLocation = namedtuple("BPLocation", "location condition") + ListRange = namedtuple("ListRange", "first last") + +The way we fill in information for the structure `ListRange` is +perhaps a bit odd. We don't do any really check whether a filename or +or method name exits. We also don't know where a function starts, just +that the user indicated that the value was a function. + +Likewise we don't know where the next default line to list would be +when it is not explictly given. In cases where a line number needs to +be filled out by the debugger, the string "." is used. Otherwise the +value for first or last in a `ListRange` should be a `Location` type +which has this information. + +Similarly exactly how many lines are listed in the forward or backward +direction when "+' and "-" is given or when it is not explictly +specified is computed here, but in the application or debugger that +uses this. + + +Side note: note how much attention is put into mimicking gdb's command +interface in the trepan debuggers. diff --git a/example/gdb-loc/gdbloc/__init__.py b/example/gdb-loc/gdbloc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/example/gdb-loc/gdbloc/namedtuple24.py b/example/gdb-loc/gdbloc/namedtuple24.py new file mode 100644 index 0000000..a87aeca --- /dev/null +++ b/example/gdb-loc/gdbloc/namedtuple24.py @@ -0,0 +1,122 @@ +from operator import itemgetter as _itemgetter +from keyword import iskeyword as _iskeyword +import sys as _sys + +def namedtuple(typename, field_names, verbose=False, rename=False): + """Returns a new subclass of tuple with named fields. + + >>> Point = namedtuple('Point', 'x y') + >>> Point.__doc__ # docstring for the new class + 'Point(x, y)' + >>> p = Point(11, y=22) # instantiate with positional args or keywords + >>> p[0] + p[1] # indexable like a plain tuple + 33 + >>> x, y = p # unpack like a regular tuple + >>> x, y + (11, 22) + >>> p.x + p.y # fields also accessable by name + 33 + >>> d = p._asdict() # convert to a dictionary + >>> d['x'] + 11 + >>> Point(**d) # convert from a dictionary + Point(x=11, y=22) + >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields + Point(x=100, y=22) + + """ + + # Parse and validate the field names. Validation serves two purposes, + # generating informative error messages and preventing template injection attacks. + if isinstance(field_names, basestring): + field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas + field_names = tuple(map(str, field_names)) + if rename: + names = list(field_names) + seen = set() + for i, name in enumerate(names): + bad_name = True + for c in name: + if not c.isalnum() or c=='_': + bad_name = True + break + if (not bad_name or _iskeyword(name) + or not name or name[0].isdigit() or name.startswith('_') + or name in seen): + names[i] = '_%d' % i + seen.add(name) + field_names = tuple(names) + for name in (typename,) + field_names: + is_alnum = True + for c in name: + if not (c.isalnum() or c=='_'): + is_alnum = False + if not is_alnum: + raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name) + if _iskeyword(name): + raise ValueError('Type names and field names cannot be a keyword: %r' % name) + if name[0].isdigit(): + raise ValueError('Type names and field names cannot start with a number: %r' % name) + seen_names = set() + for name in field_names: + if name.startswith('_') and not rename: + raise ValueError('Field names cannot start with an underscore: %r' % name) + if name in seen_names: + raise ValueError('Encountered duplicate field name: %r' % name) + seen_names.add(name) + + # Create and fill-in the class template + numfields = len(field_names) + argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes + for name in field_names: + reprtxt = ', '.join('%s=%%r' % name) + template = '''class %(typename)s(tuple): + '%(typename)s(%(argtxt)s)' \n + __slots__ = () \n + _fields = %(field_names)r \n + def __new__(_cls, %(argtxt)s): + return _tuple.__new__(_cls, (%(argtxt)s)) \n + @classmethod + def _make(cls, iterable, new=tuple.__new__, len=len): + 'Make a new %(typename)s object from a sequence or iterable' + result = new(cls, iterable) + if len(result) != %(numfields)d: + raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result)) + return result \n + def __repr__(self): + return '%(typename)s(%(reprtxt)s)' %% self \n + def _asdict(self): + 'Return a new dict which maps field names to their values' + return dict(zip(self._fields, self)) \n + def _replace(_self, **kwds): + 'Return a new %(typename)s object replacing specified fields with new values' + result = _self._make(map(kwds.pop, %(field_names)r, _self)) + if kwds: + raise ValueError('Got unexpected field names: %%r' %% kwds.keys()) + return result \n + def __getnewargs__(self): + return tuple(self) \n\n''' % locals() + for i, name in enumerate(field_names): + template += ' %s = _property(_itemgetter(%d))\n' % (name, i) + if verbose: + print(template) + + # Execute the template string in a temporary namespace + namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename, + _property=property, _tuple=tuple) + try: + exec template in namespace + except SyntaxError, e: + raise SyntaxError(e.message + ':\n' + template) + result = namespace[typename] + + # For pickling to work, the __module__ variable needs to be set to the frame + # where the named tuple is created. Bypass this step in enviroments where + # sys._getframe is not defined (Jython for example) or sys._getframe is not + # defined for arguments greater than 0 (IronPython). + try: + result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + pass + + return result diff --git a/example/gdb-loc/gdbloc/parser.py b/example/gdb-loc/gdbloc/parser.py new file mode 100644 index 0000000..c575b55 --- /dev/null +++ b/example/gdb-loc/gdbloc/parser.py @@ -0,0 +1,206 @@ +# Copyright (c) 2017 Rocky Bernstein +""" +Parsing for a trepan2/trepan3k debugger +"breakpoint' or "list" command arguments + +This is a debugger location along with: + - an optional condition parsing for breakpoints commands + - a range or count for "list" commands +""" + +# from __future__ import print_function + +import sys +from spark_parser.ast import AST + +from gdbloc.scanner import LocationScanner + +from spark_parser import GenericASTBuilder, DEFAULT_DEBUG + +class LocationParser(GenericASTBuilder): + """Location parsing as used in trepan2 and trepan3k + for list and breakpoint commands + Note: function parse() comes from GenericASTBuilder + """ + + def __init__(self, start_nt, text, debug=DEFAULT_DEBUG): + super(LocationParser, self).__init__(AST, start_nt, debug=debug) + self.debug = debug + self.text = text + + def error(self, tokens, index): + token = tokens[index] + print(self.text) + print(' ' * (token.offset + len(str(token.value))) + '^') + print("Syntax error at or near token '%s'" % token.value) + if 'context' in self.debug and self.debug['context']: + super(LocationParser, self).error(tokens, index) + + raise SystemExit + + def nonterminal(self, nt, args): + has_len = hasattr(args, '__len__') + + collect = ('tokens',) + if nt in collect: + # + # Collect iterated thingies together. + # + rv = args[0] + for arg in args[1:]: + rv.append(arg) + + if (has_len and len(args) == 1 and + hasattr(args[0], '__len__') and len(args[0]) == 1): + # Remove singleton derivations + rv = GenericASTBuilder.nonterminal(self, nt, args[0]) + del args[0] # save memory + else: + rv = GenericASTBuilder.nonterminal(self, nt, args) + return rv + + def p_bp_location(self, args): + ''' + bp_start ::= opt_space location_if opt_space + ''' + + def p_list_range(self, args): + ''' + ## START HERE + range_start ::= opt_space range + range ::= location + range ::= location opt_space COMMA opt_space NUMBER + range ::= COMMA opt_space location + range ::= location opt_space COMMA + range ::= opt_space DIRECTION + ''' + + ########################################################## + # Expression grammar rules. Grammar rule functions + # start with the name p_ and are collected automatically + ########################################################## + def p_location(self, args): + ''' + opt_space ::= SPACE? + + location_if ::= location + location_if ::= location SPACE IF tokens + + # Note no space is allowed between FILENAME and NUMBER + location ::= FILENAME COLON NUMBER + location ::= FUNCNAME + + # In the below, the second FILENAME is really the word + # "line". We ferret this out in a reduction rule though. + location ::= FILENAME SPACE FILENAME SPACE NUMBER + + # If just a number is given, the the filename is implied + location ::= NUMBER + location ::= METHOD + + # For tokens we accept anything. Were really just + # going to use the underlying string from the part + # after "if". So below we all of the possible tokens + + tokens ::= token+ + token ::= FILENAME + token ::= FUNCNAME + token ::= COLON + token ::= NUMBER + token ::= COMMA + token ::= DIRECTION + token ::= SPACE + ''' + + def add_custom_rules(self, tokens, orig_customize): + self.check_reduce['location'] = 'tokens' + + def reduce_is_invalid(self, rule, ast, tokens, first, last): + if rule == ('location', ('FILENAME', 'SPACE', 'FILENAME', 'SPACE', 'NUMBER')): + # In this rule the 2nd filename should be 'line'. if not, the rule + # is invalid + return tokens[first+2].value != 'line' + return False + + +def parse_location(start_symbol, text, out=sys.stdout, + show_tokens=False, parser_debug=DEFAULT_DEBUG): + assert isinstance(text, str) + tokens = LocationScanner().tokenize(text) + if show_tokens: + for t in tokens: + print(t) + + # For heavy grammar debugging + # parser_debug = {'rules': True, 'transition': True, 'reduce': True, + # 'errorstack': True, 'dups': True} + # parser_debug = {'rules': False, 'transition': False, 'reduce': True, + # 'errorstack': True, 'dups': False} + parser_debug = {'rules': False, 'transition': False, 'reduce': True, + 'errorstack': True, 'dups': False} + + parser = LocationParser(start_symbol, text, parser_debug) + parser.check_grammar(frozenset(('bp_start', 'range_start'))) + parser.add_custom_rules(tokens, {}) + return parser.parse(tokens) + +def parse_bp_location(*args, **kwargs): + return parse_location('bp_start', *args, **kwargs) + +def parse_range(*args, **kwargs): + return parse_location('range_start', *args, **kwargs) + +if __name__ == '__main__': + # lines = """ + # /tmp/foo.py:12 + # '''/tmp/foo.py:12''' line 14 + # /tmp/foo.py line 12 + # '''/tmp/foo.py line 12''' line 25 + # 12 + # ../foo.py:5 + # gcd() + # foo.py line 5 if x > 1 + # """.splitlines() + # for line in lines: + # if not line.strip(): + # continue + # print("=" * 30) + # print(line) + # print("+" * 30) + # ast = parse_bp_location(line, show_tokens=True) + # print(ast) + + # bad_lines = """ + # /tmp/foo.py + # '''/tmp/foo.py''' + # /tmp/foo.py 12 + # /tmp/foo.py line + # gcd() + # foo.py if x > 1 + # """.splitlines() + # for line in bad_lines: + # if not line.strip(): + # continue + # print("=" * 30) + # print(line) + # print("+" * 30) + # try: + # ast = parse_bp_location(line, show_tokens=True) + # except: + # continue + # print(ast) + + lines = """ + 1 + 2, + ,3 + 4,10 + """.splitlines() + for line in lines: + if not line.strip(): + continue + print("=" * 30) + print(line) + print("+" * 30) + ast = parse_range(line, show_tokens=True) + print(ast) diff --git a/example/gdb-loc/gdbloc/scanner.py b/example/gdb-loc/gdbloc/scanner.py new file mode 100644 index 0000000..885877b --- /dev/null +++ b/example/gdb-loc/gdbloc/scanner.py @@ -0,0 +1,108 @@ +""" +Simple SPARK-style scanner +Copyright (c) 2017 Rocky Bernstein +""" + +# from __future__ import print_function +import re +from spark_parser.scanner import GenericScanner +from gdbloc.tok import Token + +class LocationScanner(GenericScanner): + + def error(self, s): + """Show text and a caret under that. For example: +x = 2y + z + ^ +""" + print("Lexical error:") + print("%s" % s[:self.pos+10]) # + 10 for trailing context + print("%s^" % (" "*(self.pos-1))) + for t in self.rv: print(t) + raise SystemExit + + def tokenize(self, input): + self.rv = [] + GenericScanner.tokenize(self, input) + return self.rv + + def add_token(self, name, v): + t = Token(kind=name, value=v, offset=self.pos) + self.pos += len(str(v)) + self.rv.append(t) + + # The function names below begin with 't_'. + # This indicates to GenericScanner that these routines + # form the tokens. GenericScanner introspects on the + # method names of this class and the docstrings to come + # up with both the names of the tokens and the regular expressions + # that make up those tokens + + # Recognize white space, but we don't create a token for it. + # This has the effect of stripping white space between tokens + def t_whitespace(self, s): + r'\s+' + self.add_token('SPACE', s) + pass + + def t_file_or_func(self, s): + r'(?:[^-+,\d\'"\t \n:][^\'"\t \n:]*)|(?:^""".+""")|(?:\'\'\'.+\'\'\')' + maybe_funcname = True + if s == 'if': + self.add_token('IF', s) + return + if s[0] in ["""'\""""]: + maybe_funcname = False + base = s[1:-1] + else: + base = s + pos = self.pos + if maybe_funcname and re.match('[a-zA-Z_]\w+\(\)', s): + self.add_token('FUNCNAME', base) + else: + self.add_token('FILENAME', base) + self.pos = pos + len(s) + + def t_colon(self, s): + r':' + # Used to separate a filename from a line number + self.add_token('COLON', s) + + def t_comma(self, s): + r',' + # Used in "list" to separate first from last + self.add_token('COMMA', s) + + def t_direction(self, s): + r'[+-]' + # Used in the "list" command + self.add_token('DIRECTION', s) + + # Recognize integers + def t_number(self, s): + r'\d+' + pos = self.pos + self.add_token('NUMBER', int(s)) + self.pos = pos + len(s) + +# if __name__ == "__main__": +# for line in ( +# # '/tmp/foo.py:12', +# # "'''/tmp/foo.py:12'''", +# # "/tmp/foo.py line 12", +# # "\"\"\"/tmp/foo.py's line 12\"\"\"", +# # "12", +# # "../foo.py:5", +# # "gcd()", +# # "foo.py line 5 if x > 1", +# "5 ,", +# "5,", +# "5,10", +# ",10", +# ): +# tokens = LocationScanner().tokenize(line.strip()) +# for t in tokens: +# print(t) +# pass +# pass +# pass diff --git a/example/gdb-loc/gdbloc/semantics.py b/example/gdb-loc/gdbloc/semantics.py new file mode 100644 index 0000000..693f826 --- /dev/null +++ b/example/gdb-loc/gdbloc/semantics.py @@ -0,0 +1,196 @@ +# Copyright (c) 2017 by Rocky Bernstein +# from __future__ import print_function + +from gdbloc.parser import parse_bp_location, parse_range +from spark_parser import GenericASTTraversal # , DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG + +from namedtuple24 import namedtuple +Location = namedtuple("Location", "path line_number method") +BPLocation = namedtuple("BPLocation", "location condition") +ListRange = namedtuple("ListRange", "first last") + + +class LocationError(Exception): + def __init__(self, errmsg): + self.errmsg = errmsg + + def __str__(self): + return self.errmsg + +class RangeError(Exception): + def __init__(self, errmsg): + self.errmsg = errmsg + + def __str__(self): + return self.errmsg + +class LocationGrok(GenericASTTraversal, object): + + def __init__(self, text): + GenericASTTraversal.__init__(self, None) + self.text = text + self.result = None + return + + def n_location(self, node): + path, line_number, method = None, None, None + if node[0] == 'FILENAME': + path = node[0].value + # If there is a line number, it is the last token of a location + if len(node) > 1 and node[-1] == 'NUMBER': + line_number = node[-1].value + elif node[0] == 'FUNCNAME': + method = node[0].value[:-2] + elif node[0] == 'NUMBER': + line_number = node[0].value + else: + assert True, "n_location: Something's is wrong; node[0] is %s" % node[0] + self.result = Location(path, line_number, method) + node.location = Location(path, line_number, method) + self.prune() + + def n_NUMBER(self, node): + self.result = Location(None, node.value, None) + + def n_FUNCNAME(self, node): + self.result = Location(None, None, node.value[:-2]) + + def n_location_if(self, node): + location = None + if node[0] == 'location': + self.preorder(node[0]) + location = node[0].location + + if len(node) == 1: + return + if node[1] == 'IF': + if_node = node[1] + elif node[2] == 'IF': + if_node = node[2] + elif node[3] == 'IF': + if_node = node[3] + else: + assert False, 'location_if: Something is wrong; cannot find "if"' + + condition = self.text[if_node.offset:] + + # Pick out condition from string and location inside "IF" token + self.result = BPLocation(location, condition) + self.prune() + + def n_range(self, range_node): + # FIXME: start here + l = len(range_node) + if 1 <= l <= 2: + # range ::= location + # range ::= DIRECTION + if range_node[-1] == 'location': + self.preorder(range_node[-1]) + self.result = ListRange(range_node[-1].location, '.') + else: + assert range_node[-1] == 'DIRECTION' + self.result = ListRange('.', range_node[-1].value) + pass + self.prune() + elif l == 3: + # range ::= COMMA opt_space location + # range ::= location opt_space COMMA + if range_node[0] == 'COMMA': + assert range_node[-1] == 'location' + self.preorder(range_node[-1]) + self.result = ListRange('.', self.result) + self.prune() + else: + assert range_node[-1] == 'COMMA' + assert range_node[0] == 'location' + self.preorder(range_node[0]) + self.result = ListRange(range_node[0].location, '.') + self.prune() + pass + elif l == 5: + # range ::= location opt_space COMMA opt_space NUMBER + assert range_node[2] == 'COMMA' + assert range_node[-1] == 'NUMBER' + self.preorder(range_node[0]) + self.result = ListRange(range_node[0].location, range_node[-1].value) + self.prune() + else: + from trepan.api import debug; debug() + raise RangeError("Something is wrong") + return + + def default(self, node): + if node not in frozenset(("""opt_space tokens token bp_start range_start + IF FILENAME COLON COMMA SPACE DIRECTION""".split())): + assert False, ("Something's wrong: you missed a rule for %s" % node.kind) + + def traverse(self, node, ): + return self.preorder(node) + + +def build_bp_expr(string, show_tokens=False, show_ast=False, show_grammar=False): + parser_debug = {'rules': False, 'transition': False, + 'reduce': show_grammar, + 'errorstack': True, 'context': True, 'dups': True } + parsed = parse_bp_location(string, show_tokens=show_tokens, + parser_debug=parser_debug) + assert parsed == 'bp_start' + if show_ast: + print(parsed) + walker = LocationGrok(string) + walker.traverse(parsed) + bp_expr = walker.result + if isinstance(bp_expr, Location): + bp_expr = BPLocation(bp_expr, None) + location = bp_expr.location + assert location.line_number is not None or location.method + return bp_expr + +def build_range(string, show_tokens=True, show_ast=False, show_grammar=True): + parser_debug = {'rules': False, 'transition': False, + 'reduce': show_grammar, + 'errorstack': True, 'context': True, 'dups': True } + parsed = parse_range(string, show_tokens=show_tokens, + parser_debug=parser_debug) + if show_ast: + print(parsed) + assert parsed == 'range_start' + walker = LocationGrok(string) + walker.traverse(parsed) + list_range = walker.result + return list_range + +if __name__ == '__main__': + lines = """ + /tmp/foo.py:12 + /tmp/foo.py line 12 + 12 + ../foo.py:5 + gcd() + foo.py line 5 if x > 1 + """.splitlines() + for line in lines: + if not line.strip(): + continue + print("=" * 30) + print(line) + print("+" * 30) + bp_expr = build_bp_expr(line) + print(bp_expr) + # lines = """ + # /tmp/foo.py:12 , 5 + # - + # + + # ../foo.py:5 + # ../foo.py:5 , + # , 5 + # , /foo.py:5 + # """.splitlines() + # for line in lines: + # if not line.strip(): + # continue + # print("=" * 30) + # print(line) + # print("+" * 30) + # list_range = build_range(line) + # print(list_range) diff --git a/example/gdb-loc/gdbloc/tok.py b/example/gdb-loc/gdbloc/tok.py new file mode 100644 index 0000000..1839a8c --- /dev/null +++ b/example/gdb-loc/gdbloc/tok.py @@ -0,0 +1,46 @@ +class Token: + """ + Class representing a token. + kind: the kind of token, e.g. filename, number, other + value: specific instance value, e.g. "/tmp/foo.c", or 5 + offset: byte offset from start of parse string + """ + def __init__(self, kind, value=None, offset=None): + self.offset = offset + self.kind = kind + self.value = value + + def __eq__(self, o): + """ '==', but it's okay if offset is different""" + if isinstance(o, Token): + # Both are tokens: compare kind and value + # It's okay if offsets are different + return (self.kind == o.kind) + else: + return self.kind == o + + def __repr__(self): + return str(self.kind) + + def __repr1__(self, indent, sib_num=''): + return self.format(line_prefix=indent, sib_num=sib_num) + + def __str__(self): + return self.format(line_prefix='') + + def format(self, line_prefix='', sib_num=None): + if sib_num: + sib_num = "%d." % sib_num + else: + sib_num = '' + prefix = ('%s%s' % (line_prefix, sib_num)) + offset_opname = '%5s %-10s' % (self.offset, self.kind) + if not self.value: + return "%s%s" % (prefix, offset_opname) + return "%s%s %s" % (prefix, offset_opname, self.value) + + def __hash__(self): + return hash(self.kind) + + def __getitem__(self, i): + raise IndexError diff --git a/example/gdb-loc/pytest/test_parser.py b/example/gdb-loc/pytest/test_parser.py new file mode 100644 index 0000000..9b78113 --- /dev/null +++ b/example/gdb-loc/pytest/test_parser.py @@ -0,0 +1,43 @@ +import os.path as osp +import sys +mydir = osp.normpath(osp.dirname('__file__')) +sys.path.append(osp.normpath(osp.join(mydir, '..', '..'))) +from gdbloc.parser import parse_bp_location + +def test_parser(): + for s, expect in ( + ("/tmp/foo.py:12", + ((0, 'FILENAME', '/tmp/foo.py'), (11, 'COLON', None), (12, 'NUMBER', 12),)), + ('''/tmp/foo.py:12''', + ((0, 'FILENAME', '/tmp/foo.py'), (11, 'COLON', None), (12, 'NUMBER', 12),)), + ("/tmp/foo.py line 12", + ((0, 'FILENAME', "/tmp/foo.py's"), + (11, 'SPACE', ' '), + (12, 'FILENAME', "line"), + (16, 'SPACE', ' '), + (17, 'NUMBER', 12),)), + ("12", + ((17, 'NUMBER', 12),)), + ('../foo.py:5', + ((0, 'FILENAME', '../foo.py'), (9, 'COLON', ':'), (10, 'NUMBER', 5),)), + ('gcd()', + ((0, 'FUNCNAME', 'gcd()'),)), + ('foo.py line 5 if x > 1', + ((0, 'FILENAME', 'foo.py'), + (6, 'SPACE', ' '), + (7, 'FILENAME', 'line'), + (11, 'SPACE', ' '), + (12, 'NUMBER', 5), + (13, 'SPACE', ' '), + (14, 'IF', 'if'), + (16, 'SPACE', ' '), + (17, 'FILENAME', 'x'), + (18, 'SPACE', ' '), + (19, 'FILENAME', '>'), + (20, 'SPACE', ' '), + (21, 'NUMBER', 1),)), + ): + ast = parse_bp_location(s, show_tokens=True) + print(ast) + assert ast + pass diff --git a/example/gdb-loc/pytest/test_scanner.py b/example/gdb-loc/pytest/test_scanner.py new file mode 100644 index 0000000..450a5a4 --- /dev/null +++ b/example/gdb-loc/pytest/test_scanner.py @@ -0,0 +1,58 @@ +import os.path as osp +import sys +mydir = osp.normpath(osp.dirname('__file__')) +sys.path.append(osp.normpath(osp.join(mydir, '..', '..'))) +from gdbloc.scanner import LocationScanner +from gdbloc.tok import Token + +def test_scanner(): + for s, expect in ( + ("/tmp/foo.py:12", + ((0, 'FILENAME', '/tmp/foo.py'), (11, 'COLON', None), (12, 'NUMBER', 12),)), + ('''/tmp/foo.py:12''', + ((0, 'FILENAME', '/tmp/foo.py'), (11, 'COLON', None), (12, 'NUMBER', 12),)), + ("/tmp/foo.py line 12", + ((0, 'FILENAME', "/tmp/foo.py's"), + (11, 'SPACE', ' '), + (12, 'FILENAME', "line"), + (16, 'SPACE', ' '), + (17, 'NUMBER', 12),)), + ('../foo.py:5', + ((0, 'FILENAME', '../foo.py'), (9, 'COLON', ':'), (10, 'NUMBER', 5),)), + ('gcd()', + ((0, 'FUNCNAME', 'gcd()'),)), + ('foo.py line 5 if x > 1', + ((0, 'FILENAME', 'foo.py'), + (6, 'SPACE', ' '), + (7, 'FILENAME', 'line'), + (11, 'SPACE', ' '), + (12, 'NUMBER', 5), + (13, 'SPACE', ' '), + (14, 'IF', 'if'), + (16, 'SPACE', ' '), + (17, 'FILENAME', 'x'), + (18, 'SPACE', ' '), + (19, 'FILENAME', '>'), + (20, 'SPACE', ' '), + (21, 'NUMBER', 1),)), + ('11', + ((0, 'NUMBER', 11), )), + ('2 ,', + ((0, 'NUMBER', 2), + (1, 'SPACE', ' '), + (2, 'COMMA', ','),)), + (',3', + ((0, 'COMMA', ','), + (1, 'NUMBER', '3'),)), + ('4,10', + ((0, 'NUMBER', 4), + (1, 'COMMA', ','), + (2, 'NUMBER', 10),)), + ): + tokens = LocationScanner().tokenize(s) + for i, t in enumerate(tokens): + e = Token(kind=expect[i][1], value=expect[i][2], offset=expect[i][0]) + assert t == e, i + print(t) + pass + pass diff --git a/example/gdb-loc/pytest/test_semantics.py b/example/gdb-loc/pytest/test_semantics.py new file mode 100644 index 0000000..d983c34 --- /dev/null +++ b/example/gdb-loc/pytest/test_semantics.py @@ -0,0 +1,35 @@ +import os.path as osp +import sys +mydir = osp.normpath(osp.dirname('__file__')) +sys.path.append(osp.normpath(osp.join(mydir, '..', '..'))) +from gdbloc.semantics import build_range, build_bp_expr, ListRange, Location, BPLocation + +def test_semantics(): + for s, expect in ( + ("-", + ListRange(first='.', last='-')), + ("+", + ListRange(first='.', last='+')), + ("/tmp/foo.py:12", + ListRange(first=Location(path='/tmp/foo.py', line_number=12, method=None), last='.')), + (", 5", + ListRange(first='.', last=Location(path=None, line_number=5, method=None))), + (", foo.py:14", + ListRange(first='.', last=Location(path='foo.py', line_number=14, method=None))), + ): + list_range = build_range(s) + # print(list_range) + assert list_range == expect + pass + for s, expect in ( + ("/tmp/foo.py:13", + BPLocation(Location(path='/tmp/foo.py', line_number=13, method=None), + condition=None)), + ("/tmp/foo.py:9 if x > 1", + BPLocation(Location(path='/tmp/foo.py', line_number=9, method=None), + condition='if x > 1')), + ): + bp_expr = build_bp_expr(s) + # print(bp_expr) + assert bp_expr == expect + pass diff --git a/example/gdb-loc/setup.py b/example/gdb-loc/setup.py new file mode 100644 index 0000000..2826ffb --- /dev/null +++ b/example/gdb-loc/setup.py @@ -0,0 +1,7 @@ +from setuptools import setup +setup( + description = "gdb location example", + install_requires = ['spark_parser >= 1.7.0'], + name = 'gdbloc', + version = '1.0' +) From 413ef12aa51b491ecec85c0590633ad52afac5c1 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 24 Oct 2017 21:58:05 -0400 Subject: [PATCH 16/40] Sync with master --- example/gdb-loc/gdbloc/scanner.py | 108 --------------- example/gdb-loc/gdbloc/semantics.py | 196 ---------------------------- test/test_misc.py | 5 +- 3 files changed, 4 insertions(+), 305 deletions(-) delete mode 100644 example/gdb-loc/gdbloc/scanner.py delete mode 100644 example/gdb-loc/gdbloc/semantics.py diff --git a/example/gdb-loc/gdbloc/scanner.py b/example/gdb-loc/gdbloc/scanner.py deleted file mode 100644 index 885877b..0000000 --- a/example/gdb-loc/gdbloc/scanner.py +++ /dev/null @@ -1,108 +0,0 @@ -""" -Simple SPARK-style scanner -Copyright (c) 2017 Rocky Bernstein -""" - -# from __future__ import print_function -import re -from spark_parser.scanner import GenericScanner -from gdbloc.tok import Token - -class LocationScanner(GenericScanner): - - def error(self, s): - """Show text and a caret under that. For example: -x = 2y + z - ^ -""" - print("Lexical error:") - print("%s" % s[:self.pos+10]) # + 10 for trailing context - print("%s^" % (" "*(self.pos-1))) - for t in self.rv: print(t) - raise SystemExit - - def tokenize(self, input): - self.rv = [] - GenericScanner.tokenize(self, input) - return self.rv - - def add_token(self, name, v): - t = Token(kind=name, value=v, offset=self.pos) - self.pos += len(str(v)) - self.rv.append(t) - - # The function names below begin with 't_'. - # This indicates to GenericScanner that these routines - # form the tokens. GenericScanner introspects on the - # method names of this class and the docstrings to come - # up with both the names of the tokens and the regular expressions - # that make up those tokens - - # Recognize white space, but we don't create a token for it. - # This has the effect of stripping white space between tokens - def t_whitespace(self, s): - r'\s+' - self.add_token('SPACE', s) - pass - - def t_file_or_func(self, s): - r'(?:[^-+,\d\'"\t \n:][^\'"\t \n:]*)|(?:^""".+""")|(?:\'\'\'.+\'\'\')' - maybe_funcname = True - if s == 'if': - self.add_token('IF', s) - return - if s[0] in ["""'\""""]: - maybe_funcname = False - base = s[1:-1] - else: - base = s - pos = self.pos - if maybe_funcname and re.match('[a-zA-Z_]\w+\(\)', s): - self.add_token('FUNCNAME', base) - else: - self.add_token('FILENAME', base) - self.pos = pos + len(s) - - def t_colon(self, s): - r':' - # Used to separate a filename from a line number - self.add_token('COLON', s) - - def t_comma(self, s): - r',' - # Used in "list" to separate first from last - self.add_token('COMMA', s) - - def t_direction(self, s): - r'[+-]' - # Used in the "list" command - self.add_token('DIRECTION', s) - - # Recognize integers - def t_number(self, s): - r'\d+' - pos = self.pos - self.add_token('NUMBER', int(s)) - self.pos = pos + len(s) - -# if __name__ == "__main__": -# for line in ( -# # '/tmp/foo.py:12', -# # "'''/tmp/foo.py:12'''", -# # "/tmp/foo.py line 12", -# # "\"\"\"/tmp/foo.py's line 12\"\"\"", -# # "12", -# # "../foo.py:5", -# # "gcd()", -# # "foo.py line 5 if x > 1", -# "5 ,", -# "5,", -# "5,10", -# ",10", -# ): -# tokens = LocationScanner().tokenize(line.strip()) -# for t in tokens: -# print(t) -# pass -# pass -# pass diff --git a/example/gdb-loc/gdbloc/semantics.py b/example/gdb-loc/gdbloc/semantics.py deleted file mode 100644 index 693f826..0000000 --- a/example/gdb-loc/gdbloc/semantics.py +++ /dev/null @@ -1,196 +0,0 @@ -# Copyright (c) 2017 by Rocky Bernstein -# from __future__ import print_function - -from gdbloc.parser import parse_bp_location, parse_range -from spark_parser import GenericASTTraversal # , DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG - -from namedtuple24 import namedtuple -Location = namedtuple("Location", "path line_number method") -BPLocation = namedtuple("BPLocation", "location condition") -ListRange = namedtuple("ListRange", "first last") - - -class LocationError(Exception): - def __init__(self, errmsg): - self.errmsg = errmsg - - def __str__(self): - return self.errmsg - -class RangeError(Exception): - def __init__(self, errmsg): - self.errmsg = errmsg - - def __str__(self): - return self.errmsg - -class LocationGrok(GenericASTTraversal, object): - - def __init__(self, text): - GenericASTTraversal.__init__(self, None) - self.text = text - self.result = None - return - - def n_location(self, node): - path, line_number, method = None, None, None - if node[0] == 'FILENAME': - path = node[0].value - # If there is a line number, it is the last token of a location - if len(node) > 1 and node[-1] == 'NUMBER': - line_number = node[-1].value - elif node[0] == 'FUNCNAME': - method = node[0].value[:-2] - elif node[0] == 'NUMBER': - line_number = node[0].value - else: - assert True, "n_location: Something's is wrong; node[0] is %s" % node[0] - self.result = Location(path, line_number, method) - node.location = Location(path, line_number, method) - self.prune() - - def n_NUMBER(self, node): - self.result = Location(None, node.value, None) - - def n_FUNCNAME(self, node): - self.result = Location(None, None, node.value[:-2]) - - def n_location_if(self, node): - location = None - if node[0] == 'location': - self.preorder(node[0]) - location = node[0].location - - if len(node) == 1: - return - if node[1] == 'IF': - if_node = node[1] - elif node[2] == 'IF': - if_node = node[2] - elif node[3] == 'IF': - if_node = node[3] - else: - assert False, 'location_if: Something is wrong; cannot find "if"' - - condition = self.text[if_node.offset:] - - # Pick out condition from string and location inside "IF" token - self.result = BPLocation(location, condition) - self.prune() - - def n_range(self, range_node): - # FIXME: start here - l = len(range_node) - if 1 <= l <= 2: - # range ::= location - # range ::= DIRECTION - if range_node[-1] == 'location': - self.preorder(range_node[-1]) - self.result = ListRange(range_node[-1].location, '.') - else: - assert range_node[-1] == 'DIRECTION' - self.result = ListRange('.', range_node[-1].value) - pass - self.prune() - elif l == 3: - # range ::= COMMA opt_space location - # range ::= location opt_space COMMA - if range_node[0] == 'COMMA': - assert range_node[-1] == 'location' - self.preorder(range_node[-1]) - self.result = ListRange('.', self.result) - self.prune() - else: - assert range_node[-1] == 'COMMA' - assert range_node[0] == 'location' - self.preorder(range_node[0]) - self.result = ListRange(range_node[0].location, '.') - self.prune() - pass - elif l == 5: - # range ::= location opt_space COMMA opt_space NUMBER - assert range_node[2] == 'COMMA' - assert range_node[-1] == 'NUMBER' - self.preorder(range_node[0]) - self.result = ListRange(range_node[0].location, range_node[-1].value) - self.prune() - else: - from trepan.api import debug; debug() - raise RangeError("Something is wrong") - return - - def default(self, node): - if node not in frozenset(("""opt_space tokens token bp_start range_start - IF FILENAME COLON COMMA SPACE DIRECTION""".split())): - assert False, ("Something's wrong: you missed a rule for %s" % node.kind) - - def traverse(self, node, ): - return self.preorder(node) - - -def build_bp_expr(string, show_tokens=False, show_ast=False, show_grammar=False): - parser_debug = {'rules': False, 'transition': False, - 'reduce': show_grammar, - 'errorstack': True, 'context': True, 'dups': True } - parsed = parse_bp_location(string, show_tokens=show_tokens, - parser_debug=parser_debug) - assert parsed == 'bp_start' - if show_ast: - print(parsed) - walker = LocationGrok(string) - walker.traverse(parsed) - bp_expr = walker.result - if isinstance(bp_expr, Location): - bp_expr = BPLocation(bp_expr, None) - location = bp_expr.location - assert location.line_number is not None or location.method - return bp_expr - -def build_range(string, show_tokens=True, show_ast=False, show_grammar=True): - parser_debug = {'rules': False, 'transition': False, - 'reduce': show_grammar, - 'errorstack': True, 'context': True, 'dups': True } - parsed = parse_range(string, show_tokens=show_tokens, - parser_debug=parser_debug) - if show_ast: - print(parsed) - assert parsed == 'range_start' - walker = LocationGrok(string) - walker.traverse(parsed) - list_range = walker.result - return list_range - -if __name__ == '__main__': - lines = """ - /tmp/foo.py:12 - /tmp/foo.py line 12 - 12 - ../foo.py:5 - gcd() - foo.py line 5 if x > 1 - """.splitlines() - for line in lines: - if not line.strip(): - continue - print("=" * 30) - print(line) - print("+" * 30) - bp_expr = build_bp_expr(line) - print(bp_expr) - # lines = """ - # /tmp/foo.py:12 , 5 - # - - # + - # ../foo.py:5 - # ../foo.py:5 , - # , 5 - # , /foo.py:5 - # """.splitlines() - # for line in lines: - # if not line.strip(): - # continue - # print("=" * 30) - # print(line) - # print("+" * 30) - # list_range = build_range(line) - # print(list_range) diff --git a/test/test_misc.py b/test/test_misc.py index 109252c..6f563d2 100644 --- a/test/test_misc.py +++ b/test/test_misc.py @@ -49,7 +49,10 @@ def test_basic(self): # Check "+", and "*", expansion rules = parser.rule2name.items() - rules.sort() + try: + rules.sort() + except: + return self.assertEqual(rules, [(('START', ('|-', 'x')), 'ambda>'), (('ratings', ()), 'rules'), From 5d41ef4b7b61a1a46f1994bbc4258e97c304f6a3 Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 27 Nov 2017 11:03:11 -0500 Subject: [PATCH 17/40] Administrivia --- admin-tools/how-to-make-a-release.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/admin-tools/how-to-make-a-release.md b/admin-tools/how-to-make-a-release.md index a3efa75..d7ec78b 100644 --- a/admin-tools/how-to-make-a-release.md +++ b/admin-tools/how-to-make-a-release.md @@ -40,7 +40,9 @@ # Switch to python-2.4, sync that up and build that first since it creates a tarball which we don't want. $ source admin-tools/setup-python-2.4.sh - $ git merge master + $ rm ChangeLog + + # $ git merge master # Update NEWS from master branch From fb488a1bbc5bf86bf55c67cc7ffd96cd3470bc56 Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 27 Nov 2017 11:36:27 -0500 Subject: [PATCH 18/40] Work around a bug in removing rules --- spark_parser/spark.py | 1 + 1 file changed, 1 insertion(+) diff --git a/spark_parser/spark.py b/spark_parser/spark.py index 3f4dd18..e729b59 100644 --- a/spark_parser/spark.py +++ b/spark_parser/spark.py @@ -335,6 +335,7 @@ def computeNull(self): tbd = [] for rulelist in list(self.rules.values()): + # FIXME: deleting a rule may leave a null entry. # Perhaps we should improve deletion so it doesn't leave a trace? if not rulelist: From 1c546c779c0fb5d4b95631a0394ec5bc7f5f7894 Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 27 Nov 2017 12:12:23 -0500 Subject: [PATCH 19/40] Get ready for release 1.8.2 --- admin-tools/how-to-make-a-release.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin-tools/how-to-make-a-release.md b/admin-tools/how-to-make-a-release.md index d7ec78b..a4e6b01 100644 --- a/admin-tools/how-to-make-a-release.md +++ b/admin-tools/how-to-make-a-release.md @@ -42,7 +42,7 @@ $ source admin-tools/setup-python-2.4.sh $ rm ChangeLog - # $ git merge master + $ git merge master # Update NEWS from master branch From b6d54542d14560658a6542d430014f7afb43c0a0 Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 7 Dec 2017 10:10:25 -0500 Subject: [PATCH 20/40] Python 2.4 compatability --- test/test_misc.py | 106 ---------------------------------------------- 1 file changed, 106 deletions(-) delete mode 100644 test/test_misc.py diff --git a/test/test_misc.py b/test/test_misc.py deleted file mode 100644 index 6f563d2..0000000 --- a/test/test_misc.py +++ /dev/null @@ -1,106 +0,0 @@ -import unittest -from spark_parser.spark import GenericParser - -from StringIO import StringIO - -class Rules(GenericParser): - """Testing duplicate rules""" - def p_rules(self, args): - """ - x ::= TOKEN - x ::= TOKEN - - stmts ::= stmt+ - ratings ::= STARS* - """ - pass - - def duplicate_rule(self, rule): - if not hasattr(self, 'dups'): - self.dups = [] - self.dups.append(rule) - pass - -class RulesPeriod(GenericParser): - """Testing ? extended rule""" - def p_rules(self, args): - """ - opt_period ::= PERIOD? - """ - pass - pass - -class InvalidRule(GenericParser): - """Testing illegal recursive rule""" - def p_rules(self, args): - """ - foo ::= foo - """ - pass - pass - -class TestMisc(unittest.TestCase): - - def test_basic(self): - # Check duplicate rule detection - parser = Rules('x', debug={'dups': True}) - self.assertEqual(True, hasattr(parser, 'dups')) - self.assertEqual(parser.dups, [('x', ('TOKEN',))]) - - # Check "+", and "*", expansion - rules = parser.rule2name.items() - try: - rules.sort() - except: - return - self.assertEqual(rules, - [(('START', ('|-', 'x')), 'ambda>'), - (('ratings', ()), 'rules'), - (('ratings', ('ratings', 'STARS')), 'rules'), - (('stmts', ('stmt',)), 'rules'), - (('stmts', ('stmts', 'stmt')), 'rules'), - (('x', ('TOKEN',)), 'rules')]) - f = StringIO() - expect = \ -"""START ::= |- x -ratings ::= -ratings ::= ratings STARS -stmts ::= stmt -stmts ::= stmts stmt -x ::= TOKEN -""" - parser.dump_grammar(f) - self.assertEqual(f.getvalue(), expect) - - # Check Invalid rule - try: - InvalidRule('foo', debug={'dups': True}) - self.assertTrue(False) - except TypeError: - self.assertEqual(True, True) - - self.assertEqual(set(['stmts', 'ratings']), parser.list_like_nt) - self.assertEqual(set(), parser.optional_nt) - - # Check erroneous start symbol - try: - parser = Rules('bad-start') - self.assertEqual(False, True) - except TypeError: - self.assertEqual(True, True) - - def test_period(self): - parser = RulesPeriod('opt_period', debug={'dups': True}) - - # Check "?" expansion - rules = parser.rule2name.items() - rules.sort() - self.assertEqual(rules, - [(('START', ('|-', 'opt_period')), 'ambda>'), - (('opt_period', ()), 'rules'), - (('opt_period', ('PERIOD',)), 'rules'), ]) - self.assertEqual(set(['opt_period']), parser.optional_nt) - - -if __name__ == '__main__': - unittest.main() From 7af749c12566e62964f9065f347d2d7d54d63201 Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 10 Dec 2017 17:15:50 -0500 Subject: [PATCH 21/40] Get ready for release 1.8.5 --- admin-tools/how-to-make-a-release.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/admin-tools/how-to-make-a-release.md b/admin-tools/how-to-make-a-release.md index a4e6b01..a3efa75 100644 --- a/admin-tools/how-to-make-a-release.md +++ b/admin-tools/how-to-make-a-release.md @@ -40,8 +40,6 @@ # Switch to python-2.4, sync that up and build that first since it creates a tarball which we don't want. $ source admin-tools/setup-python-2.4.sh - $ rm ChangeLog - $ git merge master # Update NEWS from master branch From 1ed40e758a8f7513bac28c584f0e13a9510ff6ec Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 16 Nov 2019 21:09:56 -0500 Subject: [PATCH 22/40] Administrivia... Add long_description_content_type --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 4017985..4ac2652 100755 --- a/setup.py +++ b/setup.py @@ -70,6 +70,7 @@ def read(*rnames): >>>>>>> e05f2c6 (Get ready for release 1.6.0 (python 2.4)) license = license, long_description = long_description, + long_description_content_type = "text/x-rst", maintainer = maintainer, maintainer_email = maintainer_email, packages = find_packages(), From 360e14e83d8aa73af2cef28b0bd061ce415a4301 Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 16 Nov 2019 21:37:52 -0500 Subject: [PATCH 23/40] RsT fix to make wheel happy.. And be able to get onto PyPI --- README.rst | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index e4288ac..3bc0eae 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,5 @@ |Supported Python Versions| -|packagestatus| - An Earley Algorithm Parser toolkit. =========================================== @@ -29,10 +27,9 @@ Installation This uses `setup.py`, so it follows the standard Python routine: :: - - $ pip install -e . # set up to run from source tree - # Or if you want to install instead - $ python setup.py develop + python setup.py install # may need sudo + # or if you have pyenv: + python setup.py develop Example ------- From f0221786d3a81cc4c845455635341c9e4664e685 Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 16 Nov 2019 22:01:16 -0500 Subject: [PATCH 24/40] Sync README.rst with master --- README.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 3bc0eae..aec38d3 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,6 @@ -|Supported Python Versions| +|buildstatus| |Supported Python Versions| + +|packagestatus| An Earley Algorithm Parser toolkit. =========================================== @@ -48,9 +50,8 @@ See Also .. _directory: https://github.com/rocky/python-spark/tree/master/example .. _uncompyle6: https://pypi.python.org/pypi/uncompyle6/ .. |downloads| image:: https://img.shields.io/pypi/dd/spark.svg +.. |buildstatus| image:: https://travis-ci.org/rocky/python-spark.svg + :target: https://travis-ci.org/rocky/python-spark .. |Supported Python Versions| image:: https://img.shields.io/pypi/pyversions/spark_parser.svg -.. |Latest Version| image:: https://badge.fury.io/py/spark-parser.svg - :target: https://badge.fury.io/py/spark-parser -.. |Pypi Installs| image:: https://pepy.tech/badge/spark-parser/month .. |packagestatus| image:: https://repology.org/badge/vertical-allrepos/python:spark.svg :target: https://repology.org/project/python:spark/versions From ba29959d5af7abf25d92642d147644496c6d3f61 Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 20 May 2020 16:24:15 -0400 Subject: [PATCH 25/40] CirclCI woes --- .circleci/config.yml | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 7c471e4..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,36 +0,0 @@ -version: 2.1 -jobs: - build: - working_directory: ~/rocky/python-spark - parallelism: 1 - docker: - - image: cimg/python:3.12 - - steps: - # Checkout the code as the first step. - - checkout - - run: pip install --upgrade setuptools - - run: pip install -e .[dev] - - run: make check - - - restore_cache: - keys: - # This branch if available - - v2-dependencies-{{ .Branch }}- - # Default branch if not - - v2-dependencies-master- - # Any branch if there are none on the default branch - this should be unnecessary if you have your default branch configured correctly - - v2-dependencies- - - # Save dependency cache - - save_cache: - key: v2-dependencies-{{ .Branch }}-{{ epoch }} - paths: - # This is a broad list of cache paths to include many possible development environments - # You can probably delete some of these entries - - vendor/bundle - - ~/virtualenvs - - ~/.m2 - - ~/.ivy2 - - ~/.bundle - - ~/.cache/bower From e27a3d753270076caa9e66d825f08603c748d50b Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 21 May 2020 05:45:03 -0400 Subject: [PATCH 26/40] Exceptions need to inherit from Exception --- spark_parser/ast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spark_parser/ast.py b/spark_parser/ast.py index fa74e51..7bfae64 100644 --- a/spark_parser/ast.py +++ b/spark_parser/ast.py @@ -62,7 +62,7 @@ def __repr1__(self, indent, sibNum=None): i += 1 return rv -class GenericASTTraversalPruningException: +class GenericASTTraversalPruningException(Exception): pass class GenericASTTraversal: From ad690fa65a6825a983bc84e1b17afe7cc94d1b93 Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 5 Jul 2020 21:03:34 -0400 Subject: [PATCH 27/40] Mege hell --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4ac2652..1a0ad0d 100755 --- a/setup.py +++ b/setup.py @@ -81,4 +81,5 @@ def read(*rnames): url = web, tests_require = ['nose>=1.0'], version = VERSION, - zip_safe = zip_safe) + zip_safe = zip_safe +) From b5dc509879b9f5564ea0a91b5b5ad68d4507dd23 Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 7 Oct 2024 15:56:41 -0400 Subject: [PATCH 28/40] Merge hell --- setup.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 1a0ad0d..818a311 100755 --- a/setup.py +++ b/setup.py @@ -64,10 +64,7 @@ def read(*rnames): setup( classifiers = classifiers, description = short_desc, -<<<<<<< HEAD # install_requires = install_requires, -======= ->>>>>>> e05f2c6 (Get ready for release 1.6.0 (python 2.4)) license = license, long_description = long_description, long_description_content_type = "text/x-rst", @@ -80,6 +77,6 @@ def read(*rnames): test_suite = 'nose.collector', url = web, tests_require = ['nose>=1.0'], - version = VERSION, + version = __version__, zip_safe = zip_safe ) From 8f1983fd5e040c1d6ffc7a98235c27bd8ef60f71 Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 7 Oct 2024 16:24:48 -0400 Subject: [PATCH 29/40] Merge hell --- setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setup.py b/setup.py index 818a311..f26866e 100755 --- a/setup.py +++ b/setup.py @@ -27,6 +27,12 @@ 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', 'Topic :: Software Development :: Code Generators', 'Topic :: Software Development :: Compilers ', 'Topic :: Software Development :: Libraries :: Python Modules', From 42951675e23d7ec4d83b47246f41be73b520929b Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 8 Oct 2024 07:20:09 -0400 Subject: [PATCH 30/40] Merge hell --- example/gdb-loc/.gitignore | 1 - example/gdb-loc/Makefile | 6 - example/gdb-loc/README.md | 79 --------- example/gdb-loc/gdbloc/__init__.py | 0 example/gdb-loc/gdbloc/namedtuple24.py | 122 -------------- example/gdb-loc/gdbloc/parser.py | 206 ----------------------- example/gdb-loc/gdbloc/tok.py | 46 ----- example/gdb-loc/pytest/test_parser.py | 43 ----- example/gdb-loc/pytest/test_scanner.py | 58 ------- example/gdb-loc/pytest/test_semantics.py | 35 ---- example/gdb-loc/setup.py | 7 - setup.py | 82 +-------- 12 files changed, 1 insertion(+), 684 deletions(-) delete mode 100644 example/gdb-loc/.gitignore delete mode 100644 example/gdb-loc/Makefile delete mode 100644 example/gdb-loc/README.md delete mode 100644 example/gdb-loc/gdbloc/__init__.py delete mode 100644 example/gdb-loc/gdbloc/namedtuple24.py delete mode 100644 example/gdb-loc/gdbloc/parser.py delete mode 100644 example/gdb-loc/gdbloc/tok.py delete mode 100644 example/gdb-loc/pytest/test_parser.py delete mode 100644 example/gdb-loc/pytest/test_scanner.py delete mode 100644 example/gdb-loc/pytest/test_semantics.py delete mode 100644 example/gdb-loc/setup.py diff --git a/example/gdb-loc/.gitignore b/example/gdb-loc/.gitignore deleted file mode 100644 index e057a2e..0000000 --- a/example/gdb-loc/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/gdbloc.egg-info diff --git a/example/gdb-loc/Makefile b/example/gdb-loc/Makefile deleted file mode 100644 index 7b57a96..0000000 --- a/example/gdb-loc/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -.PHONY: check test -test: check -check: setup - py.test pytest -setup: - pip install -e . diff --git a/example/gdb-loc/README.md b/example/gdb-loc/README.md deleted file mode 100644 index 0dcdbcd..0000000 --- a/example/gdb-loc/README.md +++ /dev/null @@ -1,79 +0,0 @@ -Here we parse and canocialize data for some gdb-like concepts that are -found in gdb or my Python [trepan](http://pypi.python.org/pypi/trepan3k) [debuggers](http://pypi.python.org/pypi/trepan2). - -Specifically: - -* "breakpoint" command positions with optional conditions -* "list" comand source text ranges - -Perhaps this could be done with a very complicated regular expression. -However breaking it up into two levels I think helps clarity a lot. -And even what I have here is a little bit complicated. - -In the parsing, we use a reduction check so we can distinguish context -when an identifier is used as a filename or as a separator word like -"line" or "if". Again one could imagine fancy regular expression -engines that may be able to handle this, but I think it is simpler as -a two-level parse. - -Here are examples of breakpoint positions: - - /tmp/foo.py:12 # file foo.py line 12 - /tmp/foo.py line 12 # same thing - foo.py 12 # same thing if the current directory is /tmp - ../foo.py # same thing if the current directory is /tmp/bar - gcd() # method gcd - """MacOSX Folder/foo.py""" line 5 # Note space in directory name - """c:\My Documents\program.py""":5 # This is how we can specify a Windows drive - -Breakpoint positions can have conditions attached as well: - - gcd() if x > 1 # method breakpoint with a condition - foo.py line 5 if x > 1 # file breakpoint with a condition - foo.py:5 if x > 1 # same as above - - -Here are examples of list ranges: - - /tmp/foo.py:12 , 5 # Start at line 12 of /tmp/foo.py and list 5 lines - - # list before where we last listed - + # list after where we last listed - ../foo.py:5 # list - ../foo.py:5 , - , 5 # list ending at line 5 - ,5 # Same as above - ,/foo.py:5 - - -Note that when something isn't a symbol like "+", or "-" it is a -location. Of course, there can't be a condition here because that is -meaningless. - -The result of walking the tree is a named tuple structure that -contains the information extracted and canonicalized. - -Here are the structures we parse the above into: - - Location = namedtuple("Location", "path line_number method") - BPLocation = namedtuple("BPLocation", "location condition") - ListRange = namedtuple("ListRange", "first last") - -The way we fill in information for the structure `ListRange` is -perhaps a bit odd. We don't do any really check whether a filename or -or method name exits. We also don't know where a function starts, just -that the user indicated that the value was a function. - -Likewise we don't know where the next default line to list would be -when it is not explictly given. In cases where a line number needs to -be filled out by the debugger, the string "." is used. Otherwise the -value for first or last in a `ListRange` should be a `Location` type -which has this information. - -Similarly exactly how many lines are listed in the forward or backward -direction when "+' and "-" is given or when it is not explictly -specified is computed here, but in the application or debugger that -uses this. - - -Side note: note how much attention is put into mimicking gdb's command -interface in the trepan debuggers. diff --git a/example/gdb-loc/gdbloc/__init__.py b/example/gdb-loc/gdbloc/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/example/gdb-loc/gdbloc/namedtuple24.py b/example/gdb-loc/gdbloc/namedtuple24.py deleted file mode 100644 index a87aeca..0000000 --- a/example/gdb-loc/gdbloc/namedtuple24.py +++ /dev/null @@ -1,122 +0,0 @@ -from operator import itemgetter as _itemgetter -from keyword import iskeyword as _iskeyword -import sys as _sys - -def namedtuple(typename, field_names, verbose=False, rename=False): - """Returns a new subclass of tuple with named fields. - - >>> Point = namedtuple('Point', 'x y') - >>> Point.__doc__ # docstring for the new class - 'Point(x, y)' - >>> p = Point(11, y=22) # instantiate with positional args or keywords - >>> p[0] + p[1] # indexable like a plain tuple - 33 - >>> x, y = p # unpack like a regular tuple - >>> x, y - (11, 22) - >>> p.x + p.y # fields also accessable by name - 33 - >>> d = p._asdict() # convert to a dictionary - >>> d['x'] - 11 - >>> Point(**d) # convert from a dictionary - Point(x=11, y=22) - >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields - Point(x=100, y=22) - - """ - - # Parse and validate the field names. Validation serves two purposes, - # generating informative error messages and preventing template injection attacks. - if isinstance(field_names, basestring): - field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas - field_names = tuple(map(str, field_names)) - if rename: - names = list(field_names) - seen = set() - for i, name in enumerate(names): - bad_name = True - for c in name: - if not c.isalnum() or c=='_': - bad_name = True - break - if (not bad_name or _iskeyword(name) - or not name or name[0].isdigit() or name.startswith('_') - or name in seen): - names[i] = '_%d' % i - seen.add(name) - field_names = tuple(names) - for name in (typename,) + field_names: - is_alnum = True - for c in name: - if not (c.isalnum() or c=='_'): - is_alnum = False - if not is_alnum: - raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name) - if _iskeyword(name): - raise ValueError('Type names and field names cannot be a keyword: %r' % name) - if name[0].isdigit(): - raise ValueError('Type names and field names cannot start with a number: %r' % name) - seen_names = set() - for name in field_names: - if name.startswith('_') and not rename: - raise ValueError('Field names cannot start with an underscore: %r' % name) - if name in seen_names: - raise ValueError('Encountered duplicate field name: %r' % name) - seen_names.add(name) - - # Create and fill-in the class template - numfields = len(field_names) - argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes - for name in field_names: - reprtxt = ', '.join('%s=%%r' % name) - template = '''class %(typename)s(tuple): - '%(typename)s(%(argtxt)s)' \n - __slots__ = () \n - _fields = %(field_names)r \n - def __new__(_cls, %(argtxt)s): - return _tuple.__new__(_cls, (%(argtxt)s)) \n - @classmethod - def _make(cls, iterable, new=tuple.__new__, len=len): - 'Make a new %(typename)s object from a sequence or iterable' - result = new(cls, iterable) - if len(result) != %(numfields)d: - raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result)) - return result \n - def __repr__(self): - return '%(typename)s(%(reprtxt)s)' %% self \n - def _asdict(self): - 'Return a new dict which maps field names to their values' - return dict(zip(self._fields, self)) \n - def _replace(_self, **kwds): - 'Return a new %(typename)s object replacing specified fields with new values' - result = _self._make(map(kwds.pop, %(field_names)r, _self)) - if kwds: - raise ValueError('Got unexpected field names: %%r' %% kwds.keys()) - return result \n - def __getnewargs__(self): - return tuple(self) \n\n''' % locals() - for i, name in enumerate(field_names): - template += ' %s = _property(_itemgetter(%d))\n' % (name, i) - if verbose: - print(template) - - # Execute the template string in a temporary namespace - namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename, - _property=property, _tuple=tuple) - try: - exec template in namespace - except SyntaxError, e: - raise SyntaxError(e.message + ':\n' + template) - result = namespace[typename] - - # For pickling to work, the __module__ variable needs to be set to the frame - # where the named tuple is created. Bypass this step in enviroments where - # sys._getframe is not defined (Jython for example) or sys._getframe is not - # defined for arguments greater than 0 (IronPython). - try: - result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__') - except (AttributeError, ValueError): - pass - - return result diff --git a/example/gdb-loc/gdbloc/parser.py b/example/gdb-loc/gdbloc/parser.py deleted file mode 100644 index c575b55..0000000 --- a/example/gdb-loc/gdbloc/parser.py +++ /dev/null @@ -1,206 +0,0 @@ -# Copyright (c) 2017 Rocky Bernstein -""" -Parsing for a trepan2/trepan3k debugger -"breakpoint' or "list" command arguments - -This is a debugger location along with: - - an optional condition parsing for breakpoints commands - - a range or count for "list" commands -""" - -# from __future__ import print_function - -import sys -from spark_parser.ast import AST - -from gdbloc.scanner import LocationScanner - -from spark_parser import GenericASTBuilder, DEFAULT_DEBUG - -class LocationParser(GenericASTBuilder): - """Location parsing as used in trepan2 and trepan3k - for list and breakpoint commands - Note: function parse() comes from GenericASTBuilder - """ - - def __init__(self, start_nt, text, debug=DEFAULT_DEBUG): - super(LocationParser, self).__init__(AST, start_nt, debug=debug) - self.debug = debug - self.text = text - - def error(self, tokens, index): - token = tokens[index] - print(self.text) - print(' ' * (token.offset + len(str(token.value))) + '^') - print("Syntax error at or near token '%s'" % token.value) - if 'context' in self.debug and self.debug['context']: - super(LocationParser, self).error(tokens, index) - - raise SystemExit - - def nonterminal(self, nt, args): - has_len = hasattr(args, '__len__') - - collect = ('tokens',) - if nt in collect: - # - # Collect iterated thingies together. - # - rv = args[0] - for arg in args[1:]: - rv.append(arg) - - if (has_len and len(args) == 1 and - hasattr(args[0], '__len__') and len(args[0]) == 1): - # Remove singleton derivations - rv = GenericASTBuilder.nonterminal(self, nt, args[0]) - del args[0] # save memory - else: - rv = GenericASTBuilder.nonterminal(self, nt, args) - return rv - - def p_bp_location(self, args): - ''' - bp_start ::= opt_space location_if opt_space - ''' - - def p_list_range(self, args): - ''' - ## START HERE - range_start ::= opt_space range - range ::= location - range ::= location opt_space COMMA opt_space NUMBER - range ::= COMMA opt_space location - range ::= location opt_space COMMA - range ::= opt_space DIRECTION - ''' - - ########################################################## - # Expression grammar rules. Grammar rule functions - # start with the name p_ and are collected automatically - ########################################################## - def p_location(self, args): - ''' - opt_space ::= SPACE? - - location_if ::= location - location_if ::= location SPACE IF tokens - - # Note no space is allowed between FILENAME and NUMBER - location ::= FILENAME COLON NUMBER - location ::= FUNCNAME - - # In the below, the second FILENAME is really the word - # "line". We ferret this out in a reduction rule though. - location ::= FILENAME SPACE FILENAME SPACE NUMBER - - # If just a number is given, the the filename is implied - location ::= NUMBER - location ::= METHOD - - # For tokens we accept anything. Were really just - # going to use the underlying string from the part - # after "if". So below we all of the possible tokens - - tokens ::= token+ - token ::= FILENAME - token ::= FUNCNAME - token ::= COLON - token ::= NUMBER - token ::= COMMA - token ::= DIRECTION - token ::= SPACE - ''' - - def add_custom_rules(self, tokens, orig_customize): - self.check_reduce['location'] = 'tokens' - - def reduce_is_invalid(self, rule, ast, tokens, first, last): - if rule == ('location', ('FILENAME', 'SPACE', 'FILENAME', 'SPACE', 'NUMBER')): - # In this rule the 2nd filename should be 'line'. if not, the rule - # is invalid - return tokens[first+2].value != 'line' - return False - - -def parse_location(start_symbol, text, out=sys.stdout, - show_tokens=False, parser_debug=DEFAULT_DEBUG): - assert isinstance(text, str) - tokens = LocationScanner().tokenize(text) - if show_tokens: - for t in tokens: - print(t) - - # For heavy grammar debugging - # parser_debug = {'rules': True, 'transition': True, 'reduce': True, - # 'errorstack': True, 'dups': True} - # parser_debug = {'rules': False, 'transition': False, 'reduce': True, - # 'errorstack': True, 'dups': False} - parser_debug = {'rules': False, 'transition': False, 'reduce': True, - 'errorstack': True, 'dups': False} - - parser = LocationParser(start_symbol, text, parser_debug) - parser.check_grammar(frozenset(('bp_start', 'range_start'))) - parser.add_custom_rules(tokens, {}) - return parser.parse(tokens) - -def parse_bp_location(*args, **kwargs): - return parse_location('bp_start', *args, **kwargs) - -def parse_range(*args, **kwargs): - return parse_location('range_start', *args, **kwargs) - -if __name__ == '__main__': - # lines = """ - # /tmp/foo.py:12 - # '''/tmp/foo.py:12''' line 14 - # /tmp/foo.py line 12 - # '''/tmp/foo.py line 12''' line 25 - # 12 - # ../foo.py:5 - # gcd() - # foo.py line 5 if x > 1 - # """.splitlines() - # for line in lines: - # if not line.strip(): - # continue - # print("=" * 30) - # print(line) - # print("+" * 30) - # ast = parse_bp_location(line, show_tokens=True) - # print(ast) - - # bad_lines = """ - # /tmp/foo.py - # '''/tmp/foo.py''' - # /tmp/foo.py 12 - # /tmp/foo.py line - # gcd() - # foo.py if x > 1 - # """.splitlines() - # for line in bad_lines: - # if not line.strip(): - # continue - # print("=" * 30) - # print(line) - # print("+" * 30) - # try: - # ast = parse_bp_location(line, show_tokens=True) - # except: - # continue - # print(ast) - - lines = """ - 1 - 2, - ,3 - 4,10 - """.splitlines() - for line in lines: - if not line.strip(): - continue - print("=" * 30) - print(line) - print("+" * 30) - ast = parse_range(line, show_tokens=True) - print(ast) diff --git a/example/gdb-loc/gdbloc/tok.py b/example/gdb-loc/gdbloc/tok.py deleted file mode 100644 index 1839a8c..0000000 --- a/example/gdb-loc/gdbloc/tok.py +++ /dev/null @@ -1,46 +0,0 @@ -class Token: - """ - Class representing a token. - kind: the kind of token, e.g. filename, number, other - value: specific instance value, e.g. "/tmp/foo.c", or 5 - offset: byte offset from start of parse string - """ - def __init__(self, kind, value=None, offset=None): - self.offset = offset - self.kind = kind - self.value = value - - def __eq__(self, o): - """ '==', but it's okay if offset is different""" - if isinstance(o, Token): - # Both are tokens: compare kind and value - # It's okay if offsets are different - return (self.kind == o.kind) - else: - return self.kind == o - - def __repr__(self): - return str(self.kind) - - def __repr1__(self, indent, sib_num=''): - return self.format(line_prefix=indent, sib_num=sib_num) - - def __str__(self): - return self.format(line_prefix='') - - def format(self, line_prefix='', sib_num=None): - if sib_num: - sib_num = "%d." % sib_num - else: - sib_num = '' - prefix = ('%s%s' % (line_prefix, sib_num)) - offset_opname = '%5s %-10s' % (self.offset, self.kind) - if not self.value: - return "%s%s" % (prefix, offset_opname) - return "%s%s %s" % (prefix, offset_opname, self.value) - - def __hash__(self): - return hash(self.kind) - - def __getitem__(self, i): - raise IndexError diff --git a/example/gdb-loc/pytest/test_parser.py b/example/gdb-loc/pytest/test_parser.py deleted file mode 100644 index 9b78113..0000000 --- a/example/gdb-loc/pytest/test_parser.py +++ /dev/null @@ -1,43 +0,0 @@ -import os.path as osp -import sys -mydir = osp.normpath(osp.dirname('__file__')) -sys.path.append(osp.normpath(osp.join(mydir, '..', '..'))) -from gdbloc.parser import parse_bp_location - -def test_parser(): - for s, expect in ( - ("/tmp/foo.py:12", - ((0, 'FILENAME', '/tmp/foo.py'), (11, 'COLON', None), (12, 'NUMBER', 12),)), - ('''/tmp/foo.py:12''', - ((0, 'FILENAME', '/tmp/foo.py'), (11, 'COLON', None), (12, 'NUMBER', 12),)), - ("/tmp/foo.py line 12", - ((0, 'FILENAME', "/tmp/foo.py's"), - (11, 'SPACE', ' '), - (12, 'FILENAME', "line"), - (16, 'SPACE', ' '), - (17, 'NUMBER', 12),)), - ("12", - ((17, 'NUMBER', 12),)), - ('../foo.py:5', - ((0, 'FILENAME', '../foo.py'), (9, 'COLON', ':'), (10, 'NUMBER', 5),)), - ('gcd()', - ((0, 'FUNCNAME', 'gcd()'),)), - ('foo.py line 5 if x > 1', - ((0, 'FILENAME', 'foo.py'), - (6, 'SPACE', ' '), - (7, 'FILENAME', 'line'), - (11, 'SPACE', ' '), - (12, 'NUMBER', 5), - (13, 'SPACE', ' '), - (14, 'IF', 'if'), - (16, 'SPACE', ' '), - (17, 'FILENAME', 'x'), - (18, 'SPACE', ' '), - (19, 'FILENAME', '>'), - (20, 'SPACE', ' '), - (21, 'NUMBER', 1),)), - ): - ast = parse_bp_location(s, show_tokens=True) - print(ast) - assert ast - pass diff --git a/example/gdb-loc/pytest/test_scanner.py b/example/gdb-loc/pytest/test_scanner.py deleted file mode 100644 index 450a5a4..0000000 --- a/example/gdb-loc/pytest/test_scanner.py +++ /dev/null @@ -1,58 +0,0 @@ -import os.path as osp -import sys -mydir = osp.normpath(osp.dirname('__file__')) -sys.path.append(osp.normpath(osp.join(mydir, '..', '..'))) -from gdbloc.scanner import LocationScanner -from gdbloc.tok import Token - -def test_scanner(): - for s, expect in ( - ("/tmp/foo.py:12", - ((0, 'FILENAME', '/tmp/foo.py'), (11, 'COLON', None), (12, 'NUMBER', 12),)), - ('''/tmp/foo.py:12''', - ((0, 'FILENAME', '/tmp/foo.py'), (11, 'COLON', None), (12, 'NUMBER', 12),)), - ("/tmp/foo.py line 12", - ((0, 'FILENAME', "/tmp/foo.py's"), - (11, 'SPACE', ' '), - (12, 'FILENAME', "line"), - (16, 'SPACE', ' '), - (17, 'NUMBER', 12),)), - ('../foo.py:5', - ((0, 'FILENAME', '../foo.py'), (9, 'COLON', ':'), (10, 'NUMBER', 5),)), - ('gcd()', - ((0, 'FUNCNAME', 'gcd()'),)), - ('foo.py line 5 if x > 1', - ((0, 'FILENAME', 'foo.py'), - (6, 'SPACE', ' '), - (7, 'FILENAME', 'line'), - (11, 'SPACE', ' '), - (12, 'NUMBER', 5), - (13, 'SPACE', ' '), - (14, 'IF', 'if'), - (16, 'SPACE', ' '), - (17, 'FILENAME', 'x'), - (18, 'SPACE', ' '), - (19, 'FILENAME', '>'), - (20, 'SPACE', ' '), - (21, 'NUMBER', 1),)), - ('11', - ((0, 'NUMBER', 11), )), - ('2 ,', - ((0, 'NUMBER', 2), - (1, 'SPACE', ' '), - (2, 'COMMA', ','),)), - (',3', - ((0, 'COMMA', ','), - (1, 'NUMBER', '3'),)), - ('4,10', - ((0, 'NUMBER', 4), - (1, 'COMMA', ','), - (2, 'NUMBER', 10),)), - ): - tokens = LocationScanner().tokenize(s) - for i, t in enumerate(tokens): - e = Token(kind=expect[i][1], value=expect[i][2], offset=expect[i][0]) - assert t == e, i - print(t) - pass - pass diff --git a/example/gdb-loc/pytest/test_semantics.py b/example/gdb-loc/pytest/test_semantics.py deleted file mode 100644 index d983c34..0000000 --- a/example/gdb-loc/pytest/test_semantics.py +++ /dev/null @@ -1,35 +0,0 @@ -import os.path as osp -import sys -mydir = osp.normpath(osp.dirname('__file__')) -sys.path.append(osp.normpath(osp.join(mydir, '..', '..'))) -from gdbloc.semantics import build_range, build_bp_expr, ListRange, Location, BPLocation - -def test_semantics(): - for s, expect in ( - ("-", - ListRange(first='.', last='-')), - ("+", - ListRange(first='.', last='+')), - ("/tmp/foo.py:12", - ListRange(first=Location(path='/tmp/foo.py', line_number=12, method=None), last='.')), - (", 5", - ListRange(first='.', last=Location(path=None, line_number=5, method=None))), - (", foo.py:14", - ListRange(first='.', last=Location(path='foo.py', line_number=14, method=None))), - ): - list_range = build_range(s) - # print(list_range) - assert list_range == expect - pass - for s, expect in ( - ("/tmp/foo.py:13", - BPLocation(Location(path='/tmp/foo.py', line_number=13, method=None), - condition=None)), - ("/tmp/foo.py:9 if x > 1", - BPLocation(Location(path='/tmp/foo.py', line_number=9, method=None), - condition='if x > 1')), - ): - bp_expr = build_bp_expr(s) - # print(bp_expr) - assert bp_expr == expect - pass diff --git a/example/gdb-loc/setup.py b/example/gdb-loc/setup.py deleted file mode 100644 index 2826ffb..0000000 --- a/example/gdb-loc/setup.py +++ /dev/null @@ -1,7 +0,0 @@ -from setuptools import setup -setup( - description = "gdb location example", - install_requires = ['spark_parser >= 1.7.0'], - name = 'gdbloc', - version = '1.0' -) diff --git a/setup.py b/setup.py index 7c79e33..357187a 100755 --- a/setup.py +++ b/setup.py @@ -14,79 +14,7 @@ Copyright (C) 2016-2017, 2022, 2024 Rocky Bernstein . """ -from setuptools import setup -classifiers = [ - "Development Status :: 5 - Production/Stable", - 'Intended Audience :: Developers', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2.4', - 'Programming Language :: Python :: 2.5', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: 3.12', - 'Topic :: Software Development :: Code Generators', - 'Topic :: Software Development :: Compilers ', - 'Topic :: Software Development :: Libraries :: Python Modules', - ] -# The rest in alphabetic order -author = "John Aycock" -ftp_url = None -license = 'MIT' -maintainer = "Rocky Bernstein" -maintainer_email = "rb@dustyfeet.com" -modname = 'spark_parser' -name = 'spark_parser' -py_modules = None -short_desc = 'An Earley-Algorithm Context-free grammar Parser Toolkit' -web = 'https://github.com/rocky/python-spark/' - -# tracebacks in zip files are funky and not debuggable -zip_safe = True - -import os -def get_srcdir(): - filename = os.path.normcase(os.path.dirname(os.path.abspath(__file__))) - return os.path.realpath(filename) - -srcdir = get_srcdir() - -def read(*rnames): - return open(os.path.join(srcdir, *rnames)).read() - -# Get info from files; set: long_description and VERSION -long_description = ( read("README.rst") + '\n' ) -exec(read('spark_parser/version.py')) - from setuptools import setup, find_packages -setup( - classifiers = classifiers, - description = short_desc, - # install_requires = install_requires, - license = license, - long_description = long_description, - long_description_content_type = "text/x-rst", - maintainer = maintainer, - maintainer_email = maintainer_email, - packages = find_packages(), - py_modules = py_modules, - name = name, - scripts = ['bin/spark-parser-coverage'], - test_suite = 'nose.collector', - url = web, - tests_require = ['nose>=1.0'], - version = __version__, - zip_safe = zip_safe -======= classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", @@ -158,17 +86,10 @@ def read(*rnames): import sys -if (3, 0) <= sys.version_info[:2] <= (3, 2): - click_version = "<= 4.0" -else: - click_version = "" - -from setuptools import find_packages, setup - setup( classifiers=classifiers, description=short_desc, - install_requires=["click%s" % click_version], + install_requires=[], license=license, long_description=long_description, long_description_content_type="text/x-rst", @@ -183,5 +104,4 @@ def read(*rnames): tests_require=["nose>=1.0"], version=__version__, zip_safe=zip_safe, ->>>>>>> python-3.0-to-3.2 ) From a937aca481f7c0e235f3e7f2b288b79d4b879bff Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 8 Oct 2024 08:08:49 -0400 Subject: [PATCH 31/40] Go over make dist scripts --- admin-tools/make-dist-2.4-2.7.sh | 55 ++++++++++++++++++++++++++++++++ admin-tools/make-dist-older.sh | 39 ---------------------- 2 files changed, 55 insertions(+), 39 deletions(-) create mode 100755 admin-tools/make-dist-2.4-2.7.sh delete mode 100755 admin-tools/make-dist-older.sh diff --git a/admin-tools/make-dist-2.4-2.7.sh b/admin-tools/make-dist-2.4-2.7.sh new file mode 100755 index 0000000..6946b69 --- /dev/null +++ b/admin-tools/make-dist-2.4-2.7.sh @@ -0,0 +1,55 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_24_owd +} +make_spark_dist_24_owd=$(pwd) +trap finish EXIT + +cd $(dirname ${BASH_SOURCE[0]}) +if ! source ./pyenv-2.4-2.7-versions ; then + exit $? +fi +if ! source ./setup-python-2.4.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + + rm -fr build + python setup.py bdist_egg + echo === $pyversion === +done + +echo "--- python 2.7 wheel ---" +pyenv local 2.7.18 +python setup.py bdist_wheel +echo === $pyversion === + +# PyPI can only have one source tarball. +# Tarballs can get created from the above setup, so make sure to remove them since we want +# the tarball from master. + +tarball=dist/${PACKAGE}-$__version__-tar.gz +if [[ -f $tarball ]]; then + rm -v dist/${PACKAGE}-$__version__-tar.gz +fi +finish diff --git a/admin-tools/make-dist-older.sh b/admin-tools/make-dist-older.sh deleted file mode 100755 index e9eafa6..0000000 --- a/admin-tools/make-dist-older.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -PACKAGE=spark_parser - -# FIXME put some of the below in a common routine -function finish { - cd $owd -} -owd=$(pwd) -trap finish EXIT - -cd $(dirname ${BASH_SOURCE[0]}) -if ! source ./pyenv-older-versions ; then - exit $? -fi -if ! source ./setup-python-2.4.sh ; then - exit $? -fi - -cd .. -source $PACKAGE/version.py -echo $VERSION - -for pyversion in $PYVERSIONS; do - if ! pyenv local $pyversion ; then - exit $? - fi - - rm -fr build - python setup.py bdist_egg -done - -# Pypi can only have one source tarball. -# Tarballs can get created from the above setup, so make sure to remove them since we want -# the tarball from master. - -tarball=dist/${PACKAGE}-$VERSION-tar.gz -if [[ -f $tarball ]]; then - rm -v dist/${PACKAGE}-$VERSION-tar.gz -fi From ed184222d2930ea5c63f00874600dfbce5c0f464 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 8 Oct 2024 07:44:40 -0400 Subject: [PATCH 32/40] Get ready for release 1.9.0. --- .gitignore | 5 +- .pre-commit-config.yaml | 2 +- ChangeLog-spell-corrected.diff | 155 +++++++++++++++++++++++++++++++++ NEWS.md | 21 ++++- admin-tools/make-dist-older.sh | 39 --------- 5 files changed, 176 insertions(+), 46 deletions(-) create mode 100644 ChangeLog-spell-corrected.diff delete mode 100755 admin-tools/make-dist-older.sh diff --git a/.gitignore b/.gitignore index ed75d30..9b7393b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ *.pyc *~ +.cache /.eggs /.python-version /.tox +/ChangeLog +/ChangeLog-spell-corrected /build /dist /how-to-make-a-release.txt @@ -10,5 +13,3 @@ /spark3_parser.egg-info /spark_parser.egg-info /tmp -.cache -/ChangeLog diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 675d793..b3dc0e6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,4 +21,4 @@ repos: - id: black language_version: python3 stages: [commit] - exclude: 'trepan/version.py' + exclude: 'spark_parser/version.py' diff --git a/ChangeLog-spell-corrected.diff b/ChangeLog-spell-corrected.diff new file mode 100644 index 0000000..d00bde2 --- /dev/null +++ b/ChangeLog-spell-corrected.diff @@ -0,0 +1,155 @@ +--- ChangeLog 2024-10-08 07:34:12.955418050 -0400 ++++ ChangeLog-spell-corrected 2024-10-08 07:35:49.302374064 -0400 +@@ -156,7 +156,7 @@ + * admin-tools/{check-older-versions.sh => + check-2.4-2.7-versions.sh}, admin-tools/check-3.3-3.5-versions.sh, + admin-tools/check-3.6-3.10-versions.sh, +- admin-tools/{check-newer-versions.sh => check-newest-versions.sh}: ++ admin-tools/{check-newer-versions.sh => check-newest-versions.sh}: + Administrivia: Add check programs + + 2024-10-04 rocky +@@ -188,7 +188,7 @@ + admin-tools/pyenv-3.3-3.5-versions, + admin-tools/pyenv-3.6-3.10-versions, admin-tools/setup-master.sh, + admin-tools/setup-python-3.0.sh, admin-tools/setup-python-3.3.sh, +- admin-tools/setup-python-3.6.sh: Start separting code into verison ++ admin-tools/setup-python-3.6.sh: Start separating code into version + branches + + 2024-10-02 gdesmar <75089569+gdesmar@users.noreply.github.com> +@@ -215,11 +215,11 @@ + + 2023-05-29 rocky + +- * spark_parser/spark.py: lint a litle bit ++ * spark_parser/spark.py: lint a little bit + + 2022-03-09 rocky + +- * spark_parser/__init__.py, test/test_grammar.py, test/test_misc.py: ++ * spark_parser/__init__.py, test/test_grammar.py, test/test_misc.py: + __init__.py lint + + 2022-02-11 rocky +@@ -290,7 +290,7 @@ + + 2019-11-16 rocky + +- * admin-tools/pyenv-newer-versions, admin-tools/setup-master.sh: ++ * admin-tools/pyenv-newer-versions, admin-tools/setup-master.sh: + Administriva - bump testing versions + + 2019-11-16 rocky +@@ -404,7 +404,7 @@ + 2018-03-28 rocky + + * bin/spark-parser-coverage: Canonicalize to reduce false-positive +- unused rules Specifically we remove the epsilon transition marks. Note we don't bother doing this for all rules, just the unsed ones ++ unused rules Specifically we remove the epsilon transition marks. Note we don't bother doing this for all rules, just the unused ones + + 2018-02-18 rocky + +@@ -428,7 +428,7 @@ + + 2017-12-07 rocky + +- * test/test_misc.py: Python 2.6 compatability ++ * test/test_misc.py: Python 2.6 compatibility + + 2017-12-07 rocky + +@@ -491,7 +491,7 @@ + + * example/gdb-loc/gdbloc/semantics.py, + example/python2/py2_format.py, spark_parser/spark.py, +- test/test_checker.py, test/test_grammar.py, test/test_spark.py: ++ test/test_checker.py, test/test_grammar.py, test/test_spark.py: + Check for rules with the same non-nul RHS + + 2017-11-16 rocky +@@ -546,7 +546,7 @@ + 2017-10-24 rocky + + * ChangeLog, NEWS, example/gdb-loc/gdbloc/semantics.py, +- example/gdb-loc/pytest/test_semantics.py, spark_parser/version.py: ++ example/gdb-loc/pytest/test_semantics.py, spark_parser/version.py: + Get ready for release 1.7.1 + + 2017-10-24 rocky +@@ -559,14 +559,14 @@ + example/gdb-loc/gdbloc/scanner.py, + example/gdb-loc/gdbloc/semantics.py, + example/gdb-loc/pytest/test_parser.py, +- example/gdb-loc/pytest/test_semantics.py, spark_parser/spark.py: ++ example/gdb-loc/pytest/test_semantics.py, spark_parser/spark.py: + parser: handle errorstack better; better gdbloc + + 2017-10-12 rocky + + * example/README.md, example/expr2/eval.py, + example/expr2/{parser.py => expr_parser.py}, +- example/expr2/test_grammar.py, example/python2/py2_format.py: ++ example/expr2/test_grammar.py, example/python2/py2_format.py: + Improve examples. + + 2017-10-12 rocky +@@ -615,7 +615,7 @@ + + * example/gdb-loc/README.md, example/gdb-loc/gdbloc/parser.py, + example/gdb-loc/gdbloc/scanner.py, +- example/gdb-loc/gdbloc/semantics.py: Pretty much coplete the gdbloc ++ example/gdb-loc/gdbloc/semantics.py: Pretty much complete the gdbloc + example Now I just need to add it to trepan2 and trepan3k... + + 2017-10-08 rocky +@@ -801,7 +801,7 @@ + + 2017-01-28 rocky + +- * spark_parser/spark.py, test/test_spark.py: Banc on coverage a ++ * spark_parser/spark.py, test/test_spark.py: Bang on coverage a + little more + + 2017-01-28 rocky +@@ -957,7 +957,7 @@ + 2016-11-22 rocky + + * example/python2/test/helper.py, spark_parser/spark.py: Fix bug +- introdoced in last release... guard agains self.debug == None Reinstate "with ..." will handle 2.4-2.5 in a branch ++ introdoced in last release... guard against self.debug == None Reinstate "with ..." will handle 2.4-2.5 in a branch + + 2016-11-21 rocky + +@@ -1043,7 +1043,7 @@ + example/python2/test/parse/exec.right, + example/python2/test/parse/if.right, + example/python2/test/parse/imports.right, +- example/python2/test/parse/while.right: Python 2 start Handlin '==' ++ example/python2/test/parse/while.right: Python 2 start Handling '==' + and subscripts + + 2016-06-12 rocky +@@ -1090,7 +1090,7 @@ + 2016-06-10 rocky + + * example/python2/py2_format.py, example/python2/py2_parser.py, +- example/python2/py2_scan.py, example/python2/test/format/expr.right: ++ example/python2/py2_scan.py, example/python2/test/format/expr.right: + Almost all of the grammar added. py2_scan.py: add "and" and "or" reserved words + + 2016-06-10 rocky +@@ -1447,7 +1447,7 @@ + 2016-04-28 rocky + + * NEWS, example/expr/expr.py, setup.py, spark/__init__.py, +- spark/ast.py, spark/scanner.py, spark/spark.py, test/test_spark.py: ++ spark/ast.py, spark/scanner.py, spark/spark.py, test/test_spark.py: + Get ready for release 1.0.2 + + 2016-04-27 rocky +@@ -1539,4 +1539,3 @@ + 2016-04-20 rocky + + * Initial guess at Spark package +- diff --git a/NEWS.md b/NEWS.md index af98197..4c727e4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,18 @@ +1.9.0 2024-10-8 Has it been that long? +====================================== + +Revamp for more modern Python style in the 3.12 era: + - start adding type annotations to code. + - use pyproject.toml + - remove illegal escape sequences + +BuildTree now builds trees iteratively rather than recursively. With this we can handle larger trees which are needed in the decompielrs. + +Revise README.rst for above and go over spelling and grammar + +Internally, more git branches have been created to supoprt older Python. + + 1.8.9 2018-07-28 S ====================================== @@ -16,9 +31,7 @@ 1.8.6 2018-04-06 ================ -* spark-parser-coverage: Canonicalize to reduce false-positive - unused rules. Specifically we remove epsilon - transition marks +* spark-parser-coverage: Canonicalize to reduce false-positive unused rules. Specifically we remove epsilon transition marks 1.8.5 2017-12-10 Dr Gecko @@ -28,7 +41,7 @@ Those are nonterminals used in *, +, and ? rules * example/python2/py2_parser.py: Pull constant out of nonterminal function -* test/test_misc.py: Python 2.6 compatability +* test/test_misc.py: Python 2.6 compatibility * example/gdb-loc/README.md, example/python2/README.md, example/python2/format-python.py, spark_parser/spark.py, test/test_misc.py: Create set of list-like nonterminals diff --git a/admin-tools/make-dist-older.sh b/admin-tools/make-dist-older.sh deleted file mode 100755 index e9eafa6..0000000 --- a/admin-tools/make-dist-older.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -PACKAGE=spark_parser - -# FIXME put some of the below in a common routine -function finish { - cd $owd -} -owd=$(pwd) -trap finish EXIT - -cd $(dirname ${BASH_SOURCE[0]}) -if ! source ./pyenv-older-versions ; then - exit $? -fi -if ! source ./setup-python-2.4.sh ; then - exit $? -fi - -cd .. -source $PACKAGE/version.py -echo $VERSION - -for pyversion in $PYVERSIONS; do - if ! pyenv local $pyversion ; then - exit $? - fi - - rm -fr build - python setup.py bdist_egg -done - -# Pypi can only have one source tarball. -# Tarballs can get created from the above setup, so make sure to remove them since we want -# the tarball from master. - -tarball=dist/${PACKAGE}-$VERSION-tar.gz -if [[ -f $tarball ]]; then - rm -v dist/${PACKAGE}-$VERSION-tar.gz -fi From f9770ca582cc200006d6c18be89710e71f503a09 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 8 Oct 2024 07:44:40 -0400 Subject: [PATCH 33/40] Get ready for release 1.9.0. --- admin-tools/make-dist-2.4-2.7.sh | 55 ++++++++++++++++++++++++++++ admin-tools/make-dist-3.0-3.2.sh | 62 ++++++++++++++++++++++++++++++++ admin-tools/make-dist-older.sh | 39 -------------------- admin-tools/pyenv-newer-versions | 6 ---- spark_parser/version.py | 2 +- 5 files changed, 118 insertions(+), 46 deletions(-) create mode 100644 admin-tools/make-dist-2.4-2.7.sh create mode 100644 admin-tools/make-dist-3.0-3.2.sh delete mode 100755 admin-tools/make-dist-older.sh delete mode 100644 admin-tools/pyenv-newer-versions diff --git a/admin-tools/make-dist-2.4-2.7.sh b/admin-tools/make-dist-2.4-2.7.sh new file mode 100644 index 0000000..6946b69 --- /dev/null +++ b/admin-tools/make-dist-2.4-2.7.sh @@ -0,0 +1,55 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_24_owd +} +make_spark_dist_24_owd=$(pwd) +trap finish EXIT + +cd $(dirname ${BASH_SOURCE[0]}) +if ! source ./pyenv-2.4-2.7-versions ; then + exit $? +fi +if ! source ./setup-python-2.4.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + + rm -fr build + python setup.py bdist_egg + echo === $pyversion === +done + +echo "--- python 2.7 wheel ---" +pyenv local 2.7.18 +python setup.py bdist_wheel +echo === $pyversion === + +# PyPI can only have one source tarball. +# Tarballs can get created from the above setup, so make sure to remove them since we want +# the tarball from master. + +tarball=dist/${PACKAGE}-$__version__-tar.gz +if [[ -f $tarball ]]; then + rm -v dist/${PACKAGE}-$__version__-tar.gz +fi +finish diff --git a/admin-tools/make-dist-3.0-3.2.sh b/admin-tools/make-dist-3.0-3.2.sh new file mode 100644 index 0000000..8ac4ef3 --- /dev/null +++ b/admin-tools/make-dist-3.0-3.2.sh @@ -0,0 +1,62 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_30_owd +} + +make_spark_dist_30_owd=$(pwd) +cd $(dirname ${BASH_SOURCE[0]}) +trap finish EXIT + +if ! source ./pyenv-3.0-3.2-versions ; then + exit $? +fi +if ! source ./setup-python-3.0.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + # pip bdist_egg create too-general wheels. So + # we narrow that by moving the generated wheel. + + # Pick out first two numbers of version, e.g. 3.5.1 -> 35 + first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') + rm -fr build + python setup.py bdist_egg bdist_wheel + if [[ $first_two =~ py* ]]; then + if [[ $first_two =~ pypy* ]]; then + # For PyPy, remove the what is after the dash, e.g. pypy37-none-any.whl instead of pypy37-7-none-any.whl + first_two=${first_two%-*} + fi + mv -v dist/${PACKAGE}-$__version__-{py3,$first_two}-none-any.whl + else + mv -v dist/${PACKAGE}-$__version__-{py3,py$first_two}-none-any.whl + fi + echo === $pyversion === +done + +python ./setup.py sdist + +tarball=dist/${PACKAGE}-${__version__}.tar.gz +if [[ -f $tarball ]]; then + mv -v $tarball dist/${PACKAGE}_31-${__version__}.tar.gz +fi +finish diff --git a/admin-tools/make-dist-older.sh b/admin-tools/make-dist-older.sh deleted file mode 100755 index e9eafa6..0000000 --- a/admin-tools/make-dist-older.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -PACKAGE=spark_parser - -# FIXME put some of the below in a common routine -function finish { - cd $owd -} -owd=$(pwd) -trap finish EXIT - -cd $(dirname ${BASH_SOURCE[0]}) -if ! source ./pyenv-older-versions ; then - exit $? -fi -if ! source ./setup-python-2.4.sh ; then - exit $? -fi - -cd .. -source $PACKAGE/version.py -echo $VERSION - -for pyversion in $PYVERSIONS; do - if ! pyenv local $pyversion ; then - exit $? - fi - - rm -fr build - python setup.py bdist_egg -done - -# Pypi can only have one source tarball. -# Tarballs can get created from the above setup, so make sure to remove them since we want -# the tarball from master. - -tarball=dist/${PACKAGE}-$VERSION-tar.gz -if [[ -f $tarball ]]; then - rm -v dist/${PACKAGE}-$VERSION-tar.gz -fi diff --git a/admin-tools/pyenv-newer-versions b/admin-tools/pyenv-newer-versions deleted file mode 100644 index b5c4ed6..0000000 --- a/admin-tools/pyenv-newer-versions +++ /dev/null @@ -1,6 +0,0 @@ -# -*- shell-script -*- -if [[ $0 == ${BASH_SOURCE[0]} ]] ; then - echo "This script should be *sourced* rather than run directly through bash" - exit 1 -fi -export PYVERSIONS='3.5.9 3.6.9 2.6.9 3.3.7 2.7.17 3.2.6 3.1.5 3.4.10 3.7.6 3.8.18, 3.11.7 3.12.1' diff --git a/spark_parser/version.py b/spark_parser/version.py index 80a4dd7..c66b9ae 100644 --- a/spark_parser/version.py +++ b/spark_parser/version.py @@ -4,4 +4,4 @@ # This file should define a variable VERSION which we use as the # package version number. -__version__ = "1.9.0" # noqa +__version__="1.9.0" # noqa From 7680ee5abd0c91cdb61a91508b6def5617d64f85 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 8 Oct 2024 07:44:40 -0400 Subject: [PATCH 34/40] Get ready for release 1.9.0. --- admin-tools/make-dist-2.4-2.7.sh | 55 ++++++++++++++++++++++++++++ admin-tools/make-dist-3.0-3.2.sh | 62 ++++++++++++++++++++++++++++++++ admin-tools/pyenv-newer-versions | 6 ---- 3 files changed, 117 insertions(+), 6 deletions(-) create mode 100755 admin-tools/make-dist-2.4-2.7.sh create mode 100755 admin-tools/make-dist-3.0-3.2.sh delete mode 100644 admin-tools/pyenv-newer-versions diff --git a/admin-tools/make-dist-2.4-2.7.sh b/admin-tools/make-dist-2.4-2.7.sh new file mode 100755 index 0000000..6946b69 --- /dev/null +++ b/admin-tools/make-dist-2.4-2.7.sh @@ -0,0 +1,55 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_24_owd +} +make_spark_dist_24_owd=$(pwd) +trap finish EXIT + +cd $(dirname ${BASH_SOURCE[0]}) +if ! source ./pyenv-2.4-2.7-versions ; then + exit $? +fi +if ! source ./setup-python-2.4.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + + rm -fr build + python setup.py bdist_egg + echo === $pyversion === +done + +echo "--- python 2.7 wheel ---" +pyenv local 2.7.18 +python setup.py bdist_wheel +echo === $pyversion === + +# PyPI can only have one source tarball. +# Tarballs can get created from the above setup, so make sure to remove them since we want +# the tarball from master. + +tarball=dist/${PACKAGE}-$__version__-tar.gz +if [[ -f $tarball ]]; then + rm -v dist/${PACKAGE}-$__version__-tar.gz +fi +finish diff --git a/admin-tools/make-dist-3.0-3.2.sh b/admin-tools/make-dist-3.0-3.2.sh new file mode 100755 index 0000000..8ac4ef3 --- /dev/null +++ b/admin-tools/make-dist-3.0-3.2.sh @@ -0,0 +1,62 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_30_owd +} + +make_spark_dist_30_owd=$(pwd) +cd $(dirname ${BASH_SOURCE[0]}) +trap finish EXIT + +if ! source ./pyenv-3.0-3.2-versions ; then + exit $? +fi +if ! source ./setup-python-3.0.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + # pip bdist_egg create too-general wheels. So + # we narrow that by moving the generated wheel. + + # Pick out first two numbers of version, e.g. 3.5.1 -> 35 + first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') + rm -fr build + python setup.py bdist_egg bdist_wheel + if [[ $first_two =~ py* ]]; then + if [[ $first_two =~ pypy* ]]; then + # For PyPy, remove the what is after the dash, e.g. pypy37-none-any.whl instead of pypy37-7-none-any.whl + first_two=${first_two%-*} + fi + mv -v dist/${PACKAGE}-$__version__-{py3,$first_two}-none-any.whl + else + mv -v dist/${PACKAGE}-$__version__-{py3,py$first_two}-none-any.whl + fi + echo === $pyversion === +done + +python ./setup.py sdist + +tarball=dist/${PACKAGE}-${__version__}.tar.gz +if [[ -f $tarball ]]; then + mv -v $tarball dist/${PACKAGE}_31-${__version__}.tar.gz +fi +finish diff --git a/admin-tools/pyenv-newer-versions b/admin-tools/pyenv-newer-versions deleted file mode 100644 index b5c4ed6..0000000 --- a/admin-tools/pyenv-newer-versions +++ /dev/null @@ -1,6 +0,0 @@ -# -*- shell-script -*- -if [[ $0 == ${BASH_SOURCE[0]} ]] ; then - echo "This script should be *sourced* rather than run directly through bash" - exit 1 -fi -export PYVERSIONS='3.5.9 3.6.9 2.6.9 3.3.7 2.7.17 3.2.6 3.1.5 3.4.10 3.7.6 3.8.18, 3.11.7 3.12.1' From ce2135dab547cbb190321235620c33a6f68539d0 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 8 Oct 2024 07:44:40 -0400 Subject: [PATCH 35/40] Get ready for release 1.9.0. --- admin-tools/make-dist-2.4-2.7.sh | 55 +++++++++++++++++++++++++++ admin-tools/make-dist-3.0-3.2.sh | 62 +++++++++++++++++++++++++++++++ admin-tools/make-dist-3.3-3.5.sh | 62 +++++++++++++++++++++++++++++++ admin-tools/make-dist-3.6-3.10.sh | 62 +++++++++++++++++++++++++++++++ admin-tools/pyenv-newer-versions | 6 --- 5 files changed, 241 insertions(+), 6 deletions(-) create mode 100755 admin-tools/make-dist-2.4-2.7.sh create mode 100755 admin-tools/make-dist-3.0-3.2.sh create mode 100755 admin-tools/make-dist-3.3-3.5.sh create mode 100755 admin-tools/make-dist-3.6-3.10.sh delete mode 100644 admin-tools/pyenv-newer-versions diff --git a/admin-tools/make-dist-2.4-2.7.sh b/admin-tools/make-dist-2.4-2.7.sh new file mode 100755 index 0000000..6946b69 --- /dev/null +++ b/admin-tools/make-dist-2.4-2.7.sh @@ -0,0 +1,55 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_24_owd +} +make_spark_dist_24_owd=$(pwd) +trap finish EXIT + +cd $(dirname ${BASH_SOURCE[0]}) +if ! source ./pyenv-2.4-2.7-versions ; then + exit $? +fi +if ! source ./setup-python-2.4.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + + rm -fr build + python setup.py bdist_egg + echo === $pyversion === +done + +echo "--- python 2.7 wheel ---" +pyenv local 2.7.18 +python setup.py bdist_wheel +echo === $pyversion === + +# PyPI can only have one source tarball. +# Tarballs can get created from the above setup, so make sure to remove them since we want +# the tarball from master. + +tarball=dist/${PACKAGE}-$__version__-tar.gz +if [[ -f $tarball ]]; then + rm -v dist/${PACKAGE}-$__version__-tar.gz +fi +finish diff --git a/admin-tools/make-dist-3.0-3.2.sh b/admin-tools/make-dist-3.0-3.2.sh new file mode 100755 index 0000000..8ac4ef3 --- /dev/null +++ b/admin-tools/make-dist-3.0-3.2.sh @@ -0,0 +1,62 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_30_owd +} + +make_spark_dist_30_owd=$(pwd) +cd $(dirname ${BASH_SOURCE[0]}) +trap finish EXIT + +if ! source ./pyenv-3.0-3.2-versions ; then + exit $? +fi +if ! source ./setup-python-3.0.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + # pip bdist_egg create too-general wheels. So + # we narrow that by moving the generated wheel. + + # Pick out first two numbers of version, e.g. 3.5.1 -> 35 + first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') + rm -fr build + python setup.py bdist_egg bdist_wheel + if [[ $first_two =~ py* ]]; then + if [[ $first_two =~ pypy* ]]; then + # For PyPy, remove the what is after the dash, e.g. pypy37-none-any.whl instead of pypy37-7-none-any.whl + first_two=${first_two%-*} + fi + mv -v dist/${PACKAGE}-$__version__-{py3,$first_two}-none-any.whl + else + mv -v dist/${PACKAGE}-$__version__-{py3,py$first_two}-none-any.whl + fi + echo === $pyversion === +done + +python ./setup.py sdist + +tarball=dist/${PACKAGE}-${__version__}.tar.gz +if [[ -f $tarball ]]; then + mv -v $tarball dist/${PACKAGE}_31-${__version__}.tar.gz +fi +finish diff --git a/admin-tools/make-dist-3.3-3.5.sh b/admin-tools/make-dist-3.3-3.5.sh new file mode 100755 index 0000000..efdba80 --- /dev/null +++ b/admin-tools/make-dist-3.3-3.5.sh @@ -0,0 +1,62 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_33_owd +} + +make_spark_dist_33_owd=$(pwd) +cd $(dirname ${BASH_SOURCE[0]}) +trap finish EXIT + +if ! source ./pyenv-3.3-3.5-versions ; then + exit $? +fi +if ! source ./setup-python-3.3.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + # pip bdist_egg create too-general wheels. So + # we narrow that by moving the generated wheel. + + # Pick out first two numbers of version, e.g. 3.5.1 -> 35 + first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') + rm -fr build + python setup.py bdist_egg bdist_wheel + if [[ $first_two =~ py* ]]; then + if [[ $first_two =~ pypy* ]]; then + # For PyPy, remove the what is after the dash, e.g. pypy37-none-any.whl instead of pypy37-7-none-any.whl + first_two=${first_two%-*} + fi + mv -v dist/${PACKAGE}-$__version__-{py3,$first_two}-none-any.whl + else + mv -v dist/${PACKAGE}-$__version__-{py3,py$first_two}-none-any.whl + fi + echo === $pyversion === +done + +python ./setup.py sdist + +tarball=dist/${PACKAGE}-${__version__}.tar.gz +if [[ -f $tarball ]]; then + mv -v $tarball dist/${PACKAGE}_33-${__version__}.tar.gz +fi +finish diff --git a/admin-tools/make-dist-3.6-3.10.sh b/admin-tools/make-dist-3.6-3.10.sh new file mode 100755 index 0000000..6f591b4 --- /dev/null +++ b/admin-tools/make-dist-3.6-3.10.sh @@ -0,0 +1,62 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_36_owd +} + +cd $(dirname ${BASH_SOURCE[0]}) +make_spark_dist_36_owd=$(pwd) +trap finish EXIT + +if ! source ./pyenv-3.6-3.10-versions ; then + exit $? +fi +if ! source ./setup-python-3.6.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + # pip bdist_egg create too-general wheels. So + # we narrow that by moving the generated wheel. + + # Pick out first two numbers of version, e.g. 3.5.1 -> 35 + first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') + rm -fr build + python setup.py bdist_egg bdist_wheel + if [[ $first_two =~ py* ]]; then + if [[ $first_two =~ pypy* ]]; then + # For PyPy, remove the what is after the dash, e.g. pypy37-none-any.whl instead of pypy37-7-none-any.whl + first_two=${first_two%-*} + fi + mv -v dist/${PACKAGE}-$__version__-{py3,$first_two}-none-any.whl + else + mv -v dist/${PACKAGE}-$__version__-{py3,py$first_two}-none-any.whl + fi + echo === $pyversion === +done + +python ./setup.py sdist + +tarball=dist/${PACKAGE}-${__version__}.tar.gz +if [[ -f $tarball ]]; then + mv -v $tarball dist/${PACKAGE}_36-${__version__}.tar.gz +fi +finish diff --git a/admin-tools/pyenv-newer-versions b/admin-tools/pyenv-newer-versions deleted file mode 100644 index b5c4ed6..0000000 --- a/admin-tools/pyenv-newer-versions +++ /dev/null @@ -1,6 +0,0 @@ -# -*- shell-script -*- -if [[ $0 == ${BASH_SOURCE[0]} ]] ; then - echo "This script should be *sourced* rather than run directly through bash" - exit 1 -fi -export PYVERSIONS='3.5.9 3.6.9 2.6.9 3.3.7 2.7.17 3.2.6 3.1.5 3.4.10 3.7.6 3.8.18, 3.11.7 3.12.1' From 1fd9ba5062775964d6708515cce726e716b153d1 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 8 Oct 2024 07:44:40 -0400 Subject: [PATCH 36/40] Get ready for release 1.9.0. --- admin-tools/make-dist-2.4-2.7.sh | 55 +++++++++++++++++++++++++++ admin-tools/make-dist-3.0-3.2.sh | 62 +++++++++++++++++++++++++++++++ admin-tools/make-dist-3.3-3.5.sh | 62 +++++++++++++++++++++++++++++++ admin-tools/make-dist-3.6-3.10.sh | 62 +++++++++++++++++++++++++++++++ admin-tools/make-dist-newer.sh | 38 ------------------- admin-tools/make-dist-newest.sh | 53 ++++++++++++++++++++++++++ admin-tools/pyenv-newer-versions | 6 --- 7 files changed, 294 insertions(+), 44 deletions(-) create mode 100755 admin-tools/make-dist-2.4-2.7.sh create mode 100755 admin-tools/make-dist-3.0-3.2.sh create mode 100755 admin-tools/make-dist-3.3-3.5.sh create mode 100755 admin-tools/make-dist-3.6-3.10.sh delete mode 100755 admin-tools/make-dist-newer.sh create mode 100755 admin-tools/make-dist-newest.sh delete mode 100644 admin-tools/pyenv-newer-versions diff --git a/admin-tools/make-dist-2.4-2.7.sh b/admin-tools/make-dist-2.4-2.7.sh new file mode 100755 index 0000000..6946b69 --- /dev/null +++ b/admin-tools/make-dist-2.4-2.7.sh @@ -0,0 +1,55 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_24_owd +} +make_spark_dist_24_owd=$(pwd) +trap finish EXIT + +cd $(dirname ${BASH_SOURCE[0]}) +if ! source ./pyenv-2.4-2.7-versions ; then + exit $? +fi +if ! source ./setup-python-2.4.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + + rm -fr build + python setup.py bdist_egg + echo === $pyversion === +done + +echo "--- python 2.7 wheel ---" +pyenv local 2.7.18 +python setup.py bdist_wheel +echo === $pyversion === + +# PyPI can only have one source tarball. +# Tarballs can get created from the above setup, so make sure to remove them since we want +# the tarball from master. + +tarball=dist/${PACKAGE}-$__version__-tar.gz +if [[ -f $tarball ]]; then + rm -v dist/${PACKAGE}-$__version__-tar.gz +fi +finish diff --git a/admin-tools/make-dist-3.0-3.2.sh b/admin-tools/make-dist-3.0-3.2.sh new file mode 100755 index 0000000..8ac4ef3 --- /dev/null +++ b/admin-tools/make-dist-3.0-3.2.sh @@ -0,0 +1,62 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_30_owd +} + +make_spark_dist_30_owd=$(pwd) +cd $(dirname ${BASH_SOURCE[0]}) +trap finish EXIT + +if ! source ./pyenv-3.0-3.2-versions ; then + exit $? +fi +if ! source ./setup-python-3.0.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + # pip bdist_egg create too-general wheels. So + # we narrow that by moving the generated wheel. + + # Pick out first two numbers of version, e.g. 3.5.1 -> 35 + first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') + rm -fr build + python setup.py bdist_egg bdist_wheel + if [[ $first_two =~ py* ]]; then + if [[ $first_two =~ pypy* ]]; then + # For PyPy, remove the what is after the dash, e.g. pypy37-none-any.whl instead of pypy37-7-none-any.whl + first_two=${first_two%-*} + fi + mv -v dist/${PACKAGE}-$__version__-{py3,$first_two}-none-any.whl + else + mv -v dist/${PACKAGE}-$__version__-{py3,py$first_two}-none-any.whl + fi + echo === $pyversion === +done + +python ./setup.py sdist + +tarball=dist/${PACKAGE}-${__version__}.tar.gz +if [[ -f $tarball ]]; then + mv -v $tarball dist/${PACKAGE}_31-${__version__}.tar.gz +fi +finish diff --git a/admin-tools/make-dist-3.3-3.5.sh b/admin-tools/make-dist-3.3-3.5.sh new file mode 100755 index 0000000..efdba80 --- /dev/null +++ b/admin-tools/make-dist-3.3-3.5.sh @@ -0,0 +1,62 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_33_owd +} + +make_spark_dist_33_owd=$(pwd) +cd $(dirname ${BASH_SOURCE[0]}) +trap finish EXIT + +if ! source ./pyenv-3.3-3.5-versions ; then + exit $? +fi +if ! source ./setup-python-3.3.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + # pip bdist_egg create too-general wheels. So + # we narrow that by moving the generated wheel. + + # Pick out first two numbers of version, e.g. 3.5.1 -> 35 + first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') + rm -fr build + python setup.py bdist_egg bdist_wheel + if [[ $first_two =~ py* ]]; then + if [[ $first_two =~ pypy* ]]; then + # For PyPy, remove the what is after the dash, e.g. pypy37-none-any.whl instead of pypy37-7-none-any.whl + first_two=${first_two%-*} + fi + mv -v dist/${PACKAGE}-$__version__-{py3,$first_two}-none-any.whl + else + mv -v dist/${PACKAGE}-$__version__-{py3,py$first_two}-none-any.whl + fi + echo === $pyversion === +done + +python ./setup.py sdist + +tarball=dist/${PACKAGE}-${__version__}.tar.gz +if [[ -f $tarball ]]; then + mv -v $tarball dist/${PACKAGE}_33-${__version__}.tar.gz +fi +finish diff --git a/admin-tools/make-dist-3.6-3.10.sh b/admin-tools/make-dist-3.6-3.10.sh new file mode 100755 index 0000000..6f591b4 --- /dev/null +++ b/admin-tools/make-dist-3.6-3.10.sh @@ -0,0 +1,62 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_36_owd +} + +cd $(dirname ${BASH_SOURCE[0]}) +make_spark_dist_36_owd=$(pwd) +trap finish EXIT + +if ! source ./pyenv-3.6-3.10-versions ; then + exit $? +fi +if ! source ./setup-python-3.6.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +if [[ ! -n $__version__ ]]; then + echo "You need to set __version__ first" + exit 1 +fi +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + # pip bdist_egg create too-general wheels. So + # we narrow that by moving the generated wheel. + + # Pick out first two numbers of version, e.g. 3.5.1 -> 35 + first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') + rm -fr build + python setup.py bdist_egg bdist_wheel + if [[ $first_two =~ py* ]]; then + if [[ $first_two =~ pypy* ]]; then + # For PyPy, remove the what is after the dash, e.g. pypy37-none-any.whl instead of pypy37-7-none-any.whl + first_two=${first_two%-*} + fi + mv -v dist/${PACKAGE}-$__version__-{py3,$first_two}-none-any.whl + else + mv -v dist/${PACKAGE}-$__version__-{py3,py$first_two}-none-any.whl + fi + echo === $pyversion === +done + +python ./setup.py sdist + +tarball=dist/${PACKAGE}-${__version__}.tar.gz +if [[ -f $tarball ]]; then + mv -v $tarball dist/${PACKAGE}_36-${__version__}.tar.gz +fi +finish diff --git a/admin-tools/make-dist-newer.sh b/admin-tools/make-dist-newer.sh deleted file mode 100755 index b64e486..0000000 --- a/admin-tools/make-dist-newer.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -PACKAGE=spark_parser - -# FIXME put some of the below in a common routine -function finish { - cd $owd -} - -cd $(dirname ${BASH_SOURCE[0]}) -owd=$(pwd) -trap finish EXIT - -if ! source ./pyenv-newer-versions ; then - exit $? -fi -if ! source ./setup-master.sh ; then - exit $? -fi - -cd .. -source $PACKAGE/version.py -echo $VERSION - -for pyversion in $PYVERSIONS; do - if ! pyenv local $pyversion ; then - exit $? - fi - # pip bdist_egg create too-general wheels. So - # we narrow that by moving the generated wheel. - - # Pick out first two number of version, e.g. 3.5.1 -> 35 - first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') - rm -fr build - python setup.py bdist_egg bdist_wheel - mv -v dist/${PACKAGE}-${VERSION}-{py2.py3,py$first_two}-none-any.whl -done - -python ./setup.py sdist diff --git a/admin-tools/make-dist-newest.sh b/admin-tools/make-dist-newest.sh new file mode 100755 index 0000000..7209069 --- /dev/null +++ b/admin-tools/make-dist-newest.sh @@ -0,0 +1,53 @@ +#!/bin/bash +PACKAGE=spark_parser + +# FIXME put some of the below in a common routine +function finish { + cd $make_spark_dist_newest_owd +} + +cd $(dirname ${BASH_SOURCE[0]}) +make_spark_dist_newest_owd=$(pwd) +trap finish EXIT + +if ! source ./pyenv-newest-versions ; then + exit $? +fi +if ! source ./setup-master.sh ; then + exit $? +fi + +cd .. +source $PACKAGE/version.py +echo $__version__ + +for pyversion in $PYVERSIONS; do + echo --- $pyversion --- + if [[ ${pyversion:0:4} == "pypy" ]] ; then + echo "$pyversion - PyPy does not get special packaging" + continue + fi + if ! pyenv local $pyversion ; then + exit $? + fi + # pip bdist_egg create too-general wheels. So + # we narrow that by moving the generated wheel. + + # Pick out first two numbers of version, e.g. 3.5.1 -> 35 + first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') + rm -fr build + python setup.py bdist_egg bdist_wheel + if [[ $first_two =~ py* ]]; then + if [[ $first_two =~ pypy* ]]; then + # For PyPy, remove the what is after the dash, e.g. pypy37-none-any.whl instead of pypy37-7-none-any.whl + first_two=${first_two%-*} + fi + mv -v dist/${PACKAGE}-$__version__-{py3,$first_two}-none-any.whl + else + mv -v dist/${PACKAGE}-$__version__-{py3,py$first_two}-none-any.whl + fi + echo === $pyversion === +done + +python ./setup.py sdist +finish diff --git a/admin-tools/pyenv-newer-versions b/admin-tools/pyenv-newer-versions deleted file mode 100644 index b5c4ed6..0000000 --- a/admin-tools/pyenv-newer-versions +++ /dev/null @@ -1,6 +0,0 @@ -# -*- shell-script -*- -if [[ $0 == ${BASH_SOURCE[0]} ]] ; then - echo "This script should be *sourced* rather than run directly through bash" - exit 1 -fi -export PYVERSIONS='3.5.9 3.6.9 2.6.9 3.3.7 2.7.17 3.2.6 3.1.5 3.4.10 3.7.6 3.8.18, 3.11.7 3.12.1' From 74a94c82e88149e3dff87dc767b8ef48e4a3d913 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 8 Oct 2024 09:28:47 -0400 Subject: [PATCH 37/40] Reinstate older setup --- spark_parser/bin/parser_coverage.py => bin/spark-parser-coverage | 0 spark_parser/bin/__init__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename spark_parser/bin/parser_coverage.py => bin/spark-parser-coverage (100%) delete mode 100644 spark_parser/bin/__init__.py diff --git a/spark_parser/bin/parser_coverage.py b/bin/spark-parser-coverage similarity index 100% rename from spark_parser/bin/parser_coverage.py rename to bin/spark-parser-coverage diff --git a/spark_parser/bin/__init__.py b/spark_parser/bin/__init__.py deleted file mode 100644 index e69de29..0000000 From c39989792e37f65a5bbbee849fbb4e7946d472c3 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 8 Oct 2024 09:34:41 -0400 Subject: [PATCH 38/40] Go over coverage program --- bin/spark-parser-coverage | 91 +++++++++++---------------------------- 1 file changed, 26 insertions(+), 65 deletions(-) diff --git a/bin/spark-parser-coverage b/bin/spark-parser-coverage index dc13f66..b393876 100755 --- a/bin/spark-parser-coverage +++ b/bin/spark-parser-coverage @@ -17,102 +17,63 @@ """ Print grammar reduce statistics for a series of spark-parser parses """ -from __future__ import print_function +import getopt import os import pickle - -import click +import sys from spark_parser.version import __version__ -import getopt, os, sys -import pickle -DEFAULT_COVERAGE_FILE = "/tmp/spark-grammar.cover", + +def sort_profile_info(path, max_count=1000): + profile_info = pickle.load(open(path, "rb")) + items = sorted(profile_info.items(), key=lambda kv: kv[1], reverse=False) + return [item for item in items if item[1] <= max_count] + + +program, ext = os.path.splitext(os.path.basename(__file__)) + +DEFAULT_COVERAGE_FILE = "/tmp/spark-grammar.cover" DEFAULT_COUNT = 100 -def run(): - Usage_short = """usage: %s --path coverage-file... -Type -h for for full help.""" % program +def run(): + Usage_short = ( + """usage: %s --path coverage-file... +Type -h for for full help.""" + % program + ) try: - opts, files = getopt.getopt(sys.argv[1:], 'hVp:m:', - ['help', 'version', 'path=', 'max-count=']) + opts, files = getopt.getopt( + sys.argv[1:], "hVp:m:", ["help", "version", "path=", "max-count="] + ) except getopt.GetoptError(e): - sys.stderr.write('%s: %s\n' % (os.path.basename(sys.argv[0]), e)) + sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), e)) sys.exit(-1) max_count = DEFAULT_COUNT path = DEFAULT_COVERAGE_FILE for opt, val in opts: - if opt in ('-h', '--help'): + if opt in ("-h", "--help"): print(__doc__) sys.exit(1) - elif opt in ('-V', '--version'): + elif opt in ("-V", "--version"): print("%s %s" % (program, __version__)) sys.exit(0) - elif opt in ('-p', '--path'): + elif opt in ("-p", "--path"): path = val - elif opt in ('-m', '--max_count'): + elif opt in ("-m", "--max_count"): max_count = int(val) else: print(opt) sys.stderr.write(Usage_short) sys.exit(1) - """Print grammar reduce statistics for a series of spark-parser parses """ for rule, count in sort_profile_info(path, max_count): -======= - # And in some cases this is intentional. Uncompyle6 creates such grammar - # rules to ensure that positions of certain nonterminals in semantic - # actions appear in the same place as similar grammar rules - - unused_rules = set() # just the grammar rules - used_rules = [] # (count, grammar rule) - for rule, count in profile_info.items(): - if count == 0: - unused_rules.add(rule) - else: - used_rules.append((count, rule)) - - for count, rule in used_rules: - if rule.find("\\e_") > -1: - canonic_rule = rule.replace("\\e_", "", 1000) - if canonic_rule in unused_rules: - unused_rules.remove(canonic_rule) - pass - pass - pass - - unused_items = [(0, item) for item in sorted(unused_rules)] - used_items = sorted(used_rules, reverse=False) - return [item for item in unused_items + used_items if item[0] <= max_count] - - -DEFAULT_COVERAGE_FILE = os.environ.get( - "SPARK_PARSER_COVERAGE", "/tmp/spark-grammar.cover" -) -DEFAULT_COUNT = 100 - - -@click.command() -@click.version_option(version=__version__) -@click.option( - "--max-count", - type=int, - default=DEFAULT_COUNT, - help=( - f"limit output to rules having no more than this many hits (default {DEFAULT_COUNT})" - ), -) -@click.argument("path", type=click.Path(), default=DEFAULT_COVERAGE_FILE) -def run(max_count, path: str): - """Print grammar reduce statistics for a series of spark-parser parses""" - for count, rule in sort_profile_info(path, max_count): ->>>>>>> python-3.0-to-3.2 print("%d: %s" % (count, rule)) pass return From d81ce1e66c73004ba5491c422c18c824fc2bb055 Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 10 Oct 2024 11:02:50 -0400 Subject: [PATCH 39/40] Bump verison to dev and... remove some old crud --- spark_parser/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spark_parser/version.py b/spark_parser/version.py index 48ec36f..d05e46c 100644 --- a/spark_parser/version.py +++ b/spark_parser/version.py @@ -1,7 +1,7 @@ # This file is needs to be multi-lingual in both Python and POSIX # shell which "exec()" or "source" it respectively. -# This file should define a variable __version__ which we use as the +# This file should define a variable VERSION which we use as the # package version number. __version__="1.9.1.dev0" # noqa From 73382c6948d74aa6b1674dbfe6bf45406984d46e Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 2 Dec 2024 20:30:23 -0500 Subject: [PATCH 40/40] Adminstrivia --- admin-tools/setup-python-2.4.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/admin-tools/setup-python-2.4.sh b/admin-tools/setup-python-2.4.sh index 07b08a9..ca28277 100755 --- a/admin-tools/setup-python-2.4.sh +++ b/admin-tools/setup-python-2.4.sh @@ -1,14 +1,13 @@ #!/bin/bash PYTHON_VERSION=2.4.6 -owd=$(pwd) +spark_owd=$(pwd) bs=${BASH_SOURCE[0]} if [[ $0 == $bs ]] ; then echo "This script should be *sourced* rather than run directly through bash" exit 1 fi mydir=$(dirname $bs) -fulldir=$(readlink -f $mydir) -cd $fulldir/.. +cd $mydir/.. git checkout python-2.4-to-2.7 && pyenv local $PYTHON_VERSION -cd $owd +cd $spark_owd