remove old Python2 constructs; patch from Claude Paroz < claude at 2xlibre dot net >; version --> 3.6.8
authorrobin
Mon, 28 Feb 2022 11:28:14 +0000
changeset 4710 5d3c80a9e519
parent 4709 1dcf7b3f7127
child 4711 2d271a6f5a35
remove old Python2 constructs; patch from Claude Paroz < claude at 2xlibre dot net >; version --> 3.6.8
CHANGES.md
README.txt
docs/userguide/ch1_intro.py
setup.py
src/reportlab/__init__.py
src/reportlab/graphics/barcode/qr.py
src/reportlab/graphics/renderPM.py
src/reportlab/graphics/shapes.py
src/reportlab/lib/fontfinder.py
src/reportlab/lib/pdfencrypt.py
src/reportlab/lib/rl_safe_eval.py
src/reportlab/lib/testutils.py
src/reportlab/lib/utils.py
src/reportlab/lib/validators.py
src/reportlab/pdfbase/pdfdoc.py
src/reportlab/pdfgen/canvas.py
src/reportlab/pdfgen/pdfimages.py
src/reportlab/platypus/paraparser.py
src/reportlab/rl_settings.py
tests/test_paragraphs.py
tests/test_renderPS.py
tests/test_renderSVG.py
--- a/CHANGES.md	Fri Feb 18 11:01:32 2022 +0000
+++ b/CHANGES.md	Mon Feb 28 11:28:14 2022 +0000
@@ -11,6 +11,10 @@
 The contributors lists are in no order and apologies to those accidentally not
 mentioned. If we missed you, please let us know!
 
+CHANGES  3.6.8   28/02/2022
+---------------------------
+	* remove old Python2 constructs; patch from Claude Paroz < claude at 2xlibre dot net >
+
 CHANGES  3.6.7   18/02/2022
 ---------------------------
 	* Remove use of cPickle; patch from Claude Paroz < claude at 2xlibre dot net >
--- a/README.txt	Fri Feb 18 11:01:32 2022 +0000
+++ b/README.txt	Mon Feb 28 11:28:14 2022 +0000
@@ -2,7 +2,7 @@
 README
 =====================================
 
-(C) Copyright ReportLab Europe Ltd. 2000-2017.
+(C) Copyright ReportLab Europe Ltd. 2000-2022.
 See ``LICENSE.txt`` for license details.
 
 This is the ReportLab PDF Toolkit. It allows rapid creation
@@ -54,7 +54,7 @@
 
 2.1 General prerequisites
 --------------------------
-You need to have installed Python (versions 2.7 or >=3.6),
+You need to have installed Python (versions >=3.6),
 and ideally PIL or Pillow with Freetype support; more notes on prerequisites
 follow below.
 
@@ -149,7 +149,7 @@
 
 3. Prerequisites / Dependencies
 ===============================
-This works with Python versions 2.7 or >=3.5. Older versions are available
+This works with Python versions >=3.6. Older versions are available
 going back to Python 1.5 or thereabouts.
 
 There are no absolute prerequisites beyond the Python
--- a/docs/userguide/ch1_intro.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/docs/userguide/ch1_intro.py	Mon Feb 28 11:28:14 2022 +0000
@@ -332,7 +332,6 @@
 bullet("""CMapSearchPath: this is a python list of strings representing directories that
 may be queried for information on font code maps.""")
 bullet("""showBoundary: set to non-zero to get boundary lines drawn.""")
-bullet("""ZLIB_WARNINGS: set to non-zero to get warnings if the Python compression extension is not found.""")
 bullet("""pageCompression: set to non-zero to try and get compressed PDF.""")
 bullet("""allowtableBoundsErrors: set to 0 to force an error on very large Platypus table elements""")
 bullet("""emptyTableAction: Controls behaviour for empty tables, can be 'error' (default), 'indicate' or 'ignore'.""")
--- a/setup.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/setup.py	Mon Feb 28 11:28:14 2022 +0000
@@ -2,6 +2,8 @@
 #see license.txt for license details
 __version__='3.6.3'
 import os, sys, glob, shutil, re, sysconfig, traceback, io, subprocess
+from configparser import RawConfigParser
+from urllib.parse import quote as urlquote
 platform = sys.platform
 pjoin = os.path.join
 abspath = os.path.abspath
@@ -12,11 +14,6 @@
 splitext = os.path.splitext
 archName = 'amd64' if sys.maxsize > 2**32 else 'x86'    #correct for windows builds
 
-try:
-    from urllib.parse import quote as urlquote
-except ImportError:
-    from urllib import quote as urlquote
-
 INFOLINES=[]
 def infoline(t,
         pfx='#####',
@@ -73,10 +70,6 @@
 verbose = specialOption('--verbose',ceq=True)
 nullDivert = not verbose
 
-try:
-    import configparser
-except ImportError:
-    import ConfigParser as configparser
 if __name__=='__main__':
     pkgDir=dirname(sys.argv[0])
 else:
@@ -95,10 +88,6 @@
     from setuptools import setup, Extension
 except ImportError:
     from distutils.core import setup, Extension
-try:
-    import sysconfig
-except ImportError:
-    from distutils import sysconfig
 
 def _packages_path(d):
     P = [_ for _ in sys.path if basename(_)==d]
@@ -171,7 +160,7 @@
 class config:
     def __init__(self):
         try:
-            self.parser = configparser.RawConfigParser()
+            self.parser = RawConfigParser()
             self.parser.read([pjoin(pkgDir,'setup.cfg'),pjoin(pkgDir,'local-setup.cfg')])
         except:
             self.parser = None
@@ -239,7 +228,6 @@
 inc_lib_dirs=inc_lib_dirs()
 
 def getVersionFromCCode(fn):
-    import re
     tag = re.search(r'^#define\s+VERSION\s+"([^"]*)"',open(fn,'r').read(),re.M)
     return tag and tag.group(1) or ''
 
@@ -331,7 +319,6 @@
         ]
 
 def url2data(url,returnRaw=False):
-    import io
     import urllib.request as ureq
     remotehandle = ureq.urlopen(url)
     try:
--- a/src/reportlab/__init__.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/__init__.py	Mon Feb 28 11:28:14 2022 +0000
@@ -1,9 +1,9 @@
 #Copyright ReportLab Europe Ltd. 2000-2021
 #see license.txt for license details
 __doc__="""The Reportlab PDF generation library."""
-Version = "3.6.7"
+Version = "3.6.8"
 __version__=Version
-__date__='20220218'
+__date__='20220228'
 
 import sys, os
 
--- a/src/reportlab/graphics/barcode/qr.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/graphics/barcode/qr.py	Mon Feb 28 11:28:14 2022 +0000
@@ -27,20 +27,7 @@
 from reportlab.lib.attrmap import AttrMap, AttrMapValue
 from reportlab.graphics.widgetbase import Widget
 from reportlab.lib.units import mm
-try:
-    from reportlab.lib.utils import asUnicodeEx, isUnicode
-except ImportError:
-    # ReportLab 2.x compatibility
-    def asUnicodeEx(v, enc='utf8'):
-        if isinstance(v, unicode):
-            return v
-        if isinstance(v, str):
-            return v.decode(enc)
-        return str(v).decode(enc)
-
-    def isUnicode(v):
-        return isinstance(v, unicode)
-
+from reportlab.lib.utils import asUnicodeEx, isUnicode
 from reportlab.graphics.barcode import qrencoder
 
 class isLevel(Validator):
--- a/src/reportlab/graphics/renderPM.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/graphics/renderPM.py	Mon Feb 28 11:28:14 2022 +0000
@@ -343,20 +343,9 @@
         elif fmt in ('PCT','PICT'):
             return _saveAsPICT(im,fn,fmt,transparent=configPIL.get('transparent',None))
         elif fmt in ('PNG','BMP', 'PPM'):
-            if fmt=='PNG':
-                try:
-                    from PIL import PngImagePlugin
-                except ImportError:
-                    import PngImagePlugin
-            elif fmt=='BMP':
-                try:
-                    from PIL import BmpImagePlugin
-                except ImportError:
-                    import BmpImagePlugin
+            pass
         elif fmt in ('JPG','JPEG'):
             fmt = 'JPEG'
-        elif fmt in ('GIF',):
-            pass
         else:
             raise RenderPMError("Unknown image kind %s" % fmt)
         if fmt=='TIFF':
--- a/src/reportlab/graphics/shapes.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/graphics/shapes.py	Mon Feb 28 11:28:14 2022 +0000
@@ -516,13 +516,8 @@
         return 'EmptyClipPath'
     elif isinstance(self,Shape):
         if I: _addObjImport(self,I)
-        try:
-            from inspect import getfullargspec
-            args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations = getfullargspec(self.__init__)
-        except ImportError:
-            from inspect import getargspec
-            args, varargs, varkw, defaults = getargspec(self.__init__)
-            kwonlyargs, kwonlydefaults, annotations = None, None, None
+        from inspect import getfullargspec
+        args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations = getfullargspec(self.__init__)
         if defaults:
             kargs = args[-len(defaults):]
             del args[-len(defaults):]
--- a/src/reportlab/lib/fontfinder.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/lib/fontfinder.py	Mon Feb 28 11:28:14 2022 +0000
@@ -59,17 +59,10 @@
 update itself smartly on repeated instantiation.
 """
 import sys, os, pickle
-from reportlab.lib.utils import asNative as _asNative
+from hashlib import md5
 from xml.sax.saxutils import quoteattr
-from reportlab.lib.utils import asBytes
-try:
-    from time import process_time as clock
-except ImportError:
-    from time import clock
-try:
-    from hashlib import md5
-except ImportError:
-    from md5 import md5
+from time import process_time as clock
+from reportlab.lib.utils import asBytes, asNative as _asNative
 
 def asNative(s):
     try:
--- a/src/reportlab/lib/pdfencrypt.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/lib/pdfencrypt.py	Mon Feb 28 11:28:14 2022 +0000
@@ -23,7 +23,6 @@
     "xor's each byte of the key with the number, which is <256"
     if num==0: return key
     return bytes(num^k for k in key)
-bytes3 = bytes
 
 #AR debug hooks - leaving in for now
 CLOBBERID = 0  # set a constant Doc ID to allow comparison with other software like iText
@@ -213,7 +212,7 @@
 
             # the permission array should be enrypted in the Perms field
             encrypter = pyaes.Encrypter(pyaes.AESModeOfOperationCBC(self.key, iv=iv))
-            self.Perms = encrypter.feed(bytes3(permsarr))
+            self.Perms = encrypter.feed(bytes(permsarr))
             self.Perms += encrypter.feed()
                         
             if DEBUG:
--- a/src/reportlab/lib/rl_safe_eval.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/lib/rl_safe_eval.py	Mon Feb 28 11:28:14 2022 +0000
@@ -9,7 +9,6 @@
 isPy39 = sys.version_info[:2]>=(3,9)
 
 haveNameConstant = hasattr(ast,'NameConstant')
-haveMatMult = haveMultiStarred = hasattr(ast,'MatMult')
 import textwrap
 
 class BadCode(ValueError):
@@ -17,7 +16,6 @@
 
 # For AugAssign the operator must be converted to a string.
 augOps = {
-	# Shared by python2 and python3
 	ast.Add: '+=',
 	ast.Sub: '-=',
 	ast.Mult: '*=',
@@ -29,13 +27,10 @@
 	ast.BitOr: '|=',
 	ast.BitXor: '^=',
 	ast.BitAnd: '&=',
-	ast.FloorDiv: '//='
+	ast.FloorDiv: '//=',
+	ast.MatMult: '@=',
 }
 
-if haveMatMult:
-	augOps[ast.MatMult] = '@='
-
-
 # For creation allowed magic method names. See also
 # https://docs.python.org/3/reference/datamodel.html#special-method-names
 __allowed_magic_methods__ = frozenset([
@@ -430,23 +425,12 @@
 
 		needs_wrap = False
 
-		# In python2.7 till python3.4 '*args', '**kwargs' have dedicated
-		# attributes on the ast.Call node.
-		# In python 3.5 and greater this has changed due to the fact that
-		# multiple '*args' and '**kwargs' are possible.
-		# '*args' can be detected by 'ast.Starred' nodes.
-		# '**kwargs' can be deteced by 'keyword' nodes with 'arg=None'.
+		for pos_arg in node.args:
+			if isinstance(pos_arg, ast.Starred):
+				needs_wrap = True
 
-		if haveMultiStarred:
-			for pos_arg in node.args:
-				if isinstance(pos_arg, ast.Starred):
-					needs_wrap = True
-
-			for keyword_arg in node.keywords:
-				if keyword_arg.arg is None:
-					needs_wrap = True
-		else:
-			if (node.starargs is not None) or (node.kwargs is not None):
+		for keyword_arg in node.keywords:
+			if keyword_arg.arg is None:
 				needs_wrap = True
 
 		node = self.visit_children(node)
--- a/src/reportlab/lib/testutils.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/lib/testutils.py	Mon Feb 28 11:28:14 2022 +0000
@@ -13,10 +13,7 @@
 """
 
 import sys, os, fnmatch, re
-try:
-    from configparser import ConfigParser
-except ImportError:
-    from ConfigParser import ConfigParser
+from configparser import ConfigParser
 import unittest
 from reportlab.lib.utils import isCompactDistro, __rl_loader__, rl_isdir, asUnicode
 
--- a/src/reportlab/lib/utils.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/lib/utils.py	Mon Feb 28 11:28:14 2022 +0000
@@ -4,14 +4,11 @@
 __version__='3.5.34'
 __doc__='''Gazillions of miscellaneous internal utility functions'''
 
-import os, pickle, sys, time, types, datetime, ast, importlib
+import os, pickle, sys, time, types, datetime, importlib
+from ast import literal_eval
+from base64 import decodebytes as base64_decodebytes, encodebytes as base64_encodebytes
 from io import BytesIO
-literal_eval = ast.literal_eval
-try:
-    from base64 import decodebytes as base64_decodebytes, encodebytes as base64_encodebytes
-except ImportError:
-    from base64 import decodestring as base64_decodebytes, encodestring as base64_encodebytes
-from reportlab.lib.logger import warnOnce
+
 from reportlab.lib.rltempfile import get_rl_tempfile, get_rl_tempdir
 from . rl_safe_eval import rl_safe_exec, rl_safe_eval, safer_globals
 
@@ -392,15 +389,6 @@
         if debug:
             print('===== restore sys.path=%s' % repr(opath))
 
-def import_zlib():
-    try:
-        import zlib
-    except ImportError:
-        zlib = None
-        from reportlab.rl_config import ZLIB_WARNINGS
-        if ZLIB_WARNINGS: warnOnce('zlib not available')
-    return zlib
-
 # Image Capability Detection.  Set a flag haveImages
 # to tell us if PIL library is present.
 # define PIL_Image as either None, or an alias for the PIL.Image
--- a/src/reportlab/lib/validators.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/lib/validators.py	Mon Feb 28 11:28:14 2022 +0000
@@ -7,10 +7,6 @@
 import codecs, re
 from reportlab.lib.utils import isSeq, isBytes, isStr
 from reportlab.lib import colors
-try:
-    _re_Pattern = re.Pattern
-except AttributeError:
-    _re_Pattern = re._pattern_type
 
 class Percentage(float):
     pass
@@ -208,9 +204,9 @@
             self._enum = tuple(enum)+args
         else:
             self._enum = (enum,)+args
-        self._patterns = tuple((_ for _ in self._enum if isinstance(_,_re_Pattern)))
+        self._patterns = tuple((_ for _ in self._enum if isinstance(_, re.Pattern)))
         if self._patterns:
-            self._enum =  tuple((_ for _ in self._enum if not isinstance(_,_re_Pattern)))
+            self._enum =  tuple((_ for _ in self._enum if not isinstance(_, re.Pattern)))
             self.test = self._test_patterns
 
     def test(self, x):
--- a/src/reportlab/pdfbase/pdfdoc.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/pdfbase/pdfdoc.py	Mon Feb 28 11:28:14 2022 +0000
@@ -14,11 +14,11 @@
 and are not part of any public interface.  Instead, canvas and font
 classes are made available elsewhere for users to manipulate.
 """
-import binascii, codecs
+import binascii, codecs, zlib
 from collections import OrderedDict
 from reportlab.pdfbase import pdfutils
 from reportlab import rl_config
-from reportlab.lib.utils import import_zlib, open_for_read, makeFileName, isSeq, isBytes, isUnicode, _digester, isStr, bytestr, annotateException, TimeStamp
+from reportlab.lib.utils import open_for_read, makeFileName, isSeq, isBytes, isUnicode, _digester, isStr, bytestr, annotateException, TimeStamp
 from reportlab.lib.rl_accel import escapePDF, fp_str, asciiBase85Encode, asciiBase85Decode
 from reportlab.pdfbase import pdfmetrics
 from hashlib import md5
@@ -747,16 +747,10 @@
 class PDFStreamFilterZCompress:
     pdfname = "FlateDecode"
     def encode(self, text):
-        from reportlab.lib.utils import import_zlib
-        zlib = import_zlib()
-        if not zlib: raise ImportError("cannot z-compress zlib unavailable")
         if isUnicode(text):
             text = text.encode('utf8')
         return zlib.compress(text)
     def decode(self, encoded):
-        from reportlab.lib.utils import import_zlib
-        zlib = import_zlib()
-        if not zlib: raise ImportError("cannot z-decompress zlib unavailable")
         return zlib.decompress(encoded)
 
 # need only one of these, unless we implement parameters later
@@ -2170,8 +2164,6 @@
         if fp:
             self.loadImageFromJPEG(fp)
         else:
-            zlib = import_zlib()
-            if not zlib: return
             self.width, self.height = im.getSize()
             raw = im.getRGBData()
             #assert len(raw) == self.width*self.height, "Wrong amount of data for image expected %sx%s=%s got %s" % (self.width,self.height,self.width*self.height,len(raw))
--- a/src/reportlab/pdfgen/canvas.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/pdfgen/canvas.py	Mon Feb 28 11:28:14 2022 +0000
@@ -9,7 +9,6 @@
 __all__ = ['Canvas']
 ENABLE_TRACKING = 1 # turn this off to do profile testing w/o tracking
 
-import sys
 import re
 import hashlib
 from string import digits
@@ -20,12 +19,11 @@
 from reportlab.pdfgen  import pathobject
 from reportlab.pdfgen.textobject import PDFTextObject, _PDFColorSetter
 from reportlab.lib.colors import black, _chooseEnforceColorSpace, Color, CMYKColor, toColor
-from reportlab.lib.utils import import_zlib, ImageReader, isSeq, isStr, isUnicode, _digester, asUnicode
+from reportlab.lib.utils import ImageReader, isSeq, isStr, isUnicode, _digester, asUnicode
 from reportlab.lib.rl_accel import fp_str, escapePDF
 from reportlab.lib.boxstuff import aspectRatioFix
 
 digitPat = re.compile(r'\d')  #used in decimal alignment
-zlib = import_zlib()
 
 # Robert Kern
 # Constants for closing paths.
@@ -1606,7 +1604,7 @@
 
     def drawRightString(self, x, y, text, mode=None, charSpace=0, direction=None, wordSpace=None):
         """Draws a string right-aligned with the x coordinate"""
-        if sys.version_info[0] == 3 and not isinstance(text, str):
+        if not isinstance(text, str):
             text = text.decode('utf-8')
         width = self.stringWidth(text, self._fontname, self._fontsize)
         if charSpace: width += (len(text)-1)*charSpace
@@ -1625,7 +1623,7 @@
         """Draws a string centred on the x coordinate. 
         
         We're British, dammit, and proud of our spelling!"""
-        if sys.version_info[0] == 3 and not isinstance(text, str):
+        if not isinstance(text, str):
             text = text.decode('utf-8')
         width = self.stringWidth(text, self._fontname, self._fontsize)
         if charSpace: width += (len(text)-1)*charSpace
@@ -1822,10 +1820,7 @@
         This applies to all subsequent pages, or until setPageCompression()
         is next called."""
         if pageCompression is None: pageCompression = rl_config.pageCompression
-        if pageCompression and not zlib:
-            self._pageCompression = 0
-        else:
-            self._pageCompression = pageCompression
+        self._pageCompression = pageCompression
         self._doc.setCompression(self._pageCompression)
 
     def setPageDuration(self, duration=None):
--- a/src/reportlab/pdfgen/pdfimages.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/pdfgen/pdfimages.py	Mon Feb 28 11:28:14 2022 +0000
@@ -11,7 +11,7 @@
 from reportlab import rl_config
 from reportlab.pdfbase import pdfutils
 from reportlab.pdfbase import pdfdoc
-from reportlab.lib.utils import import_zlib, haveImages, isStr
+from reportlab.lib.utils import haveImages, isStr
 from reportlab.lib.rl_accel import fp_str, asciiBase85Encode
 from reportlab.lib.boxstuff import aspectRatioFix
 
@@ -74,8 +74,6 @@
     def cache_imagedata(self):
         image = self.image
         if not pdfutils.cachedImageExists(image):
-            zlib = import_zlib()
-            if not zlib: return
             if not haveImages: return
             pdfutils.cacheImageFile(image)
 
@@ -87,14 +85,13 @@
         return imagedata
 
     def PIL_imagedata(self):
+        import zlib
         image = self.image
         if image.format=='JPEG':
             fp=image.fp
             fp.seek(0)
             return self._jpg_imagedata(fp)
         self.source = 'PIL'
-        zlib = import_zlib()
-        if not zlib: return
 
         bpc = 8
         # Use the colorSpace in the image
--- a/src/reportlab/platypus/paraparser.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/platypus/paraparser.py	Mon Feb 28 11:28:14 2022 +0000
@@ -3083,8 +3083,7 @@
     #----------------------------------------------------------------
 
     def __init__(self,verbose=0, caseSensitive=0, ignoreUnknownTags=1, crashOnError=True):
-        HTMLParser.__init__(self,
-            **(dict(convert_charrefs=False) if sys.version_info>=(3,4) else {}))
+        HTMLParser.__init__(self, **(dict(convert_charrefs=False)))
         self.verbose = verbose
         #HTMLParser is case insenstive anyway, but the rml interface still needs this
         #all start/end_ methods should have a lower case version for HMTMParser
--- a/src/reportlab/rl_settings.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/src/reportlab/rl_settings.py	Mon Feb 28 11:28:14 2022 +0000
@@ -15,7 +15,6 @@
 useA85
 defaultPageSize
 defaultImageCaching
-ZLIB_WARNINGS
 warnOnMissingFontGlyphs
 verbose
 showBoundary
@@ -78,7 +77,6 @@
 useA85 =                    1                       #set to 0 to disable Ascii Base 85 stream filters
 defaultPageSize =           'A4'                    #default page size
 defaultImageCaching =       0                       #set to zero to remove those annoying cached images
-ZLIB_WARNINGS =             1
 warnOnMissingFontGlyphs =   0                       #if 1, warns of each missing glyph
 verbose =                   0
 showBoundary =              0                       # turns on and off boundary behaviour in Drawing
--- a/tests/test_paragraphs.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/tests/test_paragraphs.py	Mon Feb 28 11:28:14 2022 +0000
@@ -390,11 +390,6 @@
             template.build(story)
 
         def testRTLBullets(self):
-            try:
-                import mwlib.ext
-            except ImportError:
-                pass
-
             font_name = getAFont()
             doc = SimpleDocTemplate(outputfile('test_rtl_bullets.pdf'),showBoundary=True)
             p_style = ParagraphStyle('default')
--- a/tests/test_renderPS.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/tests/test_renderPS.py	Mon Feb 28 11:28:14 2022 +0000
@@ -1,24 +1,11 @@
 #!/usr/bin/env python
 from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation
 setOutDir(__name__)
-import sys
 from xml.dom import minidom
-from xml.sax._exceptions import SAXReaderNotAvailable
 import unittest
 from reportlab.graphics.shapes import *
 from reportlab.graphics import renderPS
 
-def warnIgnoredRestofTest():
-    "Raise a warning (if possible) about a not fully completed test."
-
-    version = sys.version_info[:2]
-    msg = "XML parser not found - consider installing expat! Rest of test(s) ignored!"
-    if version >= (2, 1):
-        import warnings
-        warnings.warn(msg)
-    else:
-        # should better also be printed only once...
-        print(msg)
 
 class RenderPSSimpleTestCase(unittest.TestCase):
     "Testing renderPS module."
--- a/tests/test_renderSVG.py	Fri Feb 18 11:01:32 2022 +0000
+++ b/tests/test_renderSVG.py	Mon Feb 28 11:28:14 2022 +0000
@@ -1,34 +1,11 @@
 #!/usr/bin/env python
 from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation
 setOutDir(__name__)
-import sys
 from xml.dom import minidom
-from xml.sax._exceptions import SAXReaderNotAvailable
 import unittest
 from reportlab.graphics.shapes import *
 from reportlab.graphics import renderSVG
 
-def warnIgnoredRestofTest():
-    "Raise a warning (if possible) about a not fully completed test."
-
-    version = sys.version_info[:2]
-    msg = "XML parser not found - consider installing expat! Rest of test(s) ignored!"
-    if version >= (2, 1):
-        import warnings
-        warnings.warn(msg)
-    else:
-        # should better also be printed only once...
-        print(msg)
-
-# Check if we have a default XML parser available or not.
-try:
-    import xml
-    from xml.sax import make_parser
-    p = xml.sax.make_parser()
-    HAVE_XML_PARSER = 1
-except SAXReaderNotAvailable:
-    HAVE_XML_PARSER = 0
-
 def load(path):
     "Helper function to read the generated SVG again."
 
@@ -49,10 +26,6 @@
         d.add(String(100, 0, "bar"))
         renderSVG.drawToFile(d, path)
 
-        if not HAVE_XML_PARSER:
-            warnIgnoredRestofTest()
-            return
-
         svg = load(path)
         fg = svg.getElementsByTagName('g')[0]           # flipping group
         dg = fg.getElementsByTagName('g')[0]            # diagram group
@@ -74,10 +47,6 @@
         d.add(g)
         renderSVG.drawToFile(d, path)
 
-        if not HAVE_XML_PARSER:
-            warnIgnoredRestofTest()
-            return
-
         svg = load(path)
         fg = svg.getElementsByTagName('g')[0]           # flipping group
         dg = fg.getElementsByTagName('g')[0]            # diagram group
@@ -103,10 +72,6 @@
         d.add(g)
         renderSVG.drawToFile(d, path)
 
-        if not HAVE_XML_PARSER:
-            warnIgnoredRestofTest()
-            return
-
         svg = load(path)
         fg = svg.getElementsByTagName('g')[0]           # flipping group
         dg = fg.getElementsByTagName('g')[0]            # diagram group
@@ -185,10 +150,6 @@
         d.add(String(100, 0, "bar"))
         renderSVG.drawToFile(d, path)
 
-        if not HAVE_XML_PARSER:
-            warnIgnoredRestofTest()
-            return
-
         svg = load(path)
         fg = svg.getElementsByTagName('g')[0]           # flipping group
         dg = fg.getElementsByTagName('g')[0]            # diagram group