Skip to content

Commit

Permalink
Merge pull request #4 from PyFPDF/master
Browse files Browse the repository at this point in the history
rebase
  • Loading branch information
andersonhc committed Aug 2, 2023
2 parents 29d01fa + dface79 commit 04a1807
Show file tree
Hide file tree
Showing 27 changed files with 282 additions and 120 deletions.
9 changes: 9 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,15 @@
"contributions": [
"code"
]
},
{
"login": "lfavole",
"name": "lfavole",
"avatar_url": "https://avatars.githubusercontent.com/u/88188568?v=4",
"profile": "http://lfavole.eu.pythonanywhere.com",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/continuous-integration-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ jobs:
export PYTHONPATH=$PWD
# Using Datalogics PDF Checker:
scripts/install-pdfchecker.sh
find . -name '*.pdf' | xargs -n 1 scripts/pdfchecker.py
scripts/pdfchecker.py # printing aggregated report
scripts/pdfchecker.py --process-all-test-pdf-files
scripts/pdfchecker.py --print-aggregated-report
# Using VeraPDF:
scripts/install-verapdf.sh
find . -name '*.pdf' | xargs -n 1 scripts/verapdf.py
scripts/verapdf.py # printing aggregated report
scripts/verapdf.py --process-all-test-pdf-files
scripts/verapdf.py --print-aggregated-report
- name: Running tests ☑
env:
CHECK_EXEC_TIME: ${{ matrix.python-version == '3.9' && 'test-enabled' || '' }}
Expand Down
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ This can also be enabled programmatically with `warnings.simplefilter('default',
- [`FPDF.image()`](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image): allowing images path starting with `data` to be passed as input
- text overflow is better handled by `FPDF.write()` & `FPDF.write_html()` - _cf._ [issue #847](https://github.com/PyFPDF/fpdf2/issues/847)
- the initial text color is preserved when using `FPDF.write_html()` - _cf._ [issue #846](https://github.com/PyFPDF/fpdf2/issues/846)
- handle superscript and subscript correctly when rendering `TextLine`- [Pull Request #862](https://github.com/PyFPDF/fpdf2/pull/862)
- PDF metadata not encrypted - _cf._ [issue #865](https://github.com/PyFPDF/fpdf2/issues/865)
- handle superscript and subscript correctly when rendering `TextLine`- thanks to @Tolker-KU - _cf._ [Pull Request #862](https://github.com/PyFPDF/fpdf2/pull/862)
- make sure warnings always point to the users code - _cf._ [Pull request #869](https://github.com/PyFPDF/fpdf2/pull/869)
### Deprecated
- the `center` optional parameter of [`FPDF.cell()`](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.cell) is **no more** deprecated, as it allows for horizontal positioning, which is different from text alignment control with `align="C"`

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ This library could only exist thanks to the dedication of many volunteers around
<td align="center" valign="top" width="14.28%"><a href="https://github.com/stenci"><img src="https://avatars.githubusercontent.com/u/5955495?v=4?s=100" width="100px;" alt="stenci"/><br /><sub><b>stenci</b></sub></a><br /><a href="https://github.com/PyFPDF/fpdf2/issues?q=author%3Astenci" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/alcnaka"><img src="https://avatars.githubusercontent.com/u/47954083?v=4?s=100" width="100px;" alt="alcnaka"/><br /><sub><b>alcnaka</b></sub></a><br /><a href="#translation-alcnaka" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Tolker-KU"><img src="https://avatars.githubusercontent.com/u/55140581?v=4?s=100" width="100px;" alt="Tolker-KU"/><br /><sub><b>Tolker-KU</b></sub></a><br /><a href="https://github.com/PyFPDF/fpdf2/commits?author=Tolker-KU" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://lfavole.eu.pythonanywhere.com"><img src="https://avatars.githubusercontent.com/u/88188568?v=4?s=100" width="100px;" alt="lfavole"/><br /><sub><b>lfavole</b></sub></a><br /><a href="https://github.com/PyFPDF/fpdf2/commits?author=lfavole" title="Code">💻</a></td>
</tr>
</tbody>
</table>
Expand Down
28 changes: 26 additions & 2 deletions fpdf/deprecation.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import contextlib
import inspect
import os.path
import warnings
from types import ModuleType

Expand All @@ -19,7 +22,7 @@ def __getattr__(self, name):
" have been deprecated in favour of"
" FPDF(font_cache_dir=...)",
DeprecationWarning,
stacklevel=2,
stacklevel=get_stack_level(),
)
return None
return super().__getattribute__(name)
Expand All @@ -32,7 +35,28 @@ def __setattr__(self, name, value):
" have been deprecated in favour of"
" FPDF(font_cache_dir=...)",
DeprecationWarning,
stacklevel=2,
stacklevel=get_stack_level(),
)
return
super().__setattr__(name, value)


def get_stack_level() -> int:
"""Get the first place in the call stack that is not inside fpdf2"""

# pylint: disable=import-outside-toplevel
import fpdf # pylint: disable=cyclic-import

pkg_dir = os.path.dirname(fpdf.__file__)
contextlib_dir = os.path.dirname(contextlib.__file__)

frame = inspect.currentframe()
n = 0
while frame is not None:
fname = inspect.getfile(frame)
if fname.startswith(pkg_dir) or fname.startswith(contextlib_dir):
frame = frame.f_back
n += 1
else:
break
return n
47 changes: 28 additions & 19 deletions fpdf/fpdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class Image:
PDFEmbeddedFile,
DEFAULT_ANNOT_FLAGS,
)
from .deprecation import WarnOnDeprecatedModuleAttributes
from .deprecation import get_stack_level, WarnOnDeprecatedModuleAttributes
from .encryption import StandardSecurityHandler
from .enums import (
AccessPermission,
Expand Down Expand Up @@ -254,7 +254,7 @@ def __init__(
warnings.warn(
'"font_cache_dir" parameter is deprecated, unused and will soon be removed',
DeprecationWarning,
stacklevel=2,
stacklevel=get_stack_level(),
)
super().__init__()
self.page = 0 # current page number
Expand Down Expand Up @@ -753,7 +753,7 @@ def set_doc_option(self, opt, value):
"set_doc_option() is deprecated and will be removed in a future release. "
"Simply set the `.core_fonts_encoding` property as a replacement.",
DeprecationWarning,
stacklevel=2,
stacklevel=get_stack_level(),
)
if opt != "core_fonts_encoding":
raise FPDFException(f'Unknown document option "{opt}"')
Expand Down Expand Up @@ -1251,7 +1251,7 @@ def polyline(self, point_list, fill=False, polygon=False, style=None):
warnings.warn(
'"fill" parameter is deprecated, use style="F" or style="DF" instead',
DeprecationWarning,
stacklevel=5 if polygon else 3,
stacklevel=get_stack_level(),
)
if fill and style is None:
style = RenderStyle.DF
Expand Down Expand Up @@ -1308,7 +1308,7 @@ def dashed_line(self, x1, y1, x2, y2, dash_length=1, space_length=1):
"dashed_line() is deprecated, and will be removed in a future release. "
"Use set_dash_pattern() and the normal drawing operations instead.",
DeprecationWarning,
stacklevel=3,
stacklevel=get_stack_level(),
)
self.set_dash_pattern(dash_length, space_length)
self.line(x1, y1, x2, y2)
Expand Down Expand Up @@ -1789,7 +1789,7 @@ def add_font(self, family=None, style="", fname=None, uni="DEPRECATED"):
warnings.warn(
'"uni" parameter is deprecated, unused and will soon be removed',
DeprecationWarning,
stacklevel=2,
stacklevel=get_stack_level(),
)

style = "".join(sorted(style.upper()))
Expand All @@ -1814,7 +1814,10 @@ def add_font(self, family=None, style="", fname=None, uni="DEPRECATED"):
fontkey = f"{family.lower()}{style}"
# Check if font already added or one of the core fonts
if fontkey in self.fonts or fontkey in CORE_FONTS:
warnings.warn(f"Core font or font already added '{fontkey}': doing nothing")
warnings.warn(
f"Core font or font already added '{fontkey}': doing nothing",
stacklevel=get_stack_level(),
)
return

self.fonts[fontkey] = TTFFont(self, font_file_path, fontkey, style)
Expand Down Expand Up @@ -1863,13 +1866,15 @@ def set_font(self, family=None, style="", size=0):
if family in self.font_aliases and family + style not in self.fonts:
warnings.warn(
f"Substituting font {family} by core font "
f"{self.font_aliases[family]}"
f"{self.font_aliases[family]}",
stacklevel=get_stack_level(),
)
family = self.font_aliases[family]
elif family in ("symbol", "zapfdingbats") and style:
warnings.warn(
f"Built-in font {family} only has a single 'style' and can't be bold "
f"or italic"
f"or italic",
stacklevel=get_stack_level(),
)
style = ""

Expand Down Expand Up @@ -2397,7 +2402,7 @@ def rotate(self, angle, x=None, y=None):
"It will be removed in a future release. "
"Use the rotation() context manager instead.",
DeprecationWarning,
stacklevel=3,
stacklevel=get_stack_level(),
)
if x is None:
x = self.x
Expand Down Expand Up @@ -2703,7 +2708,8 @@ def cell(
)
if isinstance(border, int) and border not in (0, 1):
warnings.warn(
'Integer values for "border" parameter other than 1 are currently ignored'
'Integer values for "border" parameter other than 1 are currently ignored',
stacklevel=get_stack_level(),
)
border = 1
new_x = XPos.coerce(new_x)
Expand Down Expand Up @@ -2735,7 +2741,7 @@ def cell(
f" Instead of ln={ln} use new_x=XPos.{new_x.name}, new_y=YPos.{new_y.name}."
),
DeprecationWarning,
stacklevel=3,
stacklevel=get_stack_level(),
)
# Font styles preloading must be performed before any call to FPDF.get_string_width:
txt = self.normalize_text(txt)
Expand Down Expand Up @@ -2811,7 +2817,8 @@ def _render_styled_text_line(
"""
if isinstance(border, int) and border not in (0, 1):
warnings.warn(
'Integer values for "border" parameter other than 1 are currently ignored'
'Integer values for "border" parameter other than 1 are currently ignored',
stacklevel=get_stack_level(),
)
border = 1
styled_txt_width = text_line.text_width
Expand Down Expand Up @@ -3369,7 +3376,7 @@ def multi_cell(
'The parameter "split_only" is deprecated.'
' Use instead dry_run=True and output="LINES".',
DeprecationWarning,
stacklevel=3,
stacklevel=get_stack_level(),
)
if dry_run or split_only:
with self._disable_writing():
Expand Down Expand Up @@ -3429,7 +3436,7 @@ def multi_cell(
f" Instead of ln={ln} use new_x=XPos.{new_x.name}, new_y=YPos.{new_y.name}."
),
DeprecationWarning,
stacklevel=3,
stacklevel=get_stack_level(),
)
align = Align.coerce(align)

Expand Down Expand Up @@ -3734,7 +3741,7 @@ def image(
warnings.warn(
'"type" parameter is deprecated, unused and will soon be removed',
DeprecationWarning,
stacklevel=3,
stacklevel=get_stack_level(),
)
if str(name).endswith(".svg"):
# Insert it as a PDF path:
Expand Down Expand Up @@ -3876,7 +3883,8 @@ def _vector_image(
svg = SVGObject(img.getvalue())
if not svg.viewbox and svg.width and svg.height:
warnings.warn(
'<svg> has no "viewBox", using its "width" & "height" as default "viewBox"'
'<svg> has no "viewBox", using its "width" & "height" as default "viewBox"',
stacklevel=get_stack_level(),
)
svg.viewbox = 0, 0, svg.width, svg.height
if w == 0 and h == 0:
Expand Down Expand Up @@ -4370,7 +4378,8 @@ def code39(self, txt, x, y, w=1.5, h=5):
warnings.warn(
# pylint: disable=implicit-str-concat
"Code 39 input must start and end with a '*' character to be valid."
" This method does not insert it automatically."
" This method does not insert it automatically.",
stacklevel=get_stack_level(),
)
chars = {
"0": "nnnwwnwnn",
Expand Down Expand Up @@ -4742,7 +4751,7 @@ def output(
warnings.warn(
'"dest" parameter is deprecated, unused and will soon be removed',
DeprecationWarning,
stacklevel=2,
stacklevel=get_stack_level(),
)
# Finish document if necessary:
if not self.buffer:
Expand Down
7 changes: 4 additions & 3 deletions fpdf/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from .enums import TextEmphasis, XPos, YPos
from .errors import FPDFException
from .deprecation import get_stack_level
from .fonts import FontFace
from .table import Table, TableBordersLayout

Expand Down Expand Up @@ -266,9 +267,9 @@ def handle_data(self, data):
if not data:
return
if "inserted" in self.td_th:
tag = self.td_th["tag"]
td_th_tag = self.td_th["tag"]
raise NotImplementedError(
f"Unsupported nested HTML tags inside <{tag}> element"
f"Unsupported nested HTML tags inside <{td_th_tag}> element: <{self._tags_stack[-1]}>"
)
# We could potentially support nested <b> / <em> / <font> tags
# by building a list of Fragment instances from the HTML cell content
Expand Down Expand Up @@ -726,5 +727,5 @@ def __init__(self, *args, **kwargs):
"The HTMLMixin class is deprecated. "
"Simply use the FPDF class as a replacement.",
DeprecationWarning,
stacklevel=2,
stacklevel=get_stack_level(),
)
12 changes: 6 additions & 6 deletions fpdf/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,12 @@ def __init__(
creation_date: PDFDate,
):
super().__init__()
self.title = PDFString(title) if title else None
self.subject = PDFString(subject) if subject else None
self.author = PDFString(author) if author else None
self.keywords = PDFString(keywords) if keywords else None
self.creator = PDFString(creator) if creator else None
self.producer = PDFString(producer) if producer else None
self.title = PDFString(title, encrypt=True) if title else None
self.subject = PDFString(subject, encrypt=True) if subject else None
self.author = PDFString(author, encrypt=True) if author else None
self.keywords = PDFString(keywords, encrypt=True) if keywords else None
self.creator = PDFString(creator, encrypt=True) if creator else None
self.producer = PDFString(producer, encrypt=True) if producer else None
self.creation_date = creation_date


Expand Down
4 changes: 3 additions & 1 deletion fpdf/recorder.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import types, warnings
from copy import deepcopy

from .deprecation import get_stack_level
from .errors import FPDFException


Expand Down Expand Up @@ -48,7 +49,8 @@ def replay(self):
result = func(*args, **kwargs)
if isinstance(result, types.GeneratorType):
warnings.warn(
"Detected usage of a context manager inside an unbreakable() section, which is not supported"
"Detected usage of a context manager inside an unbreakable() section, which is not supported",
stacklevel=get_stack_level(),
)
# The results of other methods can also be invalidated: .pages_count, page_no(), get_x() / get_y(), will_page_break()
except Exception as error:
Expand Down
7 changes: 4 additions & 3 deletions fpdf/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import csv, locale, warnings

from .deprecation import get_stack_level
from .errors import FPDFException
from .fpdf import FPDF

Expand Down Expand Up @@ -480,7 +481,7 @@ def _code39(
warnings.warn(
"code39 arguments x/y/w/h are deprecated, please use x1/y1/y2/size instead",
DeprecationWarning,
stacklevel=2,
stacklevel=get_stack_level(),
)
pdf = self.pdf
if pdf.fill_color.serialize().lower() != _rgb_as_str(foreground):
Expand Down Expand Up @@ -637,7 +638,7 @@ def __init__(
warnings.warn(
'"infile" is deprecated, unused and will soon be removed',
DeprecationWarning,
stacklevel=2,
stacklevel=get_stack_level(),
)
for arg in (
"format",
Expand Down Expand Up @@ -684,7 +685,7 @@ def render(self, outfile=None, dest=None):
warnings.warn(
'"dest" is deprecated, unused and will soon be removed',
DeprecationWarning,
stacklevel=2,
stacklevel=get_stack_level(),
)
self.pdf.set_font("helvetica", "B", 16)
self.pdf.set_auto_page_break(False, margin=0)
Expand Down
Loading

0 comments on commit 04a1807

Please sign in to comment.