Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-reportlab for 
openSUSE:Factory checked in at 2026-06-15 19:43:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-reportlab (Old)
 and      /work/SRC/openSUSE:Factory/.python-reportlab.new.1981 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-reportlab"

Mon Jun 15 19:43:58 2026 rev:44 rq:1359295 version:4.5.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-reportlab/python-reportlab.changes        
2026-01-28 15:15:04.881811068 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-reportlab.new.1981/python-reportlab.changes  
    2026-06-15 19:47:12.284870450 +0200
@@ -1,0 +2,19 @@
+Sun Jun 14 18:54:27 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 4.5.1:
+  * fix tests/runAll.py to avoid issues with sys.args
+  * fix no such attribute in lib.utils.rl_warn
+  * SVGCanvas new keyword argument fontSizer defaulting to 'px'
+  * add rl_warn to lib/utils.py and use in tables (via extra
+    allowTableBoundsErrors bits).
+  * rl_config.register_reset can have callback and now handles
+    methods
+  * shapes.py fix Group.asDrawing
+  * fix __rl_get_module__ for Python 3.15
+  * moved extformat.py elsewhere
+  * added combineTransforms
+  * improve colors.cssParse
+  * change None to mean no-draw in acroform.py
+  * extend allowTableBoundsErrors scope
+
+-------------------------------------------------------------------

Old:
----
  reportlab-4.4.9.tar.gz

New:
----
  reportlab-4.5.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-reportlab.spec ++++++
--- /var/tmp/diff_new_pack.Po6OYr/_old  2026-06-15 19:47:13.308913365 +0200
+++ /var/tmp/diff_new_pack.Po6OYr/_new  2026-06-15 19:47:13.312913533 +0200
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-reportlab
-Version:        4.4.9
+Version:        4.5.1
 Release:        0
 Summary:        The Reportlab Toolkit
 License:        BSD-3-Clause


++++++ reportlab-4.4.9.tar.gz -> reportlab-4.5.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/CHANGES.md 
new/reportlab-4.5.1/CHANGES.md
--- old/reportlab-4.4.9/CHANGES.md      2026-01-15 10:17:03.000000000 +0100
+++ new/reportlab-4.5.1/CHANGES.md      2026-05-12 11:14:40.000000000 +0200
@@ -11,6 +11,37 @@
 The contributors lists are in no order and apologies to those accidentally not
 mentioned. If we missed you, please let us know!
 
+
+CHANGES  4.5.1   12/05/2026
+---------------------------
+    * fix tests/runAll.py to avoid issues with sys.args
+    * release 4.5.1
+
+CHANGES  4.5.1a2 08/05/2026
+---------------------------
+    * fix no such attribute in lib.utils.rl_warn
+
+CHANGES  4.5.1a1 05/05/2026
+---------------------------
+    * SVGCanvas new keyword argument fontSizer defaulting to 'px'
+    * add rl_warn to lib/utils.py and use in tables (via extra 
allowTableBoundsErrors bits).
+    * rl_config.register_reset can have callback and now handles methods
+
+CHANGES  4.5.0   27/04/2026
+---------------------------
+    * shapes.py fix Group.asDrawing
+    * fix __rl_get_module__ for Python 3.15
+    * moved extformat.py elsewhere
+    * added combineTransforms
+    * improve colors.cssParse suggested by moritz dot schreiber at tu-ilmenau 
dot de
+    * change None to mean no-draw in acroform.py: Cozmin Velciu cozmin dot 
velciu at gmail dot com
+    * extend allowTableBoundsErrors scope: James Beith james dot beith at 
kraken dot tec
+
+CHANGES  4.4.10  12/02/2026
+---------------------------
+    * fix security issue found by Ethan Kim lt ethan 4t cremit d0t io gt
+    * add a User-Agent header in rlUrlRead to overcome some anti bot actions
+
 CHANGES  4.4.9   15/01/2026
 ---------------------------
     * remove unwanted debug
@@ -18,6 +49,7 @@
 CHANGES  4.4.8   15/01/2026
 ---------------------------
     * fix callback security hole reported by Pedro "gankd"  lt pedrovgcruz at 
icloud dot com gt
+    * https://www.linkedin.com/in/pedro-cruz-967b2524b/
 
 CHANGES  4.4.7   21/12/2025
 ---------------------------
@@ -730,6 +762,7 @@
        * Axel P. Kielhorn
        * ben @ readingtype.org.uk
        * Chris Jerdonek cjerdonek @ bitbucket
+    * Cozmin Velciu cozmin dot velciu at gmail dot com
        * Dan Palmer danpalmer @ bitbucket
        * Garry Williams gary_williams @ bit_bucket
        * Greg Svitak
@@ -742,6 +775,8 @@
        * Martin J. Laubach bitbucket issue #140
        * Moritz Pfeiffer moritzpfeiffer @ bitbucket
        * Raji Sundar
+    * Schreiber Moritz TU Ilmenau
+    * James Beith james dot beith at kraken dot tec
        * Silas Sewell silassewell @ bitbucket
        * simonkagwe @ bitbucket
        * Tom Alexander @ bitbucket
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/PKG-INFO new/reportlab-4.5.1/PKG-INFO
--- old/reportlab-4.4.9/PKG-INFO        2026-01-15 10:23:12.014963200 +0100
+++ new/reportlab-4.5.1/PKG-INFO        2026-05-12 11:20:50.736108300 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: reportlab
-Version: 4.4.9
+Version: 4.5.1
 Summary: The Reportlab Toolkit
 Home-page: https://www.reportlab.com/
 Author: Andy Robinson, Robin Becker, the ReportLab team and the community
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/__init__.py 
new/reportlab-4.5.1/src/reportlab/__init__.py
--- old/reportlab-4.4.9/src/reportlab/__init__.py       2026-01-15 
10:17:13.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/__init__.py       2026-05-12 
11:14:11.000000000 +0200
@@ -1,9 +1,9 @@
-#Copyright ReportLab Europe Ltd. 2000-2023
+#Copyright ReportLab Europe Ltd. 2000-2026
 #see license.txt for license details
 __doc__="""The Reportlab PDF generation library."""
-Version = "4.4.9"
+Version = "4.5.1"
 __version__=Version
-__date__='20260115'
+__date__='20260512'
 
 import sys, os
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/reportlab-4.4.9/src/reportlab/graphics/charts/utils.py 
new/reportlab-4.5.1/src/reportlab/graphics/charts/utils.py
--- old/reportlab-4.4.9/src/reportlab/graphics/charts/utils.py  2025-03-24 
13:48:38.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/graphics/charts/utils.py  2026-01-21 
12:29:52.000000000 +0100
@@ -1,8 +1,30 @@
-#Copyright ReportLab Europe Ltd. 2000-2017
+#Copyright ReportLab Europe Ltd. 2000-2026
 #see license.txt for license details
 #history 
https://hg.reportlab.com/hg-public/reportlab/log/tip/src/reportlab/graphics/charts/utils.py
+__all__ = (
+            'angle2corner',
+            'angle2dir',
+            'boxCornerCoords',
+            'CustomDrawChanger',
+            'DrawTimeCollector',
+            'FillPairedData',
+            'find_good_grid',
+            'find_interval',
+            'findNones',
+            'lineSegmentIntersect',
+            'makeCircularString',
+            'maverage',
+            'mkTimeTuple',
+            'nextRoundNumber',
+            'pairFixNones',
+            'pairMaverage',
+            'seconds2str',
+            'str2seconds',
+            'ticks',
+            'xyDist',
+            )
 
-__version__='3.3.0'
+__version__='3.4.8'
 __doc__="Utilities used here and there."
 from time import mktime, gmtime, strftime
 from math import log10, pi, floor, sin, cos, hypot
@@ -393,3 +415,69 @@
     def __init__(self,v,other=0):
         list.__init__(self,v)
         self.other = other
+
+_arange2dirs = [
+        (-1,22.5,'e'),
+        (22.5,67.5,'ne'),
+        (67.5,112.5,'n'),
+        (112.5,157.5,'nw'),
+        (157.5,202.5,'w'),
+        (202.5,247.5,'sw'),
+        (247.5,292.5,'s'),
+        (292.5,337.5,'se'),
+        (337.5,361,'e'),
+        ]
+def angle2dir(angle):
+    '''converts mathematical angle to a compass point from a math angle where
+    0 degrees lies along the x axis ie east==0 degrees
+
+    >>> [angle2dir(_) for _ in [0,360]+[__[0] for __ in _arange2dirs]+[__[1] 
for __ in _arange2dirs]]
+    ['e', 'e', 'e', 'e', 'ne', 'n', 'nw', 'w', 'sw', 's', 'se', 'e', 'ne', 
'n', 'nw', 'w', 'sw', 's', 'se', 'e']
+    '''
+    a = angle % 360
+    for lo, hi, d in _arange2dirs:
+        if lo<a<=hi: return d
+    return 'c'
+    #I tested the bisect version below; it works, but is fractionally slower
+    #import bisect
+    #_elemk = lambda _: _[1]
+    #return _arange2dirs[bisect.bisect_left(_arange2dirs,angle % 
360,key=_elemk)][2]
+
+_cornerNames=dict(e='w',ne='sw',n='s',nw='se',w='e',sw='ne',s='n',se='nw',c='c')
+def angle2corner(angle):
+    '''converts a direction angle to a box corner name effectively the reverse 
direction
+    >>> [angle2corner(_) for _ in [0,360]+[__[0] for __ in 
_arange2dirs]+[__[1] for __ in _arange2dirs]]
+    ['w', 'w', 'w', 'w', 'sw', 's', 'se', 'e', 'ne', 'n', 'nw', 'w', 'sw', 
's', 'se', 'e', 'ne', 'n', 'nw', 'w']
+    '''
+    return _cornerNames[angle2dir(angle)]
+
+def boxCornerCoords(bb, cn):
+    '''return (x,y) for bounding box and corner name
+    >>> bb=(1,0,0,1);[boxCornerCoords(bb,_) for _ in 'c n ne e se s sw w 
nw'.split()]
+    [(0.5, 0.5), (0.5, 1), (1, 1), (1, 0.5), (1, 0), (0.5, 0), (0, 0), (0, 
0.5), (0, 1)]
+    >>> boxCornerCoords(bb,'z')
+    Traceback (most recent call last):
+        ...
+    ValueError: invalid box corner name 'z'
+    '''
+    if bb[0]>bb[2] or bb[1]>bb[3]:
+        bb = 
(min(bb[0],bb[2]),min(bb[1],bb[3]),max(bb[0],bb[2]),max(bb[1],bb[3]))
+    if cn not in ('n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'c'):
+        raise ValueError(f'invalid box corner name {cn!r}')
+    if cn in ('c','s','n'):
+        x = (bb[0]+bb[2])/2
+    elif cn in ('ne','e','se'):
+        x = bb[2]
+    else:
+        x = bb[0]
+    if cn in ('e','c','w'):
+        y = (bb[1]+bb[3])/2
+    elif cn in ('nw','n','ne'):
+            y = bb[3]
+    else:
+        y = bb[1]
+    return x, y
+
+if __name__=='__main__':
+    import doctest
+    doctest.testmod()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/graphics/renderSVG.py 
new/reportlab-4.5.1/src/reportlab/graphics/renderSVG.py
--- old/reportlab-4.4.9/src/reportlab/graphics/renderSVG.py     2024-12-13 
09:46:59.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/graphics/renderSVG.py     2026-05-11 
16:12:06.000000000 +0200
@@ -157,12 +157,20 @@
         extraXmlDecl = ''   use to add extra xml declarations
         scaleGroupId = ''   id of an extra group to add around the drawing to 
allow easy scaling
         svgAttrs = {}       dictionary of attributes to be applied to the svg 
tag itself
+        fontSizer = 'px'    a string unit or acallable that returns a string 
fontSize value
         '''
         self.verbose = verbose
         self.encoding = codecs.lookup(encoding).name
         self.bom = bom
         useClip = kwds.pop('useClip',False)
         self.fontHacks = kwds.pop('fontHacks',{})
+        fz = kwds.pop('fontSizer','px')
+        if isinstance(fz,str):
+            self.fontSizer = lambda v: f'%s{fz}' % v
+        elif callable(fz):
+            self.fontSizer = fz
+        else:
+            raise ValueError(f'{fontSizer=} should be a str unit eg px/pt or a 
callable that returns a string')
         self.extraXmlDecl = kwds.pop('extraXmlDecl','')
         scaleGroupId = kwds.pop('scaleGroupId','')
         self._fillMode = FILL_EVEN_ODD
@@ -414,7 +422,7 @@
                         style[a] = v
             if 'font-family' not in style:
                 style['font-family'] = font
-            style['font-size'] = '%spx' % fontSize
+            style['font-size'] = self.fontSizer(fontSize)
 
     def _add_link(self, dom_object, link_info) :
         assert isinstance(link_info, dict)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/graphics/shapes.py 
new/reportlab-4.5.1/src/reportlab/graphics/shapes.py
--- old/reportlab-4.4.9/src/reportlab/graphics/shapes.py        2025-02-13 
14:38:28.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/graphics/shapes.py        2026-03-13 
11:13:42.000000000 +0100
@@ -455,7 +455,7 @@
             After calling this the instance will be a drawing!
         """
         self.__class__ = Drawing
-        self._attrMap.update(self._xtraAttrMap)
+        self._attrMap.update(getattr(self,'_xtraAttrMap',{}))
         self.width = width
         self.height = height
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/graphics/transform.py 
new/reportlab-4.5.1/src/reportlab/graphics/transform.py
--- old/reportlab-4.4.9/src/reportlab/graphics/transform.py     2025-08-21 
11:46:51.000000000 +0200
+++ new/reportlab-4.5.1/src/reportlab/graphics/transform.py     2026-03-12 
09:20:47.000000000 +0100
@@ -7,6 +7,7 @@
     'skewX',
     'skewY',
     'mmult',
+    'combineTransforms',
     'inverse',
     'zTransformPoint',
     'transformPoint',
@@ -57,6 +58,23 @@
             A[0]*B[4] + A[2]*B[5] + A[4],
             A[1]*B[4] + A[3]*B[5] + A[5])
 
+def combineTransforms(*T):
+    '''
+    given transform matrices in the order they should be applied generate
+    a combined transform.
+
+    combineTransforms(T0,T1,T2) == mmult(T2,mmult(T1,T0))
+                                == T2*T1*T0
+    so that T0 is applied first, then T1 and finally T2.
+    '''
+    nT = len(T)
+    return (
+            mmult(T[1],T[0]) if nT==2 
+            else mmult(combineTransforms(*T[2:]), mmult(T[1],T[0])) if nT>2
+            else T[0] if nT==1
+            else nullTransform()
+            )
+
 def inverse(A):
     "For A affine 2D represented as 6vec return 6vec version of A**(-1)"
     # I checked this RGB
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/lib/colors.py 
new/reportlab-4.5.1/src/reportlab/lib/colors.py
--- old/reportlab-4.4.9/src/reportlab/lib/colors.py     2024-12-13 
09:46:59.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/lib/colors.py     2026-05-01 
12:15:44.000000000 +0200
@@ -769,15 +769,37 @@
     return hue2rgb(m1, m2, h+1./3),hue2rgb(m1, m2, h),hue2rgb(m1, m2, h-1./3)
 
 import re
-_re_css = re.compile(r'^\s*(pcmyk|cmyk|rgb|hsl)(a|)\s*\(\s*([^)]*)\)\s*$')
+_re_css_func = re.compile(r'^\s*(pcmyk|cmyk|rgb|hsl)(a|)\s*(.*)\s*$')
+_re_css_args = 
re.compile(r'^\(\s*([^)/]*)(?:\s*/\s*(\d{0,3}(?:\.\d*|)%?)|)\)$')
 class cssParse:
-    def pcVal(self,v):
+    '''
+    best effort convert css like rgb/rgba colours into reportlab Color
+    we support functions rgb/a, cmyk/a, pcmyk/a & hsl/a
+
+    rgb & rgba have special treatment if the r g b arguments have a 
+    decimal point and no % signs. In that case the r g b values are
+    treated as simple floats and must lie in [0,1]. Otherwise we assume
+    the r g b values will be treated as 255 fractions ie 1 --> 1/255.
+
+    if arguments have a percentage sign appended then the values are first
+    divided by 100.
+
+    The alpha values can be specified using the <func>a form and adding
+    an extra argument or using the simple form and adding /<alpha> before
+    the closing parenthesis. The alpha values can have decimal points and
+    percent signs as desired. It's not clear if we should force rgb alpha
+    values into 8 bit form.
+
+    Arguments can be separated by comma or space.
+    '''
+    def pcVal(self,v,n='argument'):
         v = v.strip()
         try:
-            c=float(v[:-1])
-            c=min(100,max(0,c))/100.
+            c=float(v.rstrip('%'))
+            if c<0 or c>100: raise ValueError
+            return c/100.
         except:
-            raise ValueError('bad percentage argument value %r in css color 
%r' % (v,self.s))
+            raise ValueError(f'bad {n} percentage value {v!r} in css color 
{self.s!r}')
         return c
 
     def rgbPcVal(self,v):
@@ -787,10 +809,19 @@
         v = v.strip()
         try:
             c=float(v)
-            if 0<c<=1: c *= 255
-            return int(min(255,max(0,c)))/255.
+            #if 0<c<=1: c *= 255
+            if c<0 or c>255: raise ValueError
+            return int(c)/255.
         except:
-            raise ValueError('bad argument value %r in css color %r' % 
(v,self.s))
+            raise ValueError(f'bad argument value {v!r} in css color 
{self.s!r}')
+
+    def floatVal(self,v):
+        try:
+            c=float(v)
+            if c<0 or c>1: raise ValueError
+            return c
+        except:
+            raise ValueError(f'bad argument value {v!r} in css color 
{self.s!r}')
 
     def hueVal(self,v):
         v = v.strip()
@@ -798,31 +829,46 @@
             c=float(v)
             return ((c%360+360)%360)/360.
         except:
-            raise ValueError('bad hue argument value %r in css color %r' % 
(v,self.s))
+            raise ValueError(f'bad hue argument value {v!r} in css color 
{self.s!r}')
 
     def alphaVal(self,v,c=1,n='alpha'):
         try:
             a = float(v)
-            return min(c,max(0,a))
+            if a>c or a<0: raise VaueError
+            return a
         except:
-            raise ValueError('bad %s argument value %r in css color %r' % 
(n,v,self.s))
+            raise ValueError(f'bad {n} argument value {v!r} in css color 
{self.s!r}')
 
     _n_c = 
dict(pcmyk=(4,100,True,False),cmyk=(4,1,True,False),hsl=(3,1,False,True),rgb=(3,1,False,False))
 
     def __call__(self,s):
-        n = _re_css.match(s)
-        if not n: return
+        f = _re_css_func.match(s)
+        if not f: return    #we didn't match the start of a css func
         self.s = s
-        b,c,cmyk,hsl = self._n_c[n.group(1)]
-        ha = n.group(2)
-        n = n.group(3).split(',')   #strip parens and split on comma
+        b,c,cmyk,hsl = self._n_c[f.group(1)]
+        n = _re_css_args.match(f.group(3))
+        if not n: raise ValueError(f'css color {s!r} has bad argument list 
{f.group(3)!r}')
+        ha = f.group(2)
+        ha1 = n.group(2)
+        if ha and ha1:
+            raise ValueError(f'css color {s!r} has both inline alpha and 
/alpha%')
+        n = n.group(1)
+        n = n.split(',') if ',' in n else n.strip().split() #split on comma or 
spaces
         if len(n)!=(b+(ha and 1 or 0)):
-            raise ValueError('css color %r has wrong number of components' % s)
+            raise ValueError(f'css color {s!r} has wrong number of components')
         if ha:
-            n,a = n[:b],self.alphaVal(n[b],c)
+            a = n[b]
+            n = n[:b]
+            a = self.pcVal(a,'alpha') if '%' in a else self.alphaVal(a,c)
+        elif ha1:
+            a = self.pcVal(ha1,f'/{ha1}') if '%' in ha1 else 
self.alphaVal(ha1,c)
         else:
             a = c
 
+        pc = ''.join(n)
+        dp = '.' in pc
+        pc = '%' in pc
+
         if cmyk:
             C = self.alphaVal(n[0],c,'cyan')
             M = self.alphaVal(n[1],c,'magenta')
@@ -832,8 +878,11 @@
         else:
             if hsl:
                 R,G,B= 
hsl2rgb(self.hueVal(n[0]),self.pcVal(n[1]),self.pcVal(n[2]))
+            elif dp and not pc:
+                R,G,B = map(self.floatVal,n)
             else:
-                R,G,B = list(map('%' in n[0] and self.rgbPcVal or 
self.rgbVal,n))
+                R,G,B = list(map(pc and self.rgbPcVal or self.rgbVal,n))
+                #a = int(a*255+0.5)/255.
 
             return Color(R,G,B,a)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/lib/extformat.py 
new/reportlab-4.5.1/src/reportlab/lib/extformat.py
--- old/reportlab-4.4.9/src/reportlab/lib/extformat.py  2024-12-13 
09:47:00.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/lib/extformat.py  1970-01-01 
01:00:00.000000000 +0100
@@ -1,91 +0,0 @@
-#Copyright ReportLab Europe Ltd. 2000-2017
-#see license.txt for license details
-__version__='3.3.0'
-__doc__='''Apparently not used anywhere, purpose unknown!'''
-try:
-       from tokenize import tokenprog
-except ImportError:
-       from tokenize import Token
-       import re
-       tokenprog = re.compile(Token)
-       del Token, re
-import sys
-
-def _matchorfail(text, pos):
-       match = tokenprog.match(text, pos)
-       if match is None: raise ValueError(text, pos)
-       return match, match.end()
-
-'''
-       Extended dictionary formatting
-       We allow expressions in the parentheses instead of
-       just a simple variable.
-'''
-def dictformat(_format, L={}, G={}):
-       format = _format
-
-       S = {}
-       chunks = []
-       pos = 0
-       n = 0
-
-       while 1:
-               pc = format.find("%", pos)
-               if pc < 0: break
-               nextchar = format[pc+1]
-
-               if nextchar == "(":
-                       chunks.append(format[pos:pc])
-                       pos, level = pc+2, 1
-                       while level:
-                               match, pos = _matchorfail(format, pos)
-                               tstart, tend = match.regs[3]
-                               token = format[tstart:tend]
-                               if token == "(": level = level+1
-                               elif token == ")": level = level-1
-                       vname = '__superformat_%d' % n
-                       n += 1
-                       S[vname] = eval(format[pc+2:pos-1],G,L)
-                       chunks.append('%%(%s)' % vname)
-               else:
-                       nc = pc+1+(nextchar=="%")
-                       chunks.append(format[pos:nc])
-                       pos = nc
-
-       if pos < len(format): chunks.append(format[pos:])
-       return (''.join(chunks)) % S
-
-def magicformat(format):
-       """Evaluate and substitute the appropriate parts of the string."""
-       frame = sys._getframe(1)
-       return dictformat(format,frame.f_locals, frame.f_globals)
-
-if __name__=='__main__':
-       from reportlab.lib.formatters import DecimalFormatter
-       _DF={}
-       def df(n,dp=2,ds='.',ts=','):
-               try:
-                       _df = _DF[dp,ds]
-               except KeyError:
-                       _df = _DF[dp,ds] = 
DecimalFormatter(places=dp,decimalSep=ds,thousandSep=ts)
-               return _df(n)
-
-       from reportlab.lib.extformat import magicformat
-
-       Z={'abc': ('ab','c')}
-       x = 300000.23
-       percent=79.2
-       class dingo:
-               a=3
-       print((magicformat('''
-$%%(df(x,dp=3))s --> $%(df(x,dp=3))s
-$%%(df(x,dp=2,ds=',',ts='.'))s --> $%(df(x,dp=2,ds=',',ts='.'))s
-%%(percent).2f%%%% --> %(percent).2f%%
-%%(dingo.a)s --> %(dingo.a)s
-%%(Z['abc'][0])s --> %(Z['abc'][0])s
-''')))
-       def func0(aa=1):
-               def func1(bb=2):
-                       print((magicformat('bb=%(bb)s Z=%(Z)r')))
-               func1('BB')
-       func0('AA')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/lib/rl_safe_eval.py 
new/reportlab-4.5.1/src/reportlab/lib/rl_safe_eval.py
--- old/reportlab-4.4.9/src/reportlab/lib/rl_safe_eval.py       2024-12-13 
09:47:00.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/lib/rl_safe_eval.py       2026-02-12 
10:24:11.000000000 +0100
@@ -666,16 +666,12 @@
                """Allow function definitions (`def`) with some restrictions."""
                self.isAllowedName(node, node.name)
                self.check_function_argument_names(node)
-
-               return node
+               return self.visit_children(node)
 
        def visit_Lambda(self, node):
                """Allow lambda with some restrictions."""
                self.check_function_argument_names(node)
-
-               node = self.visit_children(node)
-
-               return node
+               return self.visit_children(node)
 
        def visit_ClassDef(self, node):
                """Check the name of a class definition."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/lib/utils.py 
new/reportlab-4.5.1/src/reportlab/lib/utils.py
--- old/reportlab-4.4.9/src/reportlab/lib/utils.py      2026-01-14 
12:49:17.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/lib/utils.py      2026-05-08 
11:06:21.000000000 +0200
@@ -471,9 +471,11 @@
         return BytesIO(s)
 
 from urllib.parse import unquote, urlparse
-from urllib.request import urlopen
-def rlUrlRead(name):
-    return urlopen(name).read()
+from urllib.request import urlopen, Request
+def rlUrlRead(name, headers=None):
+    if headers==None: headers = {}
+    headers.setdefault('User-Agent','ReportLabAgent')
+    return urlopen(Request(name,headers=headers)).read()
 
 def open_for_read(name,mode='b'):
     #auto initialized function`
@@ -581,7 +583,9 @@
         path = os.path.join(dir,name+ext)
         if os.path.isfile(path):
             spec = importlib_util.spec_from_file_location(name,path)
-            return spec.loader.load_module()
+            module = importlib_util.module_from_spec(spec)
+            spec.loader.exec_module(module)
+            return module
     raise ImportError('no suitable file found')
 
 def rl_get_module(name,dir):
@@ -1353,3 +1357,32 @@
 
     def get(self,k,default=None):
         return self.store.get(k,default)
+
+class rl_warn:
+    __shared_state = {} #resistance is futile we are a BORG
+    def __init__(self):
+        self.__dict__ = self.__shared_state
+
+    def __call__(self,message):
+        if not self.__shared_state:
+            self.__warnings_seen = {}
+            from reportlab.rl_config import register_reset
+            register_reset(self.__reset)
+            import inspect, warnings
+            self.__inspect = inspect
+            self.__warnings = warnings
+
+        if message not in self.__warnings_seen:
+            self.__warnings.warn(message,stacklevel=2)
+        frame = self.__inspect.stack()[1]
+        self.__warnings_seen.setdefault(message,set()).add(
+                f'in {frame.function} @ {frame.filename}:{frame.lineno}')
+
+    def __reset(self):
+        self.__warnings_seen.clear()
+
+    @property
+    def warnings_seen(self):
+        return self.__warnings_seen
+
+rl_warn = rl_warn()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/license.txt 
new/reportlab-4.5.1/src/reportlab/license.txt
--- old/reportlab-4.4.9/src/reportlab/license.txt       2024-12-13 
09:46:59.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/license.txt       1970-01-01 
01:00:00.000000000 +0100
@@ -1,29 +0,0 @@
-#####################################################################################
-#
-#      Copyright (c) 2000-2018, ReportLab Inc.
-#      All rights reserved.
-#
-#      Redistribution and use in source and binary forms, with or without 
modification,
-#      are permitted provided that the following conditions are met:
-#
-#              *       Redistributions of source code must retain the above 
copyright notice,
-#                      this list of conditions and the following disclaimer. 
-#              *       Redistributions in binary form must reproduce the above 
copyright notice,
-#                      this list of conditions and the following disclaimer in 
the documentation
-#                      and/or other materials provided with the distribution. 
-#              *       Neither the name of the company nor the names of its 
contributors may be
-#                      used to endorse or promote products derived from this 
software without
-#                      specific prior written permission. 
-#
-#      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
IS" AND
-#      ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
-#      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED.
-#      IN NO EVENT SHALL THE OFFICERS OR CONTRIBUTORS BE LIABLE FOR ANY 
DIRECT, INDIRECT,
-#      INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED
-#      TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS;
-#      OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
LIABILITY, WHETHER
-#      IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
OTHERWISE) ARISING
-#      IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
POSSIBILITY OF
-#      SUCH DAMAGE.
-#
-#####################################################################################
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/pdfbase/acroform.py 
new/reportlab-4.5.1/src/reportlab/pdfbase/acroform.py
--- old/reportlab-4.4.9/src/reportlab/pdfbase/acroform.py       2024-12-13 
09:47:00.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/pdfbase/acroform.py       2026-04-16 
09:57:11.000000000 +0200
@@ -7,6 +7,8 @@
 from reportlab.lib.utils import isStr, asNative
 import weakref
 
+_useDefault=object()
+
 visibilities = dict(
                 visible=0,
                 hidden=0,
@@ -133,6 +135,8 @@
         return obj._s
     return str(obj)
 
+_NotSet = object()
+
 class AcroForm(PDFObject):
     formFontNames = {
         "Helvetica": "Helv",
@@ -160,6 +164,10 @@
         self.extras = {}
 
     @property
+    def useDefault(self):
+        return _useDefault
+
+    @property
     def canv(self):
         _canv = self._canv()
         if _canv is None:
@@ -209,7 +217,7 @@
                 fillColor=None,
                 borderColor=None,
                 textColor=None,
-                borderWidth=1,
+                borderWidth=None,
                 borderStyle='solid',
                 size=20,
                 dashLen=3,
@@ -218,9 +226,10 @@
         ds = size
         if shape=='square':
             stream('q')
-            streamFill = self.streamFillColor(fillColor)
-            stream('1 g 1 G %(streamFill)s 0 0 %(size)s %(size)s re f')
-            if borderWidth!=None:
+            if opaqueColor(fillColor):
+                streamFill = self.streamFillColor(fillColor)
+                stream('1 g 1 G %(streamFill)s 0 0 %(size)s %(size)s re f')
+            if borderWidth is not None and opaqueColor(borderColor):
                 streamStroke = self.streamStrokeColor(borderColor)
                 hbw = borderWidth*0.5
                 smbw = size - borderWidth
@@ -234,7 +243,7 @@
                         dash = ''
                     stream('%(streamStroke)s%(dash)s %(borderWidth)s w %(hbw)s 
%(hbw)s %(smbw)s %(smbw)s re s')
 
-                if borderStyle in ('bevelled','inset'):
+                if borderStyle in ('bevelled','inset') and 
opaqueColor(fillColor):
                     _2bw = 2*borderWidth
                     sm2bw = size - _2bw
                     ds = sm2bw
@@ -249,12 +258,13 @@
         elif shape=='circle':
             cas = lambda _r,**_casKwds: 
self.circleArcStream(size,_r,**_casKwds)
             r = size*0.5
-            streamFill = self.streamFillColor(fillColor)
-            stream('q 1 g 1 G %(streamFill)s')
-            stream(cas(r))
-            stream('f')
-            stream('Q')
-            if borderWidth!=None:
+            if opaqueColor(fillColor):
+                streamFill = self.streamFillColor(fillColor)
+                stream('q 1 g 1 G %(streamFill)s')
+                stream(cas(r))
+                stream('f')
+                stream('Q')
+            if borderWidth is not None and opaqueColor(borderColor):
                 stream('q')
                 streamStroke = self.streamStrokeColor(borderColor)
                 hbw = borderWidth*0.5
@@ -270,7 +280,7 @@
                     stream(cas(r-hbw))
                     stream('s')
                 stream('Q')
-                if borderStyle in ('bevelled','inset'):
+                if borderStyle in ('bevelled','inset') and 
opaqueColor(fillColor):
                     _3bwh = 3*hbw
                     ds = size - _3bwh
                     bbs0 = Blacker(fillColor,0.5)
@@ -289,8 +299,12 @@
                     stream(cas(r-_3bwh,rotated=True,arcs=a1))
                     stream('S Q')
         if value=='Yes':
-            textFillColor = self.streamFillColor(textColor)
-            textStrokeColor = self.streamStrokeColor(textColor)
+            if opaqueColor(textColor):
+                textFillColor = self.streamFillColor(textColor)
+                textStrokeColor = self.streamStrokeColor(textColor)
+            else:
+                textFillColor = '0 g'
+                textStrokeColor = '0 G'
             stream('q %(textFillColor)s %(textStrokeColor)s')
             cbm = cbmarks[buttonStyle]
             if shape=='circle' and buttonStyle=='circle':
@@ -351,18 +365,57 @@
     def getRefStr(self,obj):
         return asNative(self.getRef(obj).format(self.canv._doc))
 
-    @staticmethod
-    def stdColors(t,b,f):
-        if isinstance(f,CMYKColor) or isinstance(t,CMYKColor) or 
isinstance(b,CMYKColor):
-            return (t or CMYKColor(0,0,0,0.9), b or  CMYKColor(0,0,0,0.9), f 
or CMYKColor(0.12,0.157,0,0))
-        else:
-            return (t or Color(0.1,0.1,0.1), b or Color(0.1,0.1,0.1), f or 
Color(0.8,0.843,1))
+    _defaultValues = dict(
+                        cmyk_textColor=CMYKColor(0,0,0,0.9),
+                        cmyk_borderColor=CMYKColor(0,0,0,0.9),
+                        cmyk_fillColor=CMYKColor(0.12,0.157,0,0),
+                        rgb_textColor=Color(0.1,0.1,0.1),
+                        rgb_borderColor=Color(0.1,0.1,0.1),
+                        rgb_fillColor=Color(0.8,0.843,1),
+                        borderWidth=1,
+                        )
+
+    def setDefault(self, name, value):
+        if '_defaultValues' not in self.__dict__:
+            self._defaultValues = self.__class__._defaultValues.clone()
+        
+        d = self._defaultValues()
+        if name in d.keys():
+            if '_' in name:
+                #its a colour name
+                if name[:4]=='cmyk':
+                    if isinstance(value,(CMYKColor,NoneType)):
+                        d[name] = value
+                        return
+                elif isinstance(value,(Color,NoneType)):
+                        d[name] = value
+                        return
+            elif isinstance(value(float,int,NoneType)):
+                #it's a number
+                d[name] = value
+                return
+            raise ValueError(f'Invalid value in 
acroForm.setDefault({name!r},{value!r})')
+        raise ValueError(f'Invalid name in 
acroForm.setDefault({name!r},{value!r})')
+                    
+    def getDefaults(self,textColor,borderColor,fillColor, borderWidth):
+        pfx = (isinstance(fillColor,CMYKColor)
+            or isinstance(textColor,CMYKColor)
+            or isinstance(borderColor,CMYKColor))
+        if not pfx: pfx = 
getattr(self.canv._enforceColorSpace,'__name__','_enforceRGB')!='_enforceRGB'
+            
+        pfx = 'cmyk_' if pfx else 'rgb_'
+        d = self._defaultValues
+        return (textColor if textColor is not _useDefault else 
d[pfx+'textColor'],
+                borderColor if borderColor is not _useDefault else 
d[pfx+'borderColor'],
+                fillColor if fillColor is not _useDefault else 
d[pfx+'fillColor'],
+                borderWidth if borderWidth is not _useDefault else 
d['borderWidth'],
+                )
     
     @staticmethod
     def varyColors(key,t,b,f):
         if key!='N':
             func = Whiter if key=='R' else Blacker
-            t,b,f = [func(c,0.9) for c in (t,b,f)]
+            t,b,f = [func(c,0.9) if c is not None else None for c in (t,b,f)]
         return t,b,f
 
     def 
checkForceBorder(self,x,y,width,height,forceBorder,shape,borderStyle,borderWidth,borderColor,fillColor):
@@ -370,7 +423,7 @@
             canv = self.canv
             canv.saveState()
             canv.resetTransforms()
-            if borderWidth!=None:
+            if borderWidth is not None and opaqueColor(borderColor):
                 hbw = 0.5*borderWidth
                 canv.setLineWidth(borderWidth)
                 canv.setStrokeColor(borderColor)
@@ -381,22 +434,24 @@
             height -= 2*hbw
             x += hbw
             y += hbw
-            canv.setFillColor(fillColor)
+            doFill = opaqueColor(fillColor)
+            if doFill:
+                canv.setFillColor(fillColor)
             if shape=='square':
-                canv.rect(x,y,width,height,stroke=s,fill=1)
+                canv.rect(x,y,width,height,stroke=s,fill=1 if doFill else 0)
             else:
                 r = min(width,height) * 0.5
-                canv.circle(x+r,y+r,r,stroke=s,fill=1)
+                canv.circle(x+r,y+r,r,stroke=s,fill=1 if doFill else 0)
             canv.restoreState()
 
     def checkbox(self,
                 checked=False,
                 buttonStyle='check',
                 shape='square',
-                fillColor=None,
-                borderColor=None,
-                textColor=None,
-                borderWidth=1,
+                fillColor=_useDefault,
+                borderColor=_useDefault,
+                textColor=_useDefault,
+                borderWidth=_useDefault,
                 borderStyle='solid',
                 size=20,
                 x=0,
@@ -410,7 +465,7 @@
                 dashLen = 3,
                 ):
         initialValue = 'Yes' if checked else 'Off'
-        
textColor,borderColor,fillColor=self.stdColors(textColor,borderColor,fillColor)
+        textColor,borderColor,fillColor,borderWidth = 
self.getDefaults(textColor,borderColor,fillColor,borderWidth)
         canv = self.canv
         if relative:
             x, y = self.canv.absolutePosition(x,y)
@@ -461,11 +516,11 @@
             name = 'AFF%03d' % len(self.fields)
         if borderWidth: CB['BS'] = bsPDF(borderWidth,borderStyle,dashLen)
         CB['T'] = PDFString(name)
-        MK = dict(
-                CA='(%s)' % ZDSyms[buttonStyle],
-                BC=PDFArray(self.colorTuple(borderColor)),
-                BG=PDFArray(self.colorTuple(fillColor)),
-                )
+        MK = dict(CA='(%s)' % ZDSyms[buttonStyle])
+        if borderColor is not None:
+            MK['BC'] = PDFArray(self.colorTuple(borderColor))
+        if fillColor is not None:
+            MK['BG'] = PDFArray(self.colorTuple(fillColor))
         CB['MK'] = PDFDictionary(MK)
         CB = PDFDictionary(CB)
         self.canv._addAnnotation(CB)
@@ -477,10 +532,10 @@
                 selected=False,
                 buttonStyle='circle',
                 shape='circle',
-                fillColor=None,
-                borderColor=None,
-                textColor=None,
-                borderWidth=1,
+                fillColor=_useDefault,
+                borderColor=_useDefault,
+                textColor=_useDefault,
+                borderWidth=_useDefault,
                 borderStyle='solid',
                 size=20,
                 x=0,
@@ -506,7 +561,7 @@
         if not value:
             raise ValueError('bad value %r for radio.%s' % (value,name))
         initialValue = value if selected else 'Off'
-        
textColor,borderColor,fillColor=self.stdColors(textColor,borderColor,fillColor)
+        textColor,borderColor,fillColor,borderWidth = 
self.getDefaults(textColor,borderColor,fillColor,borderWidth)
 
         if initialValue==value:
             if group.V is not None:
@@ -559,11 +614,11 @@
                 H=PDFName('N'),
                 )
         #RB['T'] = PDFString(name)
-        MK = dict(
-                CA='(%s)' % ZDSyms[buttonStyle],
-                BC=PDFArray(self.colorTuple(borderColor)),
-                BG=PDFArray(self.colorTuple(fillColor)),
-                )
+        MK = dict(CA='(%s)' % ZDSyms[buttonStyle])
+        if borderColor is not None:
+            MK['BC'] = PDFArray(self.colorTuple(borderColor))
+        if fillColor is not None:
+            MK['BG'] = PDFArray(self.colorTuple(fillColor))
         if borderWidth: RB['BS'] = bsPDF(borderWidth,borderStyle,dashLen)
         RB['MK'] = PDFDictionary(MK)
         RB = PDFDictionary(RB)
@@ -602,7 +657,7 @@
                 fillColor=None,
                 borderColor=None,
                 textColor=None,
-                borderWidth=1,
+                borderWidth=None,
                 borderStyle='solid',
                 width=120,
                 height=36,
@@ -618,6 +673,12 @@
         if opaqueColor(fillColor):
             streamFill = self.streamFillColor(fillColor)
             stream('%(streamFill)s\n0 0 %(width)s %(height)s re\nf')
+        # Pre-initialise border-derived variables so they are always defined 
for
+        # the /Tx clipping-region stream that follows, even when no border is 
drawn.
+        hbw = _2bw = 0
+        bww = width
+        bwh = height
+        undash = ''
         if borderWidth!=None and borderWidth>0 and opaqueColor(borderColor):
             hbw = borderWidth*0.5
             bww = width - borderWidth
@@ -655,7 +716,7 @@
         _4bw = 4*borderWidth
         w4bw = width - _4bw
         h4bw = height - _4bw
-        textFill = self.streamFillColor(textColor)
+        textFill = self.streamFillColor(textColor) if opaqueColor(textColor) 
else '0 g'
         stream('/Tx BMC \nq\n%(_2bw)s %(_2bw)s %(w4bw)s %(h4bw)s re\nW\nn')
         leading = 1.2 * fontSize
         if wkind=='listbox':
@@ -736,10 +797,10 @@
 
     def _textfield(self,
                 value='',
-                fillColor=None,
-                borderColor=None,
-                textColor=None,
-                borderWidth=1,
+                fillColor=_useDefault,
+                borderColor=_useDefault,
+                textColor=_useDefault,
+                borderWidth=_useDefault,
                 borderStyle='solid',
                 width=120,
                 height=36,
@@ -759,9 +820,14 @@
                 dashLen=3,
                 ):
         rFontName, iFontName = self.makeFont(fontName)
+        # Decide which widget dictionary entries to write before fontSize gets
+        # its rendering default.  Omitting /DA, /MK /BG, and /MK /BC when they
+        # were not explicitly requested lets the field inherit appearance from
+        # the AcroForm-level /DA//DR or the PDF viewer's built-in default.
+        _write_da = textColor is not None or fontName is not None or fontSize 
is not None
         if fontSize is None:
             fontSize = 12
-        
textColor,borderColor,fillColor=self.stdColors(textColor,borderColor,fillColor)
+        textColor,borderColor,fillColor,borderWidth = 
self.getDefaults(textColor,borderColor,fillColor,borderWidth)
         canv = self.canv
         if relative:
             x, y = self.canv.absolutePosition(x,y)
@@ -864,8 +930,13 @@
                 F = makeFlags(annotationFlags,annotationFlagValues),
                 Ff = Ff,
                 #H=PDFName('N'),
-                DA=PDFString('/%s %d Tf %s' % (iFontName,fontSize, 
self.streamFillColor(textColor))),
                 )
+        # Write /DA only when font or text color was explicitly requested.
+        # Omitting /DA lets the widget inherit its default appearance from the
+        # AcroForm /DA string instead of overriding it with a widget-level 
entry.
+        if _write_da:
+            da_color = self.streamFillColor(textColor) if 
opaqueColor(textColor) else '0 g'
+            TF['DA'] = PDFString('/%s %d Tf %s' % (iFontName,fontSize, 
da_color))
         if Opt: TF['Opt'] = Opt
         if I: TF['I'] = PDFArray(I)
         if maxlen:
@@ -875,15 +946,17 @@
         if not name:
             name = 'AFF%03d' % len(self.fields)
         TF['T'] = PDFString(name)
-        MK = dict(
-                BG=PDFArray(self.colorTuple(fillColor)),
-                )
+        MK = {}
+        if fillColor is not None:
+            MK['BG'] = PDFArray(self.colorTuple(fillColor))
         # Acrobat seems to draw a thin border when BS is defined, so only
         # include this if there actually is a border to draw
         if borderWidth:
             TF['BS'] = bsPDF(borderWidth,borderStyle,dashLen)
-            MK['BC'] = PDFArray(self.colorTuple(borderColor))
-        TF['MK'] = PDFDictionary(MK)
+            if borderColor is not None:
+                MK['BC'] = PDFArray(self.colorTuple(borderColor))
+        if MK:
+            TF['MK'] = PDFDictionary(MK)
 
         TF = PDFDictionary(TF)
         self.canv._addAnnotation(TF)
@@ -892,10 +965,10 @@
 
     def textfield(self,
                 value='',
-                fillColor=None,
-                borderColor=None,
-                textColor=None,
-                borderWidth=1,
+                fillColor=_useDefault,
+                borderColor=_useDefault,
+                textColor=_useDefault,
+                borderWidth=_useDefault,
                 borderStyle='solid',
                 width=120,
                 height=36,
@@ -938,10 +1011,10 @@
 
     def listbox(self,
                 value='',
-                fillColor=None,
-                borderColor=None,
-                textColor=None,
-                borderWidth=1,
+                fillColor=_useDefault,
+                borderColor=_useDefault,
+                textColor=_useDefault,
+                borderWidth=_useDefault,
                 borderStyle='solid',
                 width=120,
                 height=36,
@@ -985,10 +1058,10 @@
                 )
     def choice(self,
                 value='',
-                fillColor=None,
-                borderColor=None,
-                textColor=None,
-                borderWidth=1,
+                fillColor=_useDefault,
+                borderColor=_useDefault,
+                textColor=_useDefault,
+                borderWidth=_useDefault,
                 borderStyle='solid',
                 width=120,
                 height=36,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/platypus/tables.py 
new/reportlab-4.5.1/src/reportlab/platypus/tables.py
--- old/reportlab-4.4.9/src/reportlab/platypus/tables.py        2025-12-21 
11:57:02.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/platypus/tables.py        2026-05-05 
08:11:09.000000000 +0200
@@ -27,7 +27,8 @@
 from reportlab import rl_config
 from reportlab.lib.styles import PropertySet, ParagraphStyle, _baseFontName
 from reportlab.lib import colors
-from reportlab.lib.utils import annotateException, IdentStr, flatten, isStr, 
asNative, strTypes, __UNSET__
+from reportlab.lib.utils import annotateException, IdentStr, flatten, isStr, 
asNative, strTypes, __UNSET__, \
+                                rl_warn
 from reportlab.lib.validators import isListOfNumbersOrNone
 from reportlab.lib.rl_accel import fp_str
 from reportlab.lib.abag import ABag as CellFrame
@@ -437,7 +438,10 @@
                     if b: break
                 if b: break
         if rh:  #find tallest row, it's of great interest'
-            tallest = '(tallest row %d)' % int(max(rh))
+            try:
+                tallest = f'(tallest row {max(rh)})'
+            except:
+                tallest = ''
         else:
             tallest = ''
         if vx:
@@ -486,8 +490,11 @@
         if not V: return 0,0
         aW = w - s.leftPadding - s.rightPadding
         aH = aH - s.topPadding - s.bottomPadding
-        if aW<0:
-            raise ValueError(f'{self.identity()}: flowable given negative 
availWidth={aW} == width={w} - leftPadding={s.leftPadding} - 
rightPadding={s.rightPadding}')
+        if aW<0:    #something is wrong
+            if not rl_config.allowTableBoundsErrors&2:  #bit 1  1 --> ignore
+                raise ValueError(f'{self.identity()}: flowable given negative 
availWidth={aW} width={w} - leftPadding={s.leftPadding} - 
rightPadding={s.rightPadding}')
+            elif rl_config.allowTableBoundsErrors&8:        #bit 3  1 --> turn 
ignore into warn
+                rl_warn(f'{self.identity()}: flowable given negative 
availWidth={aW} width={w} - leftPadding={s.leftPadding} - 
rightPadding={s.rightPadding}')
         t = 0
         w = 0
         canv = getattr(self,'canv',None)
@@ -664,9 +671,12 @@
                             dW,t = self._listCellGeom(v,w or 
self._listValueWidth(v),s)
                             if canv: canv._fontname, canv._fontsize, 
canv._leading = saved
                             dW = dW + s.leftPadding + s.rightPadding
-                            if not rl_config.allowTableBoundsErrors and dW>w:
-                                from reportlab.platypus.doctemplate import 
LayoutError
-                                raise LayoutError("Flowable %s (%sx%s points) 
too wide for cell(%d,%d) (%sx* points) in\n%s" % 
(v[0].identity(30),fp_str(dW),fp_str(t),i,j, fp_str(w), self.identity(30)))
+                            if dW>(w or 0): #something wrong
+                                if not rl_config.allowTableBoundsErrors&1:  
#bit 0 1 --> ignore
+                                    from reportlab.platypus.doctemplate import 
LayoutError
+                                    raise LayoutError(f"Flowable 
{v[0].identity(30)} ({fp_str(dW)}x{fp_str(t)} points) too wide for 
cell({i},{j}) (fp_str(w)x* points) in\n{self.identity(30)}")
+                                elif rl_config.allowTableBoundsErrors&4:    
#bit 2 1 --> ignore
+                                    rl_warn(f"Flowable {v[0].identity(30)} 
({fp_str(dW)}x{fp_str(t)} points) too wide for cell({i},{j}) (fp_str(w)x* 
points) in\n{self.identity(30)}")
                         else:
                             v = (v is not None and str(v) or '').split("\n")
                             t = (s.leading or 1.2*s.fontsize)*len(v)
@@ -2167,7 +2177,11 @@
     def split(self, availWidth, availHeight):
         self._calc(availWidth, availHeight)
         if self.splitByRow or self.splitInRow:
-            if not rl_config.allowTableBoundsErrors and 
self._width>availWidth: return []
+            if self._width>availWidth:  #something wrong
+                if not rl_config.allowTableBoundsErrors&1:
+                    return []
+                elif rl_config.allowTableBoundsErrors&4:
+                    rl_warn(f'{self.identity(30)} split called with inadequate 
width')
 
             # If self.splitByRow is true, first try with doInRowSplit as false.
             # Otherwise, first try with doInRowSplit as true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/rl_config.py 
new/reportlab-4.5.1/src/reportlab/rl_config.py
--- old/reportlab-4.4.9/src/reportlab/rl_config.py      2024-12-13 
09:47:00.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab/rl_config.py      2026-05-01 
12:16:20.000000000 +0200
@@ -129,13 +129,13 @@
             _setOpt(k,v,conv)
 
 _registered_resets=[]
-def register_reset(func):
+def register_reset(func, callback=None):
     '''register a function to be called by rl_config._reset'''
     _registered_resets[:] = [x for x in _registered_resets if x()]
     L = [x for x in _registered_resets if x() is func]
     if L: return
-    from weakref import ref
-    _registered_resets.append(ref(func))
+    from weakref import ref, WeakMethod
+    _registered_resets.append((WeakMethod if hasattr(func,'__self__') else 
ref)(func,callback))
 
 def _reset():
     '''attempt to reset reportlab and friends'''
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab/rl_settings.py 
new/reportlab-4.5.1/src/reportlab/rl_settings.py
--- old/reportlab-4.4.9/src/reportlab/rl_settings.py    2025-04-17 
12:06:52.000000000 +0200
+++ new/reportlab-4.5.1/src/reportlab/rl_settings.py    2026-05-01 
12:16:20.000000000 +0200
@@ -73,7 +73,11 @@
 defCWRF
 unShapedFontGlob'''.split())
 
-allowTableBoundsErrors =    1 # set to 0 to die on too large elements in 
tables in debug (recommend 1 for production use)
+allowTableBoundsErrors =    1                       # bit 0 --> ignore overall 
width excession
+                                                    # bit 1 --> ignore 
negative available width
+                                                    # bit 2 --> turn bit 0 to 
a warning
+                                                    # bit 3 --> turn bit 1 
into a warning
+                                                    # (recommend 1 for 
production use)
 shapeChecking =             1
 defaultEncoding =           'WinAnsiEncoding'       # 'WinAnsi' or 'MacRoman'
 defaultGraphicsFontName=    'Times-Roman'           #initializer for 
STATE_DEFAULTS in shapes.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab.egg-info/PKG-INFO 
new/reportlab-4.5.1/src/reportlab.egg-info/PKG-INFO
--- old/reportlab-4.4.9/src/reportlab.egg-info/PKG-INFO 2026-01-15 
10:23:11.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab.egg-info/PKG-INFO 2026-05-12 
11:20:50.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: reportlab
-Version: 4.4.9
+Version: 4.5.1
 Summary: The Reportlab Toolkit
 Home-page: https://www.reportlab.com/
 Author: Andy Robinson, Robin Becker, the ReportLab team and the community
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/src/reportlab.egg-info/SOURCES.txt 
new/reportlab-4.5.1/src/reportlab.egg-info/SOURCES.txt
--- old/reportlab-4.4.9/src/reportlab.egg-info/SOURCES.txt      2026-01-15 
10:23:11.000000000 +0100
+++ new/reportlab-4.5.1/src/reportlab.egg-info/SOURCES.txt      2026-05-12 
11:20:50.000000000 +0200
@@ -66,7 +66,6 @@
 docs/userguide/testfile.txt
 src/reportlab/MANIFEST.in
 src/reportlab/__init__.py
-src/reportlab/license.txt
 src/reportlab/rl_config.py
 src/reportlab/rl_settings.py
 src/reportlab.egg-info/PKG-INFO
@@ -188,7 +187,6 @@
 src/reportlab/lib/colors.py
 src/reportlab/lib/corp.py
 src/reportlab/lib/enums.py
-src/reportlab/lib/extformat.py
 src/reportlab/lib/fontfinder.py
 src/reportlab/lib/fonts.py
 src/reportlab/lib/formatters.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/tests/render-out/Drawing14.py 
new/reportlab-4.5.1/tests/render-out/Drawing14.py
--- old/reportlab-4.4.9/tests/render-out/Drawing14.py   2026-01-15 
10:19:21.000000000 +0100
+++ new/reportlab-4.5.1/tests/render-out/Drawing14.py   2026-05-11 
16:19:31.000000000 +0200
@@ -6,8 +6,8 @@
        def __init__(self,width=400,height=200,*args,**kw):
                Drawing.__init__(self,width,height,*args,**kw)
                self.transform = (1,0,0,1,0,0)
-               self.add(Image(0,0,None,None,<PIL.GifImagePlugin.GifImageFile 
image mode=P size=10x7 at 
0x7F8A50052710>,fillColor=Color(0,0,0,1),fillOpacity=None,strokeColor=Color(0,0,0,1),strokeWidth=1,strokeLineCap=0,strokeLineJoin=0,strokeMiterLimit=0,strokeDashArray=None,strokeOpacity=None))
-               self.add(Image(380,186,20,14,<PIL.GifImagePlugin.GifImageFile 
image mode=P size=10x7 at 
0x7F8A5015A990>,fillColor=Color(0,0,0,1),fillOpacity=None,strokeColor=Color(0,0,0,1),strokeWidth=1,strokeLineCap=0,strokeLineJoin=0,strokeMiterLimit=0,strokeDashArray=None,strokeOpacity=None))
+               self.add(Image(0,0,None,None,<PIL.GifImagePlugin.GifImageFile 
image mode=P size=10x7 at 
0x7F2C085596D0>,fillColor=Color(0,0,0,1),fillOpacity=None,strokeColor=Color(0,0,0,1),strokeWidth=1,strokeLineCap=0,strokeLineJoin=0,strokeMiterLimit=0,strokeDashArray=None,strokeOpacity=None))
+               self.add(Image(380,186,20,14,<PIL.GifImagePlugin.GifImageFile 
image mode=P size=10x7 at 
0x7F2C094C0F50>,fillColor=Color(0,0,0,1),fillOpacity=None,strokeColor=Color(0,0,0,1),strokeWidth=1,strokeLineCap=0,strokeLineJoin=0,strokeMiterLimit=0,strokeDashArray=None,strokeOpacity=None))
 
 
 if __name__=="__main__": #NORUNTESTS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/tests/runAll.py 
new/reportlab-4.5.1/tests/runAll.py
--- old/reportlab-4.4.9/tests/runAll.py 2024-12-13 09:47:00.000000000 +0100
+++ new/reportlab-4.5.1/tests/runAll.py 2026-05-01 12:13:26.000000000 +0200
@@ -113,6 +113,8 @@
                             for _ in a[10:].split(',') if _.strip()]
                                 for a in sys.argv if a.startswith('--exclude=')
                     ],[])
+        for a in ('--verbosity=','--exclude=','--failfast'):
+            sys.argv[:] = [_ for _ in sys.argv if not _.startswith(a)]
         testSuite = 
makeSuite(folder,nonImportable=NI,exclude=exclude,pattern=pattern+(not haveSRC 
and 'c' or ''))
         result = 
unittest.TextTestRunner(verbosity=verbosity,failfast=failfast).run(testSuite)
     else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/tests/test_lib_colors.py 
new/reportlab-4.5.1/tests/test_lib_colors.py
--- old/reportlab-4.4.9/tests/test_lib_colors.py        2024-12-13 
09:47:00.000000000 +0100
+++ new/reportlab-4.5.1/tests/test_lib_colors.py        2026-04-20 
17:20:17.000000000 +0200
@@ -64,10 +64,39 @@
         allRed = [colors.red, [1, 0, 0], (1, 0, 0),
                   b'red', b'RED', b'0xFF0000', b'0xff0000',b'rgb(255,0,0)',
                   u'red', u'RED', u'0xFF0000', u'0xff0000',u'rgb(255,0,0)',
+                  'rgb(1.,0,0)', 'rgb(1.,0,0/100%)', 'rgb(255,0,0/100%)',
+                  'rgb(100.% 0% 0%/100%)',
                   ]
 
         for thing in allRed:
-            assert colors.toColor(thing) == 
colors.red,"colors.toColor(%s)-->%s != colors.red(%s)" % 
(ascii(thing),ascii(colors.toColor(thing)),colors.red)
+            
self.assertEqual(colors.toColor(thing),colors.red,"colors.toColor(%s)-->%s != 
colors.red(%s)" % (ascii(thing),ascii(colors.toColor(thing)),colors.red))
+        self.assertEqual(colors.toColor('rgba(1 0 0 
0.5)'),colors.Color(1/255,0,0,.5))
+        self.assertEqual(colors.toColor('rgb(255 0 
0/50%)'),colors.Color(1,0,0,0.5))
+
+
+        def compare(c, x, nd=5):
+            for a in ('red','green','blue','alpha'):
+                if round(getattr(c,a),nd)!=round(getattr(x,a),nd): return False
+            return True
+
+        #compare str here to avoid float diffs caused by 255 divisions
+        toColor = colors.toColor
+        Color = colors.Color
+        CMYKColor = colors.CMYKColor
+        for value, expected in (
+                    ("rgba(.10,.10,.10,.10)", "Color(.1,.1,.1,.1)"),
+                    ("rgba(10.%,10.%,10.%,10.%)", 
"Color(.101961,.101961,.101961,.1)"),
+                    ("rgba(10%,10%,10%,10%)", 
"Color(.101961,.101961,.101961,.1)"),
+                    ("rgb(10%,10%,10%/10%)", 
"Color(.101961,.101961,.101961,.1)"),
+                    ("rgb(10%,10%,10%/.1)", 
"Color(.101961,.101961,.101961,.1)"),
+                    ("rgba(255,255,255,1)", "Color(1,1,1,1)"),
+                    ("rgba(1,1,1,1.)", "Color(.003922,.003922,.003922,1)"),
+                    ("rgb(1,1,1/1.)", "Color(.003922,.003922,.003922,1)"),
+                    ("cmyk(1,1,1,1/.1)", "CMYKColor(1,1,1,1,alpha=0.1)"),
+                    ("cmyka(1,1,1,1,.1)", "CMYKColor(1,1,1,1,alpha=0.1)"),
+                    ):
+            self.assertTrue(compare(toColor(toColor(value)),eval(expected)),
+                                f'toColor({value!r}) --> {toColor(value)!r} != 
{expected!r}')
 
     def test2a(self):
         '''attempt to test toColor against simple attacks'''
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/tests/test_lib_rl_safe_eval.py 
new/reportlab-4.5.1/tests/test_lib_rl_safe_eval.py
--- old/reportlab-4.4.9/tests/test_lib_rl_safe_eval.py  2024-12-13 
09:47:00.000000000 +0100
+++ new/reportlab-4.5.1/tests/test_lib_rl_safe_eval.py  2026-02-12 
10:27:46.000000000 +0100
@@ -138,17 +138,17 @@
         except:
             print('expr=%r' % expr)
             annotateException('\nexpr=%r\n' % expr)
-        self.assertEqual(answer,result,"rl_safe_eval(%r) = %r not expected %r" 
% (expr,result,answer))
+        self.assertEqual(answer,result,f"rl_safe_eval({expr!r}) = {result!r}) 
not expected {answer!r}")
     def skips(self,*args,**kwds):
         raise unittest.SkipTest
     def fails(self, expr, g=None, l=None, timeout=None, exception=BadCode):
         try:
             result = rl_safe_eval(expr,g,l,timeout=timeout)
-            self.assertEqual(True,False,"rl_safe_eval(%r)=%r did not raise %s" 
% (expr,result,exception.__name__))
+            self.assertEqual(True,False,f"rl_safe_eval({expr!r}) = {result!r} 
did not raise {exception.__name__}")
         except exception:
             return
         except:
-            self.assertEqual(True,False,"rl_safe_eval(%r) raised %s: %s 
instead of %s" % 
(expr,sys.exc_info()[0].__name__,str(sys.exc_info()[1]),exception.__name__))
+            self.assertEqual(True,False,"rl_safe_eval({expr!r}) raised 
{sys.exc_info()[0].__name__}: {str(sys.exc_info()[1])} instead of 
{exception.__name__}")
 
 GA = 'ga'
 class SafeEvalTestBasics(unittest.TestCase):
@@ -158,6 +158,25 @@
     def test_002(self):
         self.assertTrue(rl_safe_eval("GA=='ga'"))
 
+class SafeExecTestBasics(unittest.TestCase):
+    def test_funcdef_blocks(self):
+        '''test security issue found by Ethan Kim lt ethan 4t cremit d0t io 
gt'''
+        codes = (
+            '().__class__.__bases__[0]',
+            'def f():\n'
+             '\tfor c in ().__class__.__bases__[0].__subclasses__():\n'
+              '\t\tif c.__name__ == "_wrap_close":\n'
+               '\t\t\treturn c.__init__.__globals__["system"]("id")\n'
+            'f()\n',
+            )
+        blocked = 0
+        for c in codes:
+            try:
+                rl_safe_exec(c,{},{})
+            except BadCode:
+                blocked += 1
+        self.assertEqual(blocked,2,f'{blocked=} expected 2; probably BadCode 
detection in FunctionDef fails')
+
 class ExtendedLiteralEval(unittest.TestCase):
     def test_001(self):
         S = colors.getAllNamedColors().copy()
@@ -197,7 +216,7 @@
             
self.assertEqual(showVal(expr),expected,f"rl_extended_literal_eval({expr!r}) is 
not equal to expected {expected}")
 
 def makeSuite():
-    return 
makeSuiteForClasses(SafeEvalTestCase,SafeEvalTestBasics,ExtendedLiteralEval)
+    return 
makeSuiteForClasses(SafeEvalTestCase,SafeEvalTestBasics,SafeExecTestBasics,ExtendedLiteralEval)
 
 if __name__ == "__main__": #noruntests
     unittest.TextTestRunner().run(makeSuite())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/reportlab-4.4.9/tests/test_pdfbase_pdfform.py 
new/reportlab-4.5.1/tests/test_pdfbase_pdfform.py
--- old/reportlab-4.4.9/tests/test_pdfbase_pdfform.py   2024-12-13 
09:47:00.000000000 +0100
+++ new/reportlab-4.5.1/tests/test_pdfbase_pdfform.py   2026-04-15 
19:07:57.000000000 +0200
@@ -1,10 +1,14 @@
 from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, 
printLocation, NearTestCase
 setOutDir(__name__)
 import unittest
+from io import BytesIO
 from reportlab.pdfgen import canvas
 from reportlab.pdfbase import pdfform
 
 class PdfFormTestCase(NearTestCase):
+    def _annotationDict(self, canv, index=1):
+        return canv._doc.idToObject['Annot.NUMBER%d' % index].dict
+
     def testMultipleUsage(self):
         for i in range(2):
             c = 
canvas.Canvas(outputfile('test_pdfbase_pdfform_multiple_usage_%s.pdf'%i))
@@ -12,6 +16,42 @@
             pdfform.buttonFieldAbsolute(c, 'button', 'Off', 200, 200)
             c.save()
 
+    def testTextfieldOmitsWidgetStyleEntriesWhenUnset(self):
+        # Regression test: omitted widget style args should not force
+        # widget-level appearance entries that block AcroForm inheritance.
+        canv = canvas.Canvas(BytesIO())
+        canv.acroForm.textfield(name='tf-none', x=10, y=10, width=100, 
height=20,
+                          textColor=None, fillColor=None, borderColor=None,
+                          borderWidth=None)
+
+        annot = self._annotationDict(canv)
+        self.assertNotIn('DA', annot)
+        self.assertNotIn('MK', annot)
+        self.assertNotIn('BS', annot)
+
+    def testCheckboxOmitsMkColorsWhenUnset(self):
+        # Regression test: checkboxes still need /MK for /CA, but unset
+        # colors must not emit /MK /BG or /MK /BC.
+        canv = canvas.Canvas(BytesIO())
+        canv.acroForm.checkbox(name='cb-none', x=10, y=10, fillColor=None, 
borderColor=None)
+
+        annot = self._annotationDict(canv)
+        self.assertIn('MK', annot)
+        mk = annot['MK'].dict
+        self.assertIn('CA', mk)
+        self.assertNotIn('BG', mk)
+        self.assertNotIn('BC', mk)
+
+    def testForceBorderWithoutFillColorDoesNotWriteBackground(self):
+        # Regression test: forceBorder with no fill color should not imply
+        # a widget background entry.
+        canv = canvas.Canvas(BytesIO())
+        canv.acroForm.textfield(name='tf-force-border', x=10, y=10, width=100, 
height=20, fillColor=None, borderColor=None, forceBorder=True)
+        canv.save()
+
+        annot = self._annotationDict(canv)
+        self.assertNotIn('MK', annot)
+
     def testAAbsoluteAndRelativeFields(self):
         #the old test1 in pdfform
         c = canvas.Canvas(outputfile("test_pdfbase_pdfform_formtest.pdf"))
@@ -56,14 +96,14 @@
         af.checkbox(name='cb1C',tooltip='Field 
cb1C',checked=True,x=72,y=72+2*36,buttonStyle='cross',borderWidth=2, 
borderColor=red, fillColor=green, textColor=blue,forceBorder=True)
         af.checkbox(name='cb1D',tooltip='Field 
cb1D',checked=True,x=72,y=72+3*36,buttonStyle='star',borderWidth=2, 
borderColor=red, fillColor=green, textColor=blue,forceBorder=True)
         af.checkbox(name='cb1E',tooltip='Field 
cb1E',checked=True,x=72,y=72+4*36,buttonStyle='diamond',borderStyle='bevelled', 
borderWidth=2, borderColor=red, fillColor=green, 
textColor=blue,forceBorder=True)
-        af.checkbox(name='cb1F',tooltip='Field 
cb1F',checked=True,x=72,y=72+5*36,buttonStyle='check', borderWidth=2, 
borderColor=red, fillColor=None, textColor=None,forceBorder=True)
-        af.checkbox(name='cb1H',tooltip='Field 
cb1H',checked=True,x=72,y=72+6*36,buttonStyle='check', 
borderStyle='underlined',borderWidth=2, borderColor=red, fillColor=None, 
textColor=None,forceBorder=True)
-        af.checkbox(name='cb1G',tooltip='Field 
cb1G',checked=True,x=72,y=72+7*36,buttonStyle='check', 
borderStyle='dashed',borderWidth=2, borderColor=red, fillColor=None, 
textColor=None,forceBorder=True)
-        af.checkbox(name='cb1I',tooltip='Field 
cb1I',checked=True,x=72,y=72+8*36,buttonStyle='check', 
borderStyle='inset',borderWidth=1, borderColor=red, fillColor=None, 
textColor=None,forceBorder=True)
+        af.checkbox(name='cb1F',tooltip='Field 
cb1F',checked=True,x=72,y=72+5*36,buttonStyle='check', borderWidth=2, 
borderColor=red,forceBorder=True)
+        af.checkbox(name='cb1H',tooltip='Field 
cb1H',checked=True,x=72,y=72+6*36,buttonStyle='check', 
borderStyle='underlined',borderWidth=2, borderColor=red,forceBorder=True)
+        af.checkbox(name='cb1G',tooltip='Field 
cb1G',checked=True,x=72,y=72+7*36,buttonStyle='check', 
borderStyle='dashed',borderWidth=2, borderColor=red,forceBorder=True)
+        af.checkbox(name='cb1I',tooltip='Field 
cb1I',checked=True,x=72,y=72+8*36,buttonStyle='check', 
borderStyle='inset',borderWidth=1, borderColor=red,forceBorder=True)
         af.checkbox(name='cb1J',tooltip='Field 
cb1J',checked=True,x=72,y=72+9*36,buttonStyle='check', 
borderStyle='solid',shape='circle', borderWidth=2, borderColor=red, 
fillColor=green, textColor=blue,forceBorder=True)
-        af.checkbox(name='cb1K',tooltip='Field 
cb1K',checked=True,x=72,y=72+10*36,buttonStyle='check', borderWidth=1, 
borderColor=None, fillColor=None, textColor=None,forceBorder=True)
-        af.checkbox(name='cb1L',tooltip='Field 
cb1L',checked=False,x=72,y=800,buttonStyle='check',borderWidth=None, 
borderColor=None, fillColor=None, textColor=None,forceBorder=True)
-        af.checkbox(name='cb1M',tooltip='Field 
cb1M',checked=False,x=72,y=600,buttonStyle='check',borderWidth=2, 
borderColor=blue, fillColor=None, textColor=None,forceBorder=True)
+        af.checkbox(name='cb1K',tooltip='Field 
cb1K',checked=True,x=72,y=72+10*36,buttonStyle='check', 
borderWidth=1,forceBorder=True)
+        af.checkbox(name='cb1L',tooltip='Field 
cb1L',checked=False,x=72,y=800,buttonStyle='check',borderWidth=None, 
borderColor=af.useDefault, fillColor=af.useDefault, 
textColor=af.useDefault,forceBorder=True)
+        af.checkbox(name='cb1M',tooltip='Field 
cb1M',checked=False,x=72,y=600,buttonStyle='check',borderWidth=2, 
borderColor=blue,forceBorder=True)
         af.radio(name='rb1A',tooltip='Field rb1A', value='V1', 
selected=False,x=144,y=72+0*36,buttonStyle='circle', 
borderStyle='solid',shape='circle', borderWidth=2, borderColor=red, 
fillColor=green, textColor=blue,forceBorder=True)
         af.radio(name='rb1A',tooltip='Field rb1A', value='V2', 
selected=True,x=144,y=72+1*36,buttonStyle='circle', 
borderStyle='solid',shape='circle', borderWidth=2, borderColor=red, 
fillColor=green, textColor=blue,forceBorder=True)
         af.radio(name='rb1B',tooltip='Field rb1B', value='V1', 
selected=False,x=144+36,y=72+0*36,buttonStyle='check', 
borderStyle='solid',shape='square', borderWidth=2, borderColor=green, 
fillColor=red, textColor=blue,forceBorder=True)
@@ -82,14 +122,14 @@
         af.checkbox(name='cb2C',tooltip='Field 
cb2C',checked=True,x=72,y=72+2*36,buttonStyle='cross',borderWidth=2, 
borderColor=red, fillColor=green, textColor=blue,forceBorder=True)
         af.checkbox(name='cb2D',tooltip='Field 
cb2D',checked=True,x=72,y=72+3*36,buttonStyle='star',borderWidth=2, 
borderColor=red, fillColor=green, textColor=blue,forceBorder=True)
         af.checkbox(name='cb2E',tooltip='Field 
cb2E',checked=True,x=72,y=72+4*36,buttonStyle='diamond',borderStyle='bevelled', 
borderWidth=2, borderColor=red, fillColor=green, 
textColor=blue,forceBorder=True)
-        af.checkbox(name='cb2F',tooltip='Field 
cb2F',checked=True,x=72,y=72+5*36,buttonStyle='check', borderWidth=2, 
borderColor=red, fillColor=None, textColor=None,forceBorder=True)
-        af.checkbox(name='cb2H',tooltip='Field 
cb2H',checked=True,x=72,y=72+6*36,buttonStyle='check', 
borderStyle='underlined',borderWidth=2, borderColor=red, fillColor=None, 
textColor=None,forceBorder=True)
-        af.checkbox(name='cb2G',tooltip='Field 
cb2G',checked=True,x=72,y=72+7*36,buttonStyle='check', 
borderStyle='dashed',borderWidth=2, borderColor=red, fillColor=None, 
textColor=None,forceBorder=True)
-        af.checkbox(name='cb2I',tooltip='Field 
cb2I',checked=True,x=72,y=72+8*36,buttonStyle='check', 
borderStyle='inset',borderWidth=2, borderColor=red, fillColor=None, 
textColor=None,forceBorder=True)
+        af.checkbox(name='cb2F',tooltip='Field 
cb2F',checked=True,x=72,y=72+5*36,buttonStyle='check', borderWidth=2, 
borderColor=red,forceBorder=True)
+        af.checkbox(name='cb2H',tooltip='Field 
cb2H',checked=True,x=72,y=72+6*36,buttonStyle='check', 
borderStyle='underlined',borderWidth=2, borderColor=red,forceBorder=True)
+        af.checkbox(name='cb2G',tooltip='Field 
cb2G',checked=True,x=72,y=72+7*36,buttonStyle='check', 
borderStyle='dashed',borderWidth=2, borderColor=red,forceBorder=True)
+        af.checkbox(name='cb2I',tooltip='Field 
cb2I',checked=True,x=72,y=72+8*36,buttonStyle='check', 
borderStyle='inset',borderWidth=2, borderColor=red,forceBorder=True)
         af.checkbox(name='cb2J',tooltip='Field 
cb2J',checked=True,x=72,y=72+9*36,buttonStyle='check', 
borderStyle='solid',shape='circle', borderWidth=2, borderColor=red, 
fillColor=green, textColor=blue,forceBorder=True)
-        af.checkbox(name='cb2K',tooltip='Field 
cb2K',checked=True,x=72,y=72+10*36,buttonStyle='check', borderWidth=1, 
borderColor=None, fillColor=None, textColor=None,forceBorder=True)
-        af.checkbox(name='cb2L',tooltip='Field 
cb2L',checked=False,x=72,y=800,buttonStyle='check',borderWidth=None, 
borderColor=None, fillColor=None, textColor=None,forceBorder=True)
-        af.checkbox(name='cb2M',tooltip='Field 
cb2M',checked=False,x=72,y=600,buttonStyle='check',borderWidth=2, 
borderColor=blue, fillColor=None, textColor=None,forceBorder=True)
+        af.checkbox(name='cb2K',tooltip='Field 
cb2K',checked=True,x=72,y=72+10*36,buttonStyle='check', 
borderWidth=1,forceBorder=True)
+        af.checkbox(name='cb2L',tooltip='Field 
cb2L',checked=False,x=72,y=800,buttonStyle='check', borderWidth=None, 
forceBorder=True)
+        af.checkbox(name='cb2M',tooltip='Field 
cb2M',checked=False,x=72,y=600,buttonStyle='check',borderWidth=2, 
borderColor=blue,forceBorder=True)
         af.radio(name='rb2A',tooltip='Field rb2A', value='V1', 
selected=False,x=144,y=72+0*36,buttonStyle='circle', 
borderStyle='solid',shape='circle', borderWidth=2, borderColor=red, 
fillColor=green, textColor=blue,forceBorder=True)
         af.radio(name='rb2A',tooltip='Field rb2A', value='V2', 
selected=True,x=144,y=72+1*36,buttonStyle='circle', 
borderStyle='solid',shape='circle', borderWidth=2, borderColor=red, 
fillColor=green, textColor=blue,forceBorder=True)
         af.radio(name='rb2B',tooltip='Field rb2B', value='V1', 
selected=False,x=144+36,y=72+0*36,buttonStyle='check', 
borderStyle='solid',shape='square', borderWidth=2, borderColor=green, 
fillColor=red, textColor=blue,forceBorder=True)
@@ -108,14 +148,14 @@
         af.checkboxRelative(name='cb3C',tooltip='Field 
cb3C',checked=True,x=72,y=72+2*36,buttonStyle='cross',borderWidth=2, 
borderColor=red, fillColor=green, textColor=blue,forceBorder=True)
         af.checkboxRelative(name='cb3D',tooltip='Field 
cb3D',checked=True,x=72,y=72+3*36,buttonStyle='star',borderWidth=2, 
borderColor=red, fillColor=green, textColor=blue,forceBorder=True)
         af.checkboxRelative(name='cb3E',tooltip='Field 
cb3E',checked=True,x=72,y=72+4*36,buttonStyle='diamond',borderStyle='bevelled', 
borderWidth=2, borderColor=red, fillColor=green, 
textColor=blue,forceBorder=True)
-        af.checkboxRelative(name='cb3F',tooltip='Field 
cb3F',checked=True,x=72,y=72+5*36,buttonStyle='check', borderWidth=2, 
borderColor=red, fillColor=None, textColor=None,forceBorder=True)
-        af.checkboxRelative(name='cb3H',tooltip='Field 
cb3H',checked=True,x=72,y=72+6*36,buttonStyle='check', 
borderStyle='underlined',borderWidth=2, borderColor=red, fillColor=None, 
textColor=None,forceBorder=True)
-        af.checkboxRelative(name='cb3G',tooltip='Field 
cb3G',checked=True,x=72,y=72+7*36,buttonStyle='check', 
borderStyle='dashed',borderWidth=2, borderColor=red, fillColor=None, 
textColor=None,forceBorder=True)
-        af.checkboxRelative(name='cb3I',tooltip='Field 
cb3I',checked=True,x=72,y=72+8*36,buttonStyle='check', 
borderStyle='inset',borderWidth=2, borderColor=red, fillColor=None, 
textColor=None,forceBorder=True)
+        af.checkboxRelative(name='cb3F',tooltip='Field 
cb3F',checked=True,x=72,y=72+5*36,buttonStyle='check', borderWidth=2, 
borderColor=red,forceBorder=True)
+        af.checkboxRelative(name='cb3H',tooltip='Field 
cb3H',checked=True,x=72,y=72+6*36,buttonStyle='check', 
borderStyle='underlined',borderWidth=2, borderColor=red,forceBorder=True)
+        af.checkboxRelative(name='cb3G',tooltip='Field 
cb3G',checked=True,x=72,y=72+7*36,buttonStyle='check', 
borderStyle='dashed',borderWidth=2, borderColor=red,forceBorder=True)
+        af.checkboxRelative(name='cb3I',tooltip='Field 
cb3I',checked=True,x=72,y=72+8*36,buttonStyle='check', 
borderStyle='inset',borderWidth=2, borderColor=red,forceBorder=True)
         af.checkboxRelative(name='cb3J',tooltip='Field 
cb3J',checked=True,x=72,y=72+9*36,buttonStyle='check', 
borderStyle='solid',shape='circle', borderWidth=2, borderColor=red, 
fillColor=green, textColor=blue,forceBorder=True)
-        af.checkboxRelative(name='cb3K',tooltip='Field 
cb3K',checked=True,x=72,y=72+10*36,buttonStyle='check', borderWidth=1, 
borderColor=None, fillColor=None, textColor=None,forceBorder=True)
-        af.checkboxRelative(name='cb3L',tooltip='Field 
cb3L',checked=False,x=72,y=800,buttonStyle='check',borderWidth=None, 
borderColor=None, fillColor=None, textColor=None,forceBorder=True)
-        af.checkboxRelative(name='cb3M',tooltip='Field 
cb3M',checked=False,x=72,y=600,buttonStyle='check',borderWidth=2, 
borderColor=blue, fillColor=None, textColor=None,forceBorder=True)
+        af.checkboxRelative(name='cb3K',tooltip='Field 
cb3K',checked=True,x=72,y=72+10*36,buttonStyle='check', 
borderWidth=1,forceBorder=True)
+        af.checkboxRelative(name='cb3L',tooltip='Field 
cb3L',checked=False,x=72,y=800,buttonStyle='check',borderWidth=None,forceBorder=True)
+        af.checkboxRelative(name='cb3M',tooltip='Field 
cb3M',checked=False,x=72,y=600,buttonStyle='check',borderWidth=2, 
borderColor=blue,forceBorder=True)
         af.radioRelative(name='rb3A',tooltip='Field rb3A', value='V1', 
selected=False,x=144,y=72+0*36,buttonStyle='circle', 
borderStyle='solid',shape='circle', borderWidth=2, borderColor=red, 
fillColor=green, textColor=blue,forceBorder=True)
         af.radioRelative(name='rb3A',tooltip='Field rb3A', value='V2', 
selected=True,x=144,y=72+1*36,buttonStyle='circle', 
borderStyle='solid',shape='circle', borderWidth=2, borderColor=red, 
fillColor=green, textColor=blue,forceBorder=True)
         af.radioRelative(name='rb3B',tooltip='Field rb3B', value='V1', 
selected=False,x=144+36,y=72+0*36,buttonStyle='check', 
borderStyle='solid',shape='square', borderWidth=2, borderColor=green, 
fillColor=red, textColor=blue,forceBorder=True)

Reply via email to