From 6db74e65eead4185574371a0e1406490c9ccc317 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 2 Sep 2025 11:48:57 -0400 Subject: [PATCH 1/5] Try MacOS and MS Windows CI testing --- .github/workflows/macos.yml | 39 +++++++++++++++++++++++++++++++++++ .github/workflows/windows.yml | 39 +++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 .github/workflows/macos.yml create mode 100644 .github/workflows/windows.yml diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml new file mode 100644 index 0000000..2fc187a --- /dev/null +++ b/.github/workflows/macos.yml @@ -0,0 +1,39 @@ +name: Mathics3 Module PyICU (macOS) + +on: + push: + branches: [ master ] + pull_request: + branches: '**' + +jobs: + build: + runs-on: macos-latest + strategy: + matrix: + os: [macOS] + python-version: ['3.12', '3.13'] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + brew install llvm + python -m pip install --upgrade pip + python -m pip install pytest + # # Go over and comment out stuff when next Mathics core and Mathics-scanner are released + # python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full] + # git clone https://github.com/Mathics3/mathics-core + # (cd mathics-core && pip3 install -e .[full]) + # (cd mathics-core && bash ./admin-tools/make-JSON-tables.sh) + # python -m pip install -e git+https://github.com/Mathics3/Mathics3-Module-Base#egg=Mathics3-Module-Base + - name: Install Mathic3 PyICU Module + run: | + python -m pip install Mathics3 PyICU + python -m pip install --no-build-isolation -e . + - name: Test Mathics3 Module PyICU + run: | + make check diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 0000000..b37b506 --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,39 @@ +name: Mathics3-Module-PyICU (MS Windows) + +on: + push: + branches: [ master ] + pull_request: + branches: '**' + +jobs: + build: + runs-on: windows-latest + strategy: + matrix: + os: [windows] + python-version: ['3.12', '3.13'] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install pytest + # python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner + # git clone --depth 1 https://github.com/Mathics3/mathics-core mathics-core + # cd mathics-core + # python -m pip install -e . + # bash admin-tools/make-JSON-tables.sh + # cd .. + # python -m pip install -e git+https://github.com/Mathics3/Mathics3-Module-Base#egg=Mathics3-Module-Base + - name: Install Mathic3 PyICU Module + run: | + python -m pip install Mathics3 PyICU + python -m pip install --no-build-isolation -e . + - name: Test Mathics + run: | + make check From c820b7802b52d6bdf74f3a15ff838f288f28a622 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 2 Sep 2025 11:54:31 -0400 Subject: [PATCH 2/5] Try to fix up MacOS CI --- .github/workflows/macos.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 2fc187a..d431dd0 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -19,6 +19,9 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} + - name: Install ICU dependencies + run: | + echo "PKG_CONFIG_PATH=$(brew --prefix icu4c)/lib/pkgconfig" >> $GITHUB_ENV - name: Install dependencies run: | brew install llvm From 923ee2a40c62c0b51f6b9d21508e1d8b2cda5dae Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 2 Sep 2025 12:08:59 -0400 Subject: [PATCH 3/5] Try to fix up Windows CI --- .github/workflows/macos.yml | 2 +- .github/workflows/windows.yml | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index d431dd0..69c6a92 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -19,7 +19,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - name: Install ICU dependencies + - name: Set ICU version run: | echo "PKG_CONFIG_PATH=$(brew --prefix icu4c)/lib/pkgconfig" >> $GITHUB_ENV - name: Install dependencies diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index b37b506..432965e 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -19,8 +19,12 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} + - name: Set ICU version + run: | + echo "ICU_VERSION=73.2" >> $GITHUB_ENV - name: Install dependencies run: | + choco install icu python -m pip install --upgrade pip python -m pip install pytest # python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner @@ -30,7 +34,7 @@ jobs: # bash admin-tools/make-JSON-tables.sh # cd .. # python -m pip install -e git+https://github.com/Mathics3/Mathics3-Module-Base#egg=Mathics3-Module-Base - - name: Install Mathic3 PyICU Module + - name: Install Mathics3 PyICU Module run: | python -m pip install Mathics3 PyICU python -m pip install --no-build-isolation -e . From 4f9f11d5eef174e2361c25cbf8c7e5fbe3207c40 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 2 Sep 2025 12:24:09 -0400 Subject: [PATCH 4/5] Skip PyUCI testing on Windows... Don't know how to install PyICU there. --- .github/workflows/windows.yml | 43 ----------------------------------- 1 file changed, 43 deletions(-) delete mode 100644 .github/workflows/windows.yml diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100644 index 432965e..0000000 --- a/.github/workflows/windows.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Mathics3-Module-PyICU (MS Windows) - -on: - push: - branches: [ master ] - pull_request: - branches: '**' - -jobs: - build: - runs-on: windows-latest - strategy: - matrix: - os: [windows] - python-version: ['3.12', '3.13'] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - name: Set ICU version - run: | - echo "ICU_VERSION=73.2" >> $GITHUB_ENV - - name: Install dependencies - run: | - choco install icu - python -m pip install --upgrade pip - python -m pip install pytest - # python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner - # git clone --depth 1 https://github.com/Mathics3/mathics-core mathics-core - # cd mathics-core - # python -m pip install -e . - # bash admin-tools/make-JSON-tables.sh - # cd .. - # python -m pip install -e git+https://github.com/Mathics3/Mathics3-Module-Base#egg=Mathics3-Module-Base - - name: Install Mathics3 PyICU Module - run: | - python -m pip install Mathics3 PyICU - python -m pip install --no-build-isolation -e . - - name: Test Mathics - run: | - make check From 20461ee9e29af23cc8326958b294becf46a68658 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 2 Sep 2025 12:46:52 -0400 Subject: [PATCH 5/5] Get ready for release 9.0.0 --- ChangeLog-spell-corrected.diff | 0 NEWS.md | 6 + admin-tools/check-versions.sh | 27 +++ admin-tools/git2cl | 407 +++++++++++++++++++++++++++++++++ admin-tools/make-dist.sh | 29 +++ admin-tools/pyenv-versions | 8 + 6 files changed, 477 insertions(+) create mode 100644 ChangeLog-spell-corrected.diff create mode 100644 NEWS.md create mode 100755 admin-tools/check-versions.sh create mode 100755 admin-tools/git2cl create mode 100755 admin-tools/make-dist.sh create mode 100644 admin-tools/pyenv-versions diff --git a/ChangeLog-spell-corrected.diff b/ChangeLog-spell-corrected.diff new file mode 100644 index 0000000..e69de29 diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 0000000..611db4b --- /dev/null +++ b/NEWS.md @@ -0,0 +1,6 @@ +9.0.0 +----- + +Setp 2, 2025 + +Revise for 9.0.0 Mathics3 API. Python 3.13 suportted. Python before 3.10 dropped diff --git a/admin-tools/check-versions.sh b/admin-tools/check-versions.sh new file mode 100755 index 0000000..0d67a1a --- /dev/null +++ b/admin-tools/check-versions.sh @@ -0,0 +1,27 @@ +#!/bin/bash +function finish { + cd $mathics_pyicu_owd +} + +# FIXME put some of the below in a common routine +mathics_pyicu_owd=$(pwd) +trap finish EXIT + +cd $(dirname ${BASH_SOURCE[0]}) +if ! source ./pyenv-versions ; 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 +finish diff --git a/admin-tools/git2cl b/admin-tools/git2cl new file mode 100755 index 0000000..5d9b90c --- /dev/null +++ b/admin-tools/git2cl @@ -0,0 +1,407 @@ +#!/usr/bin/perl + +# Copyright (C) 2007, 2008 Simon Josefsson +# Copyright (C) 2007 Luis Mondesi +# * calls git directly. To use it just: +# cd ~/Project/my_git_repo; git2cl > ChangeLog +# * implements strptime() +# * fixes bugs in $comment parsing +# - copy input before we remove leading spaces +# - skip "merge branch" statements as they don't +# have information about files (i.e. we never +# go into $state 2) +# - behaves like a pipe/filter if input is given from the CLI +# else it calls git log by itself +# +# The functions mywrap, last_line_len, wrap_log_entry are derived from +# the cvs2cl tool, see : +# Copyright (C) 2001,2002,2003,2004 Martyn J. Pearce +# Copyright (C) 1999 Karl Fogel +# +# git2cl is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# git2cl is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with git2cl; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 USA. + +=head1 NAME + +git2cl - tool to convert git logs to GNU ChangeLog + +=head1 SYNOPSIS + +git2cl > ChangeLog + +If you don't want git2cl to invoke git log internally, you can use it +as a pipe. +It needs a git log generated with --pretty --numstat and --summary. +You can use it as follows: + + git log --pretty --numstat --summary | git2cl > ChangeLog + +=head1 DESCRIPTION + +This is a quick'n'dirty tool to convert git logs to GNU ChangeLog +format. + +The tool invokes `git log` internally unless you pipe a log to it. +Thus, typically you would use it as follows: + +=head1 SEE ALSO + +Output format specification: + + +=head1 AUTHORS + +git2cl is developed by Simon Josefsson + and Luis Mondesi + +=cut + +use strict; +use POSIX qw(strftime); +use Text::Wrap qw(wrap); +use FileHandle; + +use constant EMPTY_LOG_MESSAGE => '*** empty log message ***'; + +# this is a helper hash for stptime. +# Assumes you are calling 'git log ...' with LC_ALL=C +my %month = ( + 'Jan'=>0, + 'Feb'=>1, + 'Mar'=>2, + 'Apr'=>3, + 'May'=>4, + 'Jun'=>5, + 'Jul'=>6, + 'Aug'=>7, + 'Sep'=>8, + 'Oct'=>9, + 'Nov'=>10, + 'Dec'=>11, +); + +my $fh = new FileHandle; + +sub key_ready +{ + my ($rin, $nfd); + vec($rin, fileno(STDIN), 1) = 1; + return $nfd = select($rin, undef, undef, 0); +} + +sub strptime { + my $str = shift; + return undef if not defined $str; + + # we are parsing this format + # Fri Oct 26 00:42:56 2007 -0400 + # to these fields + # sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1 + # Luis Mondesi + my @date; + if ($str =~ /([[:alpha:]]{3})\s+([[:alpha:]]{3})\s+([[:digit:]]{1,2})\s+([[:digit:]]{1,2}):([[:digit:]]{1,2}):([[:digit:]]{1,2})\s+([[:digit:]]{4})/){ + push(@date,$6,$5,$4,$3,$month{$2},($7 - 1900),-1,-1,-1); + } else { + die ("Cannot parse date '$str'\n'"); + } + return @date; +} + +sub mywrap { + my ($indent1, $indent2, @text) = @_; + # If incoming text looks preformatted, don't get clever + my $text = Text::Wrap::wrap($indent1, $indent2, @text); + if ( grep /^\s+/m, @text ) { + return $text; + } + my @lines = split /\n/, $text; + $indent2 =~ s!^((?: {8})+)!"\t" x (length($1)/8)!e; + $lines[0] =~ s/^$indent1\s+/$indent1/; + s/^$indent2\s+/$indent2/ + for @lines[1..$#lines]; + my $newtext = join "\n", @lines; + $newtext .= "\n" + if substr($text, -1) eq "\n"; + return $newtext; +} + +sub last_line_len { + my $files_list = shift; + my @lines = split (/\n/, $files_list); + my $last_line = pop (@lines); + return length ($last_line); +} + +# A custom wrap function, sensitive to some common constructs used in +# log entries. +sub wrap_log_entry { + my $text = shift; # The text to wrap. + my $left_pad_str = shift; # String to pad with on the left. + + # These do NOT take left_pad_str into account: + my $length_remaining = shift; # Amount left on current line. + my $max_line_length = shift; # Amount left for a blank line. + + my $wrapped_text = ''; # The accumulating wrapped entry. + my $user_indent = ''; # Inherited user_indent from prev line. + + my $first_time = 1; # First iteration of the loop? + my $suppress_line_start_match = 0; # Set to disable line start checks. + + my @lines = split (/\n/, $text); + while (@lines) # Don't use `foreach' here, it won't work. + { + my $this_line = shift (@lines); + chomp $this_line; + + if ($this_line =~ /^(\s+)/) { + $user_indent = $1; + } + else { + $user_indent = ''; + } + + # If it matches any of the line-start regexps, print a newline now... + if ($suppress_line_start_match) + { + $suppress_line_start_match = 0; + } + elsif (($this_line =~ /^(\s*)\*\s+[a-zA-Z0-9]/) + || ($this_line =~ /^(\s*)\* [a-zA-Z0-9_\.\/\+-]+/) + || ($this_line =~ /^(\s*)\([a-zA-Z0-9_\.\/\+-]+(\)|,\s*)/) + || ($this_line =~ /^(\s+)(\S+)/) + || ($this_line =~ /^(\s*)- +/) + || ($this_line =~ /^()\s*$/) + || ($this_line =~ /^(\s*)\*\) +/) + || ($this_line =~ /^(\s*)[a-zA-Z0-9](\)|\.|\:) +/)) + { + $length_remaining = $max_line_length - (length ($user_indent)); + } + + # Now that any user_indent has been preserved, strip off leading + # whitespace, so up-folding has no ugly side-effects. + $this_line =~ s/^\s*//; + + # Accumulate the line, and adjust parameters for next line. + my $this_len = length ($this_line); + if ($this_len == 0) + { + # Blank lines should cancel any user_indent level. + $user_indent = ''; + $length_remaining = $max_line_length; + } + elsif ($this_len >= $length_remaining) # Line too long, try breaking it. + { + # Walk backwards from the end. At first acceptable spot, break + # a new line. + my $idx = $length_remaining - 1; + if ($idx < 0) { $idx = 0 }; + while ($idx > 0) + { + if (substr ($this_line, $idx, 1) =~ /\s/) + { + my $line_now = substr ($this_line, 0, $idx); + my $next_line = substr ($this_line, $idx); + $this_line = $line_now; + + # Clean whitespace off the end. + chomp $this_line; + + # The current line is ready to be printed. + $this_line .= "\n${left_pad_str}"; + + # Make sure the next line is allowed full room. + $length_remaining = $max_line_length - (length ($user_indent)); + + # Strip next_line, but then preserve any user_indent. + $next_line =~ s/^\s*//; + + # Sneak a peek at the user_indent of the upcoming line, so + # $next_line (which will now precede it) can inherit that + # indent level. Otherwise, use whatever user_indent level + # we currently have, which might be none. + my $next_next_line = shift (@lines); + if ((defined ($next_next_line)) && ($next_next_line =~ /^(\s+)/)) { + $next_line = $1 . $next_line if (defined ($1)); + # $length_remaining = $max_line_length - (length ($1)); + $next_next_line =~ s/^\s*//; + } + else { + $next_line = $user_indent . $next_line; + } + if (defined ($next_next_line)) { + unshift (@lines, $next_next_line); + } + unshift (@lines, $next_line); + + # Our new next line might, coincidentally, begin with one of + # the line-start regexps, so we temporarily turn off + # sensitivity to that until we're past the line. + $suppress_line_start_match = 1; + + last; + } + else + { + $idx--; + } + } + + if ($idx == 0) + { + # We bottomed out because the line is longer than the + # available space. But that could be because the space is + # small, or because the line is longer than even the maximum + # possible space. Handle both cases below. + + if ($length_remaining == ($max_line_length - (length ($user_indent)))) + { + # The line is simply too long -- there is no hope of ever + # breaking it nicely, so just insert it verbatim, with + # appropriate padding. + $this_line = "\n${left_pad_str}${this_line}"; + } + else + { + # Can't break it here, but may be able to on the next round... + unshift (@lines, $this_line); + $length_remaining = $max_line_length - (length ($user_indent)); + $this_line = "\n${left_pad_str}"; + } + } + } + else # $this_len < $length_remaining, so tack on what we can. + { + # Leave a note for the next iteration. + $length_remaining = $length_remaining - $this_len; + + if ($this_line =~ /\.$/) + { + $this_line .= " "; + $length_remaining -= 2; + } + else # not a sentence end + { + $this_line .= " "; + $length_remaining -= 1; + } + } + + # Unconditionally indicate that loop has run at least once. + $first_time = 0; + + $wrapped_text .= "${user_indent}${this_line}"; + } + + # One last bit of padding. + $wrapped_text .= "\n"; + + return $wrapped_text; +} + +# main + +my @date; +my $author; +my @files; +my $comment; + +my $state; # 0-header 1-comment 2-files +my $done = 0; + +$state = 0; + +# if reading from STDIN, we assume that we are +# getting git log as input +if (key_ready()) +{ + + #my $dummyfh; # don't care about writing + #($fh,$dummyfh) = FileHandle::pipe; + $fh->fdopen(*STDIN, 'r'); +} +else +{ + $fh->open("LC_ALL=C git log --pretty --numstat --summary|") + or die("Cannot execute git log...$!\n"); +} + +while (my $_l = <$fh>) { + #print STDERR "debug ($state, " . (@date ? (strftime "%Y-%m-%d", @date) : "") . "): `$_'\n"; + if ($state == 0) { + if ($_l =~ m,^Author: (.*),) { + $author = $1; + } + if ($_l =~ m,^Date: (.*),) { + @date = strptime($1); + } + $state = 1 if ($_l =~ m,^$, and $author and (@date+0>0)); + } elsif ($state == 1) { + # * modifying our input text is a bad choice + # let's make a copy of it first, then we remove spaces + # * if we meet a "merge branch" statement, we need to start + # over and find a real entry + # Luis Mondesi + my $_s = $_l; + $_s =~ s/^ //g; + if ($_s =~ m/^Merge branch/) + { + $state=0; + next; + } + $comment = $comment . $_s; + $state = 2 if ($_l =~ m,^$,); + } elsif ($state == 2) { + if ($_l =~ m,^([0-9]+)\t([0-9]+)\t(.*)$,) { + push @files, $3; + } + $done = 1 if ($_l =~ m,^$,); + } + + if ($done) { + print (strftime "%Y-%m-%d $author\n\n", @date); + + my $files = join (", ", @files); + $files = mywrap ("\t", "\t", "* $files"), ": "; + + if (index($comment, EMPTY_LOG_MESSAGE) > -1 ) { + $comment = "[no log message]\n"; + } + + my $files_last_line_len = 0; + $files_last_line_len = last_line_len($files) + 1; + my $msg = wrap_log_entry($comment, "\t", 69-$files_last_line_len, 69); + + $msg =~ s/[ \t]+\n/\n/g; + + print "$files: $msg\n"; + + @date = (); + $author = ""; + @files = (); + $comment = ""; + + $state = 0; + $done = 0; + } +} + +if (@date + 0) +{ + print (strftime "%Y-%m-%d $author\n\n", @date); + my $msg = wrap_log_entry($comment, "\t", 69, 69); + $msg =~ s/[ \t]+\n/\n/g; + print "\t* $msg\n"; +} diff --git a/admin-tools/make-dist.sh b/admin-tools/make-dist.sh new file mode 100755 index 0000000..8735f9d --- /dev/null +++ b/admin-tools/make-dist.sh @@ -0,0 +1,29 @@ +#!/bin/bash +PACKAGE=Mathics3-Module-pyicu + +# FIXME put some of the below in a common routine +function finish { + cd $mathics_pyicu_owd +} + +cd $(dirname ${BASH_SOURCE[0]}) +mathics_pyicu_owd=$(pwd) +trap finish EXIT + +if ! source ./pyenv-versions ; then + exit $? +fi + + +cd .. +source pymathics/language/version.py +echo $__version__ + +if ! pyenv local $pyversion ; then + exit $? +fi + +python setup.py bdist_wheel --universal +mv -v dist/pymathics_module_pyicu-${__version__}-{py2.,}py3-none-any.whl +python ./setup.py sdist +finish diff --git a/admin-tools/pyenv-versions b/admin-tools/pyenv-versions new file mode 100644 index 0000000..d21d7dc --- /dev/null +++ b/admin-tools/pyenv-versions @@ -0,0 +1,8 @@ +# -*- shell-script -*- +# Sets PYVERSIONS to be pyenv versions that +# we can use in the master 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.10 3.11 3.12 3.13'