From ba6e116559f908ca0816a13a1198f336e322131fb74f466c028a1f3a92649247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mark=C3=A9ta=20Machov=C3=A1?= Date: Thu, 18 Sep 2025 12:39:10 +0000 Subject: [PATCH] - Update to 0.8.1 * Fix crash on Windows for Python >= 3.12, caused by distutils module been removed from Python 3.12. - from version 0.8 * Fix unnecessary runtime dependency on setuptools. * Explicitly require a first argument called "progname". This is to avoid the common error not passing a progname by pointing users to it. This is fully backward compatible * Issue a warning if first argument looks like an option. * Fix crash if gs.new_instance() fails. * Breaking change (only effecting the low-level API): init_with_args() no longer catches e_Quit, but raises an exception like for any other error except e_Info. * Pass correct value to gslib if user_error is set. * Enhance documentation * Add some doc-strings. * Fix some linting issues. * Add testing with Python 3.10, 3.11, 3.12 and 3.13. * Revise testing, packaging and CI/CD. * Make tests independent of fonts, thus avoiding test failures. * Enhance examples. - Drop python-ghostscript-update-tests.patch, fixed upstream - Remove CHANGES.txt from %doc section OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-ghostscript?expand=0&rev=5 --- ghostscript-0.7.tar.gz | 3 - ghostscript-0.8.1.tar.gz | 3 + python-ghostscript-update-tests.patch | 379 -------------------------- python-ghostscript.changes | 27 ++ python-ghostscript.spec | 7 +- 5 files changed, 32 insertions(+), 387 deletions(-) delete mode 100644 ghostscript-0.7.tar.gz create mode 100644 ghostscript-0.8.1.tar.gz delete mode 100644 python-ghostscript-update-tests.patch diff --git a/ghostscript-0.7.tar.gz b/ghostscript-0.7.tar.gz deleted file mode 100644 index 6cdcca0..0000000 --- a/ghostscript-0.7.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b7875a87098740eb0be3de2d9662d15db727305ca9a6d4b7534a3cc33a4b965a -size 46557 diff --git a/ghostscript-0.8.1.tar.gz b/ghostscript-0.8.1.tar.gz new file mode 100644 index 0000000..39e224d --- /dev/null +++ b/ghostscript-0.8.1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7cfa85d201036bf87890e425b4a0cdc9749abc4670a4492ae2aa66ad792b1388 +size 28590 diff --git a/python-ghostscript-update-tests.patch b/python-ghostscript-update-tests.patch deleted file mode 100644 index 544bf11..0000000 --- a/python-ghostscript-update-tests.patch +++ /dev/null @@ -1,379 +0,0 @@ -diff -Nru ghostscript-0.7/MANIFEST.in ghostscript-0.7-update-tests/MANIFEST.in ---- ghostscript-0.7/MANIFEST.in 2021-03-06 12:54:56.000000000 -0300 -+++ ghostscript-0.7-update-tests/MANIFEST.in 2024-09-16 09:39:36.434531108 -0300 -@@ -1,5 +1,5 @@ - include COPYING - include README.txt - exclude .gitgnore --recursive-include test *.xml *.py *.bmp -+recursive-include test *.xml *.py *.bmp *.ps - #recursive-include doc *.html *.1 -Binary files ghostscript-0.7/test/hello_world.bmp and ghostscript-0.7-update-tests/test/hello_world.bmp differ -diff -Nru ghostscript-0.7/test/test_highlevel.py ghostscript-0.7-update-tests/test/test_highlevel.py ---- ghostscript-0.7/test/test_highlevel.py 2021-03-06 12:54:56.000000000 -0300 -+++ ghostscript-0.7-update-tests/test/test_highlevel.py 2024-09-16 10:10:16.046587248 -0300 -@@ -1,7 +1,7 @@ - # -*- coding: utf-8 -*- - # - # This file is part of python-ghostscript. --# Copyright 2010-2021 by Hartmut Goebel -+# Copyright 2010-2023 by Hartmut Goebel - # - # 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,39 +14,33 @@ - # General Public License for more details. - # - # You should have received a copy of the GNU General Public License --# along with this program. If not, see . -+# along with this program. If not, see . - # - - __author__ = "Hartmut Goebel " --__copyright__ = "Copyright 2010-2021 by Hartmut Goebel " -+__copyright__ = "Copyright 2010-2023 by Hartmut Goebel " - __licence__ = "GNU General Public License version 3 (GPL v3)" - - import io --import sys, os --import locale # required to encode file paths - import binascii -+import pathlib - import warnings - --import py, pytest -+import pytest - - import ghostscript as gslib - - --postscript_img = b""" -- /Helvetica findfont 12 scalefont setfont -- 0 0 moveto -- (Hello World) show -- showpage -- """ -- - HELLO_WORLD = ''.join(('%x' % ord(c) for c in 'Hello World')) - postscript_doc = ('<%s> = flush' % HELLO_WORLD).encode('ascii') - - STDARGS = ['test.py', '-dNOPAUSE', '-dBATCH', '-dSAFER', '-q', -- '-sDEVICE=bmp16', '-g80x12'] -+ '-sDEVICE=bmp16', '-g80x20'] - --TEST_PIC_FILENAME = os.path.join(os.path.dirname(__file__), 'hello_world.bmp') --TEST_PIC_DATA = py.path.local(TEST_PIC_FILENAME).read('rb') -+POSTSCRIPT_FILE = pathlib.Path(__file__).with_name('testimage.ps') -+POSTSCRIPT_DATA = POSTSCRIPT_FILE.read_bytes() -+TEST_PIC = POSTSCRIPT_FILE.with_suffix('.bmp') -+TEST_PIC_DATA = TEST_PIC.read_bytes() - - - # Ensure the instanse is removed after all high-level tests have been -@@ -71,7 +65,7 @@ - - - def test_revision_instance(instance): -- with gslib.Ghostscript('-dBATCH', '-q') as gs: -+ with gslib.Ghostscript('test.py', '-dBATCH', '-q') as gs: - rev1 = gs.revision() - rev2 = gslib.revision() - assert rev1 == rev2 -@@ -80,7 +74,7 @@ - def test_simple(instance, tmpdir): - """Let ghostscript read from a file and write to a file""" - infile = tmpdir.join('in.ps') -- infile.write(postscript_img) -+ infile.write(POSTSCRIPT_DATA) - outfile = tmpdir.join('out.bmp') - - # Using a context with an empty body looks not like good code, So -@@ -95,7 +89,7 @@ - def test_unicode_arguments(instance, tmpdir): - """Let ghostscript read from a file and write to a file""" - infile = tmpdir.join('in-äöü.ps') -- infile.write(postscript_img) -+ infile.write(POSTSCRIPT_DATA) - outfile = tmpdir.join('outäöü.bmp') - - gs = gslib.Ghostscript(*STDARGS, '-sOutputFile=%s' % outfile, str(infile)) -@@ -108,7 +102,7 @@ - def test_run_string_empty(instance, tmpdir): - """Let ghostscript read from a file and write to a file""" - infile = tmpdir.join('in.ps') -- infile.write(postscript_img) -+ infile.write(POSTSCRIPT_DATA) - outfile = tmpdir.join('out.bmp') - - with gslib.Ghostscript(*STDARGS, '-sOutputFile=%s' % outfile) as gs: -@@ -128,7 +122,7 @@ - outfile = tmpdir.join('out.bmp') - - with gslib.Ghostscript(*STDARGS, '-sOutputFile=%s' % outfile) as gs: -- gs.run_string(postscript_img) -+ gs.run_string(POSTSCRIPT_DATA) - - data = outfile.read('rb') - assert data == TEST_PIC_DATA -@@ -138,7 +132,7 @@ - """Let ghostscript read from stdin and write to a file""" - outfile = tmpdir.join('out.bmp') - gs = gslib.Ghostscript(*STDARGS, '-sOutputFile=%s' % outfile, '-', -- stdin=io.BytesIO(postscript_img)) -+ stdin=io.BytesIO(POSTSCRIPT_DATA)) - gs.exit() - - data = outfile.read('rb') -@@ -176,15 +170,13 @@ - keep stdout on the console. - """ - stderr = io.BytesIO() # buffer for collecting stderr -- try: -+ with pytest.raises(gslib.GhostscriptError): -+ # this call is expected to fail due to the intended error in -+ # the postscript code - with gslib.Ghostscript(*STDARGS, '-', - stdin=io.BytesIO(b'foobar'), - stderr=stderr): -- # this call is expected to fail due to the intended error in -- # the postscript code - pass -- except gslib.GhostscriptError: -- pass - - data = stderr.getvalue() - assert b'Unrecoverable error' in data -@@ -197,15 +189,13 @@ - """ - stdout = io.BytesIO() # buffer for collecting the output - stderr = io.BytesIO() # buffer for collecting stderr -- try: -+ with pytest.raises(gslib.GhostscriptError): -+ # this call is expected to fail due to the intended error in -+ # the postscript code - with gslib.Ghostscript(*STDARGS, '-', - stdin=io.BytesIO(b'foobar'), - stdout=stdout, stderr=stderr): -- # this call is expected to fail due to the intended error in -- # the postscript code - pass -- except gslib.GhostscriptError: -- pass - - data = stdout.getvalue() - assert b'Error: /undefined in foobar' in data -@@ -219,8 +209,9 @@ - # Cause all warnings to always be triggered - warnings.simplefilter("always") - # Trigger the warning -- with gslib.Ghostscript(b'-dBATCH', b'-q') as gs: -+ with gslib.Ghostscript(b'test.py', b'-dBATCH', b'-q') as gs: - pass - assert len(w) == 1 - assert issubclass(w[-1].category, DeprecationWarning) - assert "deprecated" in str(w[-1].message) -+ -Binary files ghostscript-0.7/test/testimage.bmp and ghostscript-0.7-update-tests/test/testimage.bmp differ -diff -Nru ghostscript-0.7/test/testimage.ps ghostscript-0.7-update-tests/test/testimage.ps ---- ghostscript-0.7/test/testimage.ps 1969-12-31 21:00:00.000000000 -0300 -+++ ghostscript-0.7-update-tests/test/testimage.ps 2024-09-16 09:42:20.618536118 -0300 -@@ -0,0 +1,22 @@ -+%!PS-Adobe-3.0 -+%%BoundingBox: 0 0 80 50 -+newpath -+0 0 moveto -+0 20 rlineto -+40 0 rlineto -+closepath -+gsave -+0.5 setgray -+fill -+grestore -+newpath -+40 0 moveto -+0 20 rlineto -+40 0 rlineto -+closepath -+gsave -+0.7 setgray -+fill -+grestore -+showpage -+ -diff -Nru ghostscript-0.7/test/test_lowlevel.py ghostscript-0.7-update-tests/test/test_lowlevel.py ---- ghostscript-0.7/test/test_lowlevel.py 2021-03-06 12:54:56.000000000 -0300 -+++ ghostscript-0.7-update-tests/test/test_lowlevel.py 2024-09-16 10:08:18.602583664 -0300 -@@ -1,7 +1,7 @@ - # -*- coding: utf-8 -*- - # - # This file is part of python-ghostscript. --# Copyright 2010-2021 by Hartmut Goebel -+# Copyright 2010-2023 by Hartmut Goebel - # - # 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,41 +14,41 @@ - # General Public License for more details. - # - # You should have received a copy of the GNU General Public License --# along with this program. If not, see . -+# along with this program. If not, see . - # - - __author__ = "Hartmut Goebel " --__copyright__ = "Copyright 2010-2021 by Hartmut Goebel " -+__copyright__ = "Copyright 2010-2023 by Hartmut Goebel " - __licence__ = "GNU General Public License version 3 (GPL v3)" - - import io --import sys, os --import locale # required to encode file paths -+import locale # required to encode arguments - import binascii -+import pathlib - --import py -+import pytest - - import ghostscript._gsprint as gs - --postscript_img = b""" -- /Helvetica findfont 12 scalefont setfont -- 0 0 moveto -- (Hello World) show -- showpage -- """ - - HELLO_WORLD = ''.join(('%x' % ord(c) for c in 'Hello World')) - #HELLO_WORLD = binascii.hexlify('Hello World') - postscript_doc = ('<%s> = flush' % HELLO_WORLD).encode('ascii') - -+# For the low-level interface arguments have to be bytes. Encode them -+# using local encoding to save calling set_arg_encoding(). - STDARGS = [b'test.py', b'-dNOPAUSE', b'-dBATCH', b'-dSAFER', b'-q', -- b'-sDEVICE=bmp16', b'-g80x12'] -+ b'-sDEVICE=bmp16', b'-g80x20'] - --TEST_PIC_FILENAME = os.path.join(os.path.dirname(__file__), 'hello_world.bmp') --TEST_PIC_DATA = py.path.local(TEST_PIC_FILENAME).read('rb') -+POSTSCRIPT_FILE = pathlib.Path(__file__).with_name('testimage.ps') -+POSTSCRIPT_DATA = POSTSCRIPT_FILE.read_bytes() -+TEST_PIC = POSTSCRIPT_FILE.with_suffix('.bmp') -+TEST_PIC_DATA = TEST_PIC.read_bytes() - - - def _encode(*args): -+ # For the low-level interface arguments have to be bytes. Encode -+ # them using local encoding to save calling set_arg_encoding(). - encoding = locale.getpreferredencoding() - return [a.encode(encoding) for a in args] - -@@ -70,8 +70,8 @@ - instance = gs.new_instance() - - try: -- gs.init_with_args(instance, args) -- gs.run_string(instance, postscript_img) -+ assert gs.init_with_args(instance, args) == 0 -+ assert gs.run_string(instance, POSTSCRIPT_DATA) == 0 - finally: - gs.exit(instance) - gs.delete_instance(instance) -@@ -80,17 +80,33 @@ - assert data == TEST_PIC_DATA - - -+def test_run_bugyy_string(tmpdir): -+ """ -+ Test whether the program flow (try/finally, gs.exit, -+ gs.delete_instance) is correct if executing fails. -+ """ -+ args = STDARGS -+ instance = gs.new_instance() -+ try: -+ assert gs.init_with_args(instance, args) == 0 -+ with pytest.raises(gs.GhostscriptError): -+ gs.run_string(instance, b"invalid postscript code") -+ finally: -+ gs.exit(instance) -+ gs.delete_instance(instance) -+ -+ - def test_simple(tmpdir): - """Let ghostscript read from a file and write to a file""" - infile = tmpdir.join('in.ps') -- infile.write(postscript_img) -+ infile.write(POSTSCRIPT_DATA) - outfile = tmpdir.join('out.bmp') - - args = STDARGS + _encode('-sOutputFile=%s' % outfile, str(infile)) - - instance = gs.new_instance() - try: -- gs.init_with_args(instance, args) -+ assert gs.init_with_args(instance, args) == 0 - finally: - gs.exit(instance) - gs.delete_instance(instance) -@@ -103,7 +119,7 @@ - instance = gs.new_instance() - - # wrappers like in -- # http://ghostscript.com/doc/8.54/API.htm#Example_usage -+ # https://ghostscript.readthedocs.io/en/gs10.0.0/API.html#Example_usage - if stdin is not None: stdin = gs._wrap_stdin(stdin) - if stdout is not None: stdout = gs._wrap_stdout(stdout) - if stderr is not None: stderr = gs._wrap_stderr(stderr) -@@ -122,7 +138,7 @@ - - args = STDARGS + _encode('-sOutputFile=%s' % outfile, '-') - -- _gs_stdio(args, stdin=io.BytesIO(postscript_img)) -+ _gs_stdio(args, stdin=io.BytesIO(POSTSCRIPT_DATA)) - - data = outfile.read('rb') - assert data == TEST_PIC_DATA -@@ -164,12 +180,10 @@ - - stderr = io.BytesIO() # buffer for collecting stderr - -- try: -+ with pytest.raises(gs.GhostscriptError): - # this call is expected to fail due to the intended error in - # the postscript code - _gs_stdio(args, stdin=io.BytesIO(b'foobar'), stderr=stderr) -- except gs.GhostscriptError: -- pass - - data = stderr.getvalue() - assert b'Unrecoverable error' in data -@@ -185,13 +199,11 @@ - stdout = io.BytesIO() # buffer for collecting the output - stderr = io.BytesIO() # buffer for collecting stderr - -- try: -+ with pytest.raises(gs.GhostscriptError): - # this call is expected to fail due to the intended error in - # the postscript code - _gs_stdio(args, - stdin=io.BytesIO(b'foobar'), stdout=stdout, stderr=stderr) -- except gs.GhostscriptError: -- pass - - data = stdout.getvalue() - assert b'Error: /undefined in foobar' in data -@@ -206,10 +218,11 @@ - Use command line ghostscript to generate the image used in testing - """ - import subprocess -- outfile = TEST_PIC_FILENAME -+ args = ['gs'] + STDARGS[1:] + _encode('-sOutputFile=%s' % TEST_PIC, -+ str(POSTSCRIPT_FILE)) -+ subprocess.Popen(args).wait() - -- args = ['gs'] + STDARGS[1:] + _encode('-sOutputFile=%s' % outfile, '-') -- subprocess.Popen(args).communicate(postscript_doc) - - if __name__ == '__main__': - generate_test_picture() -+ diff --git a/python-ghostscript.changes b/python-ghostscript.changes index 599c8c1..3100b13 100644 --- a/python-ghostscript.changes +++ b/python-ghostscript.changes @@ -1,3 +1,30 @@ +------------------------------------------------------------------- +Thu Sep 18 11:52:11 UTC 2025 - John Paul Adrian Glaubitz + +- Update to 0.8.1 + * Fix crash on Windows for Python >= 3.12, caused by + distutils module been removed from Python 3.12. +- from version 0.8 + * Fix unnecessary runtime dependency on setuptools. + * Explicitly require a first argument called "progname". This is to + avoid the common error not passing a progname by pointing users to it. + This is fully backward compatible + * Issue a warning if first argument looks like an option. + * Fix crash if gs.new_instance() fails. + * Breaking change (only effecting the low-level API): + init_with_args() no longer catches e_Quit, + but raises an exception like for any other error except e_Info. + * Pass correct value to gslib if user_error is set. + * Enhance documentation + * Add some doc-strings. + * Fix some linting issues. + * Add testing with Python 3.10, 3.11, 3.12 and 3.13. + * Revise testing, packaging and CI/CD. + * Make tests independent of fonts, thus avoiding test failures. + * Enhance examples. +- Drop python-ghostscript-update-tests.patch, fixed upstream +- Remove CHANGES.txt from %doc section + ------------------------------------------------------------------- Tue Sep 17 13:19:05 UTC 2024 - Markéta Machová diff --git a/python-ghostscript.spec b/python-ghostscript.spec index 9866005..c5ae452 100644 --- a/python-ghostscript.spec +++ b/python-ghostscript.spec @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-ghostscript -Version: 0.7 +Version: 0.8.1 Release: 0 License: GPL-3.0-or-later Summary: Python interface to the Ghostscript C-API @@ -26,9 +26,6 @@ Group: Development/Languages/Python URL: https://gitlab.com/pdftools/python-ghostscript Source: https://files.pythonhosted.org/packages/source/g/ghostscript/ghostscript-%{version}.tar.gz Source1: https://gitlab.com/pdftools/python-ghostscript/-/raw/develop/test/testimage.bmp -# Previous tests were dependent on fonts and generated different results -# depending on ghostscript version and platform -Patch1: python-ghostscript-update-tests.patch BuildRequires: %{python_module devel} BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools} @@ -62,7 +59,7 @@ cp %{SOURCE1} test %pytest -v %files %{python_files} -%doc CHANGES.txt README.rst +%doc README.rst %license COPYING %{python_sitelib}/ghostscript %{python_sitelib}/ghostscript-%{version}*-info