reportlab: Add some basic type hints for graphics rendering API (#12051)

This commit is contained in:
David Salvisberg
2024-05-29 14:38:19 +02:00
committed by GitHub
parent b45456739a
commit 93b5016a29
10 changed files with 332 additions and 195 deletions

View File

@@ -8,6 +8,7 @@ reportlab\.platypus\.(doctemplate\.|flowables\.)?[A-Za-z_]+\.drawOn
# similary the wrap/split methods use inconsistent names for their
# parameters, so we decided to make them positional-only
reportlab.graphics.shapes.Drawing.wrap
reportlab\.platypus\.(doctemplate\.|flowables\.|tableofcontents\.)?[A-Za-z_]+\.split
reportlab\.platypus\.(doctemplate\.|flowables\.|tableofcontents\.)?[A-Za-z_]+\.wrap
reportlab.platypus.multicol.MultiCol.split

View File

@@ -190,3 +190,10 @@ Table(
("ROUNDEDCORNERS", [0, 0, 5, 5]),
],
)
# Testing the various possible data layouts
Table([["foo"]])
Table([("foo",)])
Table((["foo"],))
Table((("foo",),))

View File

@@ -1,12 +1,14 @@
from _typeshed import Incomplete
from typing import Final
from typing import IO, Final
from reportlab.graphics.renderbase import Renderer
from reportlab.graphics.shapes import Drawing
from reportlab.pdfgen.canvas import Canvas
from reportlab.platypus import Flowable
__version__: Final[str]
def draw(drawing, canvas, x, y, showBoundary=...) -> None: ...
def draw(drawing: Drawing, canvas: Canvas, x: float, y: float, showBoundary=...) -> None: ...
class _PDFRenderer(Renderer):
def __init__(self) -> None: ...
@@ -32,6 +34,6 @@ class GraphicsFlowable(Flowable):
def __init__(self, drawing) -> None: ...
def draw(self) -> None: ...
def drawToFile(d, fn, msg: str = "", showBoundary=..., autoSize: int = 1, canvasKwds={}) -> None: ...
def drawToString(d, msg: str = "", showBoundary=..., autoSize: int = 1, canvasKwds={}): ...
def drawToFile(d: Drawing, fn: str | IO[bytes], msg: str = "", showBoundary=..., autoSize: int = 1, canvasKwds={}) -> None: ...
def drawToString(d: Drawing, msg: str = "", showBoundary=..., autoSize: int = 1, canvasKwds={}) -> str: ...
def test(outDir: str = "pdfout", shout: bool = False) -> None: ...

View File

@@ -1,13 +1,15 @@
from _typeshed import Incomplete
from typing import Final
from typing import IO, Final
from reportlab.graphics.renderbase import Renderer
from reportlab.graphics.shapes import Drawing
from reportlab.pdfgen.canvas import Canvas
__version__: Final[str]
def Color2Hex(c): ...
def CairoColor(c): ...
def draw(drawing, canvas, x, y, showBoundary=...) -> None: ...
def draw(drawing: Drawing, canvas: Canvas, x: float, y: float, showBoundary=...) -> None: ...
class _PMRenderer(Renderer):
def pop(self) -> None: ...
@@ -72,53 +74,53 @@ class PMCanvas:
def setLineWidth(self, width) -> None: ...
def drawToPMCanvas(
d,
dpi: int = 72,
bg: int = 16777215,
d: Drawing,
dpi: float = 72,
bg: int = 0xFFFFFF,
configPIL: Incomplete | None = None,
showBoundary=...,
backend="rlPyCairo",
backendFmt: str = "RGB",
): ...
def drawToPIL(
d,
dpi: int = 72,
bg: int = 16777215,
d: Drawing,
dpi: float = 72,
bg: int = 0xFFFFFF,
configPIL: Incomplete | None = None,
showBoundary=...,
backend="rlPyCairo",
backendFmt: str = "RGB",
): ...
def drawToPILP(
d,
dpi: int = 72,
bg: int = 16777215,
d: Drawing,
dpi: float = 72,
bg: int = 0xFFFFFF,
configPIL: Incomplete | None = None,
showBoundary=...,
backend="rlPyCairo",
backendFmt: str = "RGB",
): ...
def drawToFile(
d,
fn,
d: Drawing,
fn: str | IO[bytes],
fmt: str = "GIF",
dpi: int = 72,
bg: int = 16777215,
dpi: float = 72,
bg: int = 0xFFFFFF,
configPIL: Incomplete | None = None,
showBoundary=...,
backend="rlPyCairo",
backendFmt: str = "RGB",
) -> None: ...
def drawToString(
d,
d: Drawing,
fmt: str = "GIF",
dpi: int = 72,
bg: int = 16777215,
dpi: float = 72,
bg: int = 0xFFFFFF,
configPIL: Incomplete | None = None,
showBoundary=...,
backend="rlPyCairo",
backendFmt: str = "RGB",
): ...
) -> str: ...
save = drawToFile

View File

@@ -1,7 +1,9 @@
from _typeshed import Incomplete
from typing import Final
from typing import IO, Final
from reportlab.graphics.renderbase import Renderer
from reportlab.graphics.shapes import Drawing
from reportlab.pdfgen.canvas import Canvas
__version__: Final[str]
PS_WinAnsiEncoding: Final[str]
@@ -50,7 +52,7 @@ class PSCanvas:
def scale(self, x, y) -> None: ...
def transform(self, a, b, c, d, e, f) -> None: ...
def draw(drawing, canvas, x: int = 0, y: int = 0, showBoundary=0) -> None: ...
def draw(drawing: Drawing, canvas: Canvas, x: float = 0, y: float = 0, showBoundary=0) -> None: ...
class _PSRenderer(Renderer):
def drawNode(self, node) -> None: ...
@@ -66,6 +68,6 @@ class _PSRenderer(Renderer):
def applyStateChanges(self, delta, newState) -> None: ...
def drawImage(self, image) -> None: ...
def drawToFile(d, fn, showBoundary=0, **kwd) -> None: ...
def drawToString(d, showBoundary=0): ...
def drawToFile(d: Drawing, fn: IO[bytes], showBoundary=0, **kwd) -> None: ...
def drawToString(d: Drawing, showBoundary=0) -> str: ...
def test(outDir: str = "epsout", shout: bool = False) -> None: ...

View File

@@ -1,9 +1,11 @@
from _typeshed import Incomplete
from collections.abc import Sequence
from math import cos as cos, pi as pi, sin as sin
from typing import Final
from typing import IO, Final
from reportlab.graphics.renderbase import Renderer
from reportlab.graphics.shapes import Drawing
from reportlab.pdfgen.canvas import Canvas
AREA_STYLES: Final[Sequence[str]]
LINE_STYLES: Final[Sequence[str]]
@@ -11,9 +13,9 @@ TEXT_STYLES: Final[Sequence[str]]
EXTRA_STROKE_STYLES: Final[Sequence[str]]
EXTRA_FILL_STYLES: Final[Sequence[str]]
def drawToString(d, showBoundary=0, **kwds): ...
def drawToFile(d, fn, showBoundary=0, **kwds) -> None: ...
def draw(drawing, canvas, x: int = 0, y: int = 0, showBoundary=0) -> None: ...
def drawToString(d: Drawing, showBoundary=0, **kwds) -> str: ...
def drawToFile(d: Drawing, fn: str | IO[str], showBoundary=0, **kwds) -> None: ...
def draw(drawing: Drawing, canvas: Canvas, x: float = 0, y: float = 0, showBoundary=0) -> None: ...
def transformNode(doc, newTag, node: Incomplete | None = None, **attrDict): ...
class EncodedWriter(list[Incomplete]):

View File

@@ -1,11 +1,96 @@
from _typeshed import Incomplete
from typing import Final
from _typeshed import Incomplete, SupportsItems
from abc import abstractmethod
from collections.abc import Iterable, Sequence
from typing import Any, Final, Literal, NoReturn, TypedDict
from typing_extensions import Self, TypeAlias, Unpack
from reportlab.lib.attrmap import *
from reportlab.lib.validators import *
from reportlab.lib.colors import Color
from reportlab.lib.validators import NoneOr, Validator
from reportlab.pdfgen.canvas import Canvas
from reportlab.platypus import Flowable
from reportlab.platypus.flowables import _HAlignment, _VAlignment
from .transform import *
_IntBool: TypeAlias = Literal[0, 1]
_BoolLike: TypeAlias = _IntBool | bool
_PathOp: TypeAlias = (
tuple[Literal["moveTo"], float, float]
| tuple[Literal["lineTo"], float, float]
| tuple[Literal["curveTo"], float, float, float, float, float, float]
# close path may either be a tuple or just the string
| Literal["closePath"]
| tuple[Literal["closePath"]]
# fallback for list that is not type safe
| list[Any]
)
# NOTE: These are derived from _attrMap and can optionally be
# verified at runtime
class _GroupKwArgs(TypedDict, total=False):
transform: tuple[float, float, float, float, float, float] | list[float] | list[int]
# NOTE: This should be used with care, since it will replace elements
# it's mostly useful for circumventing validation logic and
# reusing the list, rather than populating a new list
contents: list[Shape]
strokeOverprint: _BoolLike
fillOverprint: _BoolLike
overprintMask: _BoolLike
class _DrawingKwArgs(_GroupKwArgs, total=False):
# TODO: Restrict to supported formats?
formats: list[str] | tuple[str, ...]
# NOTE: This looks like an implementation detail, so we may not
# want to include this in KwArgs
canv: Canvas
background: Shape | UserNode | None
# NOTE: The runtime validation for alignments is incorrect, so
# we assume it is turned off and allow all valid values
hAlign: _HAlignment
vAlign: _VAlignment
renderScale: float
initialFontName: str | None
initialFontSize: float | None
class _LineShapeKwArgs(TypedDict, total=False):
strokeColor: Color | None
strokeWidth: float
strokeLineCap: Literal[0, 1, 2]
strokeLineJoin: Literal[0, 1, 2]
strokeMiterLimit: float
strokeDashArray: Sequence[float] | tuple[float, Sequence[float]]
strokeOpacity: float | None
strokeOverprint: _BoolLike
overprintMask: _BoolLike
class _PathKwArgs(_LineShapeKwArgs, total=False):
fillColor: Color | None
fillOpacity: float
fillOverprint: _BoolLike
class _AllPathKwArgs(_PathKwArgs, total=False):
points: list[float] | None
operators: list[float] | None
isClipPath: _BoolLike
autoclose: Literal["svg", "pdf"] | None
fillMode: Literal[0, 1]
class _SolidShapeKwArgs(_PathKwArgs, total=False):
fillMode: Literal[0, 1]
class _DefinePathKwArgs(_SolidShapeKwArgs, total=False):
autoclose: Literal["svg", "pdf"] | None
bbox: tuple[float, float, float, float] | None
class _WedgeKwArgs(_SolidShapeKwArgs, total=False):
radius1: float | None
yradius1: float | None
class _StringKwArgs(TypedDict, total=False):
fontName: str
fontSize: float
fillColor: Color | None
textAnchor: Literal["start", "middle", "end", "numeric"]
encoding: str
textRenderMode: Literal[0, 1, 2, 3, 4, 5, 6, 7]
__version__: Final[str]
isOpacity: NoneOr
@@ -16,61 +101,63 @@ STATE_DEFAULTS: Final[Incomplete]
class _DrawTimeResizeable: ...
class _SetKeyWordArgs:
def __init__(self, keywords={}) -> None: ...
def __init__(self, keywords: SupportsItems[str, Any] = {}) -> None: ...
def getRectsBounds(rectList): ...
def getPathBounds(points): ...
def getPointsBounds(pointList): ...
class Shape(_SetKeyWordArgs, _DrawTimeResizeable):
def copy(self) -> None: ...
def getProperties(self, recur: int = 1): ...
@abstractmethod
def copy(self) -> Self: ...
def getProperties(self, recur: int = 1) -> dict[str, Any]: ...
def setProperties(self, props) -> None: ...
def dumpProperties(self, prefix: str = "") -> None: ...
def verify(self) -> None: ...
def __setattr__(self, attr, value) -> None: ...
def getBounds(self) -> None: ...
@abstractmethod
def getBounds(self) -> tuple[float, float, float, float]: ...
class Group(Shape):
contents: Incomplete
transform: Incomplete
def __init__(self, *elements, **keywords) -> None: ...
def add(self, node, name: Incomplete | None = None) -> None: ...
def insert(self, i, n, name: Incomplete | None = None) -> None: ...
def expandUserNodes(self): ...
def copy(self): ...
def rotate(self, theta) -> None: ...
def translate(self, dx, dy) -> None: ...
def scale(self, sx, sy) -> None: ...
def skew(self, kx, ky) -> None: ...
def shift(self, x, y) -> None: ...
__class__: Incomplete
width: Incomplete
height: Incomplete
def asDrawing(self, width, height) -> None: ...
def getContents(self): ...
def getBounds(self): ...
contents: list[Shape]
transform: tuple[float, float, float, float, float, float] | list[float] | list[int]
def __init__(self, *elements: Shape | UserNode, **keywords: Unpack[_GroupKwArgs]) -> None: ...
def add(self, node: Shape | UserNode, name: str | None = None) -> None: ...
def insert(self, i: int, n: Shape | UserNode, name: str | None = None) -> None: ...
def expandUserNodes(self) -> Group: ...
def copy(self) -> Self: ...
def rotate(self, theta: float) -> None: ...
def translate(self, dx: float, dy: float) -> None: ...
def scale(self, sx: float, sy: float) -> None: ...
def skew(self, kx: float, ky: float) -> None: ...
def shift(self, x: float, y: float) -> None: ...
# NOTE: This changes the object to a Drawing, rather than returning
# a new one, which is not ideal...
def asDrawing(self, width: float, height: float) -> None: ...
def getContents(self) -> list[Shape | UserNode]: ...
def getBounds(self) -> tuple[float, float, float, float]: ...
class Drawing(Group, Flowable):
background: Incomplete
background: Shape | UserNode | None
renderScale: float
def __init__(self, width: int = 400, height: int = 200, *nodes, **keywords) -> None: ...
def __init__(
self, width: float = 400, height: float = 200, *nodes: Shape | UserNode, **keywords: Unpack[_DrawingKwArgs]
) -> None: ...
def draw(self, showBoundary=...) -> None: ...
def wrap(self, availWidth, availHeight): ...
def expandUserNodes(self): ...
def copy(self): ...
def asGroup(self, *args, **kw): ...
def expandUserNodes(self) -> Drawing: ...
def asGroup(self, *args: Shape | UserNode, **kw: Unpack[_GroupKwArgs]) -> Group: ...
def save(
self,
formats: Incomplete | None = None,
verbose: Incomplete | None = None,
fnRoot: Incomplete | None = None,
outDir: Incomplete | None = None,
formats: Iterable[str] | None = None,
verbose: bool | None = None,
fnRoot: str | None = None,
outDir: str | None = None,
title: str = "",
**kw,
): ...
def asString(self, format, verbose: Incomplete | None = None, preview: int = 0, **kw): ...
def resized(self, kind: str = "fit", lpad: int = 0, rpad: int = 0, bpad: int = 0, tpad: int = 0): ...
def asString(self, format: str, verbose: bool | None = None, preview: int = 0, **kw) -> str: ...
def resized(
self, kind: Literal["fit", "fitx", "fity"] = "fit", lpad: float = 0, rpad: float = 0, bpad: float = 0, tpad: float = 0
) -> Drawing: ...
class _DrawingEditorMixin: ...
@@ -80,174 +167,205 @@ class _isStrokeDashArray(Validator):
isStrokeDashArray: _isStrokeDashArray
class LineShape(Shape):
strokeColor: Incomplete
strokeWidth: int
strokeLineCap: int
strokeLineJoin: int
strokeMiterLimit: int
strokeDashArray: Incomplete
strokeOpacity: Incomplete
def __init__(self, kw) -> None: ...
strokeColor: Color | None
strokeWidth: float
strokeLineCap: Literal[0, 1, 2]
strokeLineJoin: Literal[0, 1, 2]
strokeMiterLimit: float
strokeDashArray: Sequence[float] | tuple[float, Sequence[float]]
strokeOpacity: float | None
def __init__(self, kw: _LineShapeKwArgs) -> None: ...
@abstractmethod
def copy(self) -> Self: ...
@abstractmethod
def getBounds(self) -> tuple[float, float, float, float]: ...
class Line(LineShape):
x1: Incomplete
y1: Incomplete
x2: Incomplete
y2: Incomplete
def __init__(self, x1, y1, x2, y2, **kw) -> None: ...
def getBounds(self): ...
x1: float
y1: float
x2: float
y2: float
def __init__(self, x1: float, y1: float, x2: float, y2: float, **kw: Unpack[_LineShapeKwArgs]) -> None: ...
# NOTE: For some reason Line doesn't implement copy
def copy(self) -> NoReturn: ...
def getBounds(self) -> tuple[float, float, float, float]: ...
class SolidShape(LineShape):
fillColor: Incomplete
fillOpacity: Incomplete
def __init__(self, kw) -> None: ...
fillColor: Color | None
fillOpacity: float | None
def __init__(self, kw: _SolidShapeKwArgs) -> None: ...
@abstractmethod
def copy(self) -> Self: ...
@abstractmethod
def getBounds(self) -> tuple[float, float, float, float]: ...
class Path(SolidShape):
points: Incomplete
operators: Incomplete
isClipPath: Incomplete
autoclose: Incomplete
fillMode: Incomplete
points: list[float]
operators: list[float]
isClipPath: _BoolLike
autoclose: Literal["svg", "pdf"] | None
fillMode: Literal[0, 1]
def __init__(
self,
points: Incomplete | None = None,
operators: Incomplete | None = None,
isClipPath: int = 0,
autoclose: Incomplete | None = None,
fillMode=0,
**kw,
points: list[float] | None = None,
operators: list[float] | None = None,
isClipPath: _BoolLike = 0,
autoclose: Literal["svg", "pdf"] | None = None,
fillMode: Literal[0, 1] = 0,
**kw: Unpack[_PathKwArgs],
) -> None: ...
def copy(self): ...
def moveTo(self, x, y) -> None: ...
def lineTo(self, x, y) -> None: ...
def curveTo(self, x1, y1, x2, y2, x3, y3) -> None: ...
def copy(self) -> Self: ...
def moveTo(self, x: float, y: float) -> None: ...
def lineTo(self, x: float, y: float) -> None: ...
def curveTo(self, x1: float, y1: float, x2: float, y2: float, x3: float, y3: float) -> None: ...
def closePath(self) -> None: ...
def getBounds(self): ...
def getBounds(self) -> tuple[float, float, float, float]: ...
EmptyClipPath: Incomplete
EmptyClipPath: Final[Path]
def getArcPoints(
centerx,
centery,
radius,
startangledegrees,
endangledegrees,
yradius: Incomplete | None = None,
degreedelta: Incomplete | None = None,
reverse: Incomplete | None = None,
): ...
centerx: float,
centery: float,
radius: float,
startangledegrees: float,
endangledegrees: float,
yradius: float | None = None,
degreedelta: float | None = None,
reverse: _BoolLike | None = None,
) -> list[float]: ...
class ArcPath(Path):
def addArc(
self,
centerx,
centery,
radius,
startangledegrees,
endangledegrees,
yradius: Incomplete | None = None,
degreedelta: Incomplete | None = None,
moveTo: Incomplete | None = None,
reverse: Incomplete | None = None,
centerx: float,
centery: float,
radius: float,
startangledegrees: float,
endangledegrees: float,
yradius: float | None = None,
degreedelta: float | None = None,
moveTo: _BoolLike | None = None,
reverse: _BoolLike | None = None,
) -> None: ...
def definePath(pathSegs=[], isClipPath: int = 0, dx: int = 0, dy: int = 0, **kw): ...
def definePath(
pathSegs: Iterable[_PathOp] = [], isClipPath: _BoolLike = 0, dx: float = 0, dy: float = 0, **kw: Unpack[_DefinePathKwArgs]
) -> Path: ...
class Rect(SolidShape):
x: Incomplete
y: Incomplete
width: Incomplete
height: Incomplete
rx: Incomplete
ry: Incomplete
def __init__(self, x, y, width, height, rx: int = 0, ry: int = 0, **kw) -> None: ...
def copy(self): ...
def getBounds(self): ...
x: float
y: float
width: float
height: float
rx: float
ry: float
def __init__(
self, x: float, y: float, width: float, height: float, rx: float = 0, ry: float = 0, **kw: _SolidShapeKwArgs
) -> None: ...
def copy(self) -> Self: ...
def getBounds(self) -> tuple[float, float, float, float]: ...
class Image(SolidShape):
x: Incomplete
y: Incomplete
width: Incomplete
height: Incomplete
x: float
y: float
width: float
height: float
path: Incomplete
def __init__(self, x, y, width, height, path, **kw) -> None: ...
def copy(self): ...
def getBounds(self): ...
def __init__(self, x: float, y: float, width: float, height: float, path, **kw: Unpack[_SolidShapeKwArgs]) -> None: ...
def copy(self) -> Self: ...
def getBounds(self) -> tuple[float, float, float, float]: ...
class Circle(SolidShape):
cx: Incomplete
cy: Incomplete
r: Incomplete
def __init__(self, cx, cy, r, **kw) -> None: ...
def copy(self): ...
def getBounds(self): ...
cx: float
cy: float
r: float
def __init__(self, cx: float, cy: float, r: float, **kw: Unpack[_SolidShapeKwArgs]) -> None: ...
def copy(self) -> Self: ...
def getBounds(self) -> tuple[float, float, float, float]: ...
class Ellipse(SolidShape):
cx: Incomplete
cy: Incomplete
rx: Incomplete
ry: Incomplete
def __init__(self, cx, cy, rx, ry, **kw) -> None: ...
def copy(self): ...
def getBounds(self): ...
cx: float
cy: float
rx: float
ry: float
def __init__(self, cx: float, cy: float, rx: float, ry: float, **kw: Unpack[_SolidShapeKwArgs]) -> None: ...
def copy(self) -> Self: ...
def getBounds(self) -> tuple[float, float, float, float]: ...
class Wedge(SolidShape):
degreedelta: int
yradius: Incomplete
annular: Incomplete
centerx: float
centery: float
radius: float
startangledegrees: float
endangledegrees: float
yradius: float | None
annular: bool
# NOTE: This one is not actually settable on the instance if runtime validation
# is turned on, but it seems bad to disallow it anyways
degreedelta: float
def __init__(
self,
centerx,
centery,
radius,
startangledegrees,
endangledegrees,
yradius: Incomplete | None = None,
centerx: float,
centery: float,
radius: float,
startangledegrees: float,
endangledegrees: float,
yradius: float | None = None,
annular: bool = False,
**kw,
**kw: Unpack[_WedgeKwArgs],
) -> None: ...
def asPolygon(self): ...
def copy(self): ...
def getBounds(self): ...
def asPolygon(self) -> Path | Polygon: ...
def copy(self) -> Self: ...
def getBounds(self) -> tuple[float, float, float, float]: ...
class Polygon(SolidShape):
points: Incomplete
def __init__(self, points=[], **kw) -> None: ...
def copy(self): ...
def getBounds(self): ...
points: list[float]
def __init__(self, points: list[float] = [], **kw: Unpack[_SolidShapeKwArgs]) -> None: ...
def copy(self) -> Self: ...
def getBounds(self) -> tuple[float, float, float, float]: ...
class PolyLine(LineShape):
points: Incomplete
def __init__(self, points=[], **kw) -> None: ...
def copy(self): ...
def getBounds(self): ...
points: list[float]
def __init__(self, points: list[float] = [], **kw: Unpack[_SolidShapeKwArgs]) -> None: ...
def copy(self) -> Self: ...
def getBounds(self) -> tuple[float, float, float, float]: ...
class Hatching(Path):
xyLists: Incomplete
angles: Incomplete
spacings: Incomplete
def __init__(self, spacings: int = 2, angles: int = 45, xyLists=[], **kwds) -> None: ...
xyLists: Sequence[tuple[float, float]]
angles: Sequence[float]
spacings: Sequence[float]
def __init__(
self,
spacings: float | Sequence[float] = 2,
angles: float | Sequence[float] = 45,
xyLists: Sequence[tuple[float, float] | list[float]] = [],
**kwds: Unpack[_AllPathKwArgs],
) -> None: ...
def numericXShift(tA, text, w, fontName, fontSize, encoding: Incomplete | None = None, pivotCharacter="."): ...
def numericXShift(
tA, text: str, w: float, fontName: str, fontSize: float, encoding: str | None = None, pivotCharacter: str = "."
) -> float: ...
class String(Shape):
encoding: str
x: Incomplete
y: Incomplete
text: Incomplete
textAnchor: str
fontName: Incomplete
fontSize: Incomplete
fillColor: Incomplete
def __init__(self, x, y, text, **kw) -> None: ...
x: float
y: float
text: str
textAnchor: Literal["start", "middle", "end", "numeric"]
fontName: str
fontSize: float
fillColor: Color | None
def __init__(self, x: float, y: float, text: str, **kw: Unpack[_StringKwArgs]) -> None: ...
def getEast(self): ...
def copy(self): ...
def getBounds(self): ...
def copy(self) -> Self: ...
def getBounds(self) -> tuple[float, float, float, float]: ...
class UserNode(_DrawTimeResizeable):
def provideNode(self) -> None: ...
@abstractmethod
def provideNode(self) -> Shape: ...
class DirectDraw(Shape):
def drawDirectly(self, canvas) -> None: ...
@abstractmethod
def drawDirectly(self, canvas: Canvas) -> None: ...
def test() -> None: ...

View File

@@ -15,10 +15,11 @@ class PropHolder:
def dumpProperties(self, prefix: str = "") -> None: ...
class Widget(PropHolder, shapes.UserNode):
# TODO: draw should probably be marked abstract
def draw(self) -> None: ...
def demo(self) -> None: ...
def provideNode(self): ...
def getBounds(self): ...
def provideNode(self) -> shapes.Shape: ...
def getBounds(self) -> tuple[float, float, float, float]: ...
class ScaleWidget(Widget):
x: Incomplete

View File

@@ -1,5 +1,5 @@
from _typeshed import Incomplete
from typing import Final
from typing import Final, NoReturn
from reportlab.graphics.shapes import LineShape
from reportlab.graphics.widgetbase import Widget
@@ -72,3 +72,5 @@ class ShadedPolygon(Widget, LineShape):
points: Incomplete
def __init__(self, **kw) -> None: ...
def draw(self): ...
# NOTE: widgets don't implement this, only actual shapes
def copy(self) -> NoReturn: ...

View File

@@ -63,9 +63,9 @@ class Table(Flowable):
spaceAfter: float
def __init__(
self,
data: list[list[Any]] | tuple[tuple[Any, ...], ...],
# NOTE: Technically only list or tuple works but lack of covariance
# on list makes this too annoying
data: Sequence[list[Any] | tuple[Any, ...]],
colWidths: Sequence[float | str | None] | float | str | None = None,
rowHeights: Sequence[float | None] | float | None = None,
style: TableStyle | Iterable[_TableCommand] | None = None,