<commit_before># coding=utf-8

from reportlab.lib import colors
from reportlab.lib.enums import TA_LEFT, TA_RIGHT
from reportlab.lib.fonts import addMapping
from reportlab.lib.pagesizes import A4, landscape, portrait
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
from reportlab.lib.units import cm, mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas
from reportlab.platypus import (BaseDocTemplate, Spacer, Frame,
    PageTemplate, NextPageTemplate, PageBreak, Table, TableStyle, Image,
    Preformatted, Flowable, XPreformatted, KeepTogether, CondPageBreak,
    Paragraph as _Paragraph)
from reportlab.platypus.flowables import HRFlowable

import os
import copy
from datetime import date, datetime
import unicodedata


def register_fonts_from_paths(regular, italic=None, bold=None, bolditalic=None,
        font_name='Reporting'):
    """
    Pass paths to TTF files which should be used for the PDFDocument
    """

    pdfmetrics.registerFont(TTFont('%s' % font_name, regular))
    pdfmetrics.registerFont(TTFont('%s-Italic' % font_name, italic or regular))
    pdfmetrics.registerFont(TTFont('%s-Bold' % font_name, bold or regular))
    pdfmetrics.registerFont(TTFont('%s-BoldItalic' % font_name, bolditalic or bold or regular))

    addMapping('%s' % font_name, 0, 0, '%s' % font_name) # regular
    addMapping('%s' % font_name, 0, 1, '%s-Italic' % font_name) # italic
    addMapping('%s' % font_name, 1, 0, '%s-Bold' % font_name) # bold
    addMapping('%s' % font_name, 1, 1, '%s-BoldItalic' % font_name) # bold & italic


class Empty(object):
    pass


def sanitize(text):
    REPLACE_MAP = [ (u'&', '&#38;'),
                    (u'<', '&#60;'),
                    (u'>', '&#62;'),
                    (u'ç', '&#231;'),
                    (u'Ç', '&#199;'),
                    (u'\n', '<br />'),
                    (u'\r', ''), ]

    for p, q in REPLACE_MAP:
        text = text.replace(p, q)
    return text


def normalize(text):
    """
    Some layers of reportlab, PDF or font handling or whatever cannot handle
    german umlauts in decomposed form correctly. Normalize everything to
    NFKC.
    """
    if not isinstance(text, unicode):
        text = unicode(text)
    return unicodedata.normalize('NFKC', text)


def MarkupParagraph(txt, *args, **kwargs):
    if not txt: return _Paragraph(u'', *args, **kwargs)
    return _Paragraph(normalize(txt), *args, **kwargs)


def Paragraph(txt, *args, **kwargs):
    if not txt: return _Paragraph(u'', *args, **kwargs)
    return _Paragraph(sanitize(normalize(txt)), *args, **kwargs)


class BottomTable(Table):
    """
    This table will automatically be moved to the bottom of the page using the
    BottomSpacer right before it.
    """
    pass


class BottomSpacer(Spacer):
    def wrap(self, availWidth, availHeight):
        my_height = availHeight-self._doc.bottomTableHeight

        if my_height<=0:
            return (self.width, availHeight)
        else:
            return (self.width, my_height)


class RestartPageBreak(PageBreak):
    """
    Insert a page break and restart the page numbering.
    """
    pass


class ReportingDocTemplate(BaseDocTemplate):
    def __init__(self, *args, **kwargs):
        BaseDocTemplate.__init__(self, *args, **kwargs)
        self.bottomTableHeight = 0
        self.bottomTableIsLast = False
        self.numPages = 0
        self._lastNumPages = 0
        self.setProgressCallBack(self._onProgress_cb)

        # For batch reports with several PDFs concatenated
        self.restartDoc = False
        self.restartDocIndex = 0
        self.restartDocPageNumbers = []

    def afterFlowable(self, flowable):
        self.numPages = max(self.canv.getPageNumber(), self.numPages)
        self.bottomTableIsLast = False

        if isinstance(flowable, BottomTable):
            self.bottomTableHeight = reduce(
                lambda p, q: p+q,
                flowable._rowHeights,
                0)

            self.bottomTableIsLast = True

        elif isinstance(flowable, RestartPageBreak):
            self.restartDoc = True
            self.restartDocIndex += 1
            self.restartDocPageNumbers.append(self.page)

    # here the real hackery starts ... thanks Ralph
    def _allSatisfied(self):
        """ Called by multi-build - are all cross-references resolved? """
        if self._lastNumPages < self.numPages:
            return 0
        return BaseDocTemplate._allSatisfied(self)

    def _onProgress_cb(self, what, arg):
        if what=='STARTED':
            self._lastNumPages = self.numPages
            self.restartDocIndex = 0
            #self.restartDocPageNumbers = []

    def page_index(self):
        """
        Return the current page index as a tuple (current_page, total_pages)

        This is the ugliest thing I've done in the last two years.
        For this I'll burn in programmer hell.

        At least it is contained here.

        (Determining the total number of pages in reportlab is a mess anyway...)
        """

        current_page = self.page
        total_pages = self.numPages

        if self.restartDoc:
            if self.restartDocIndex:
                current_page = current_page - self.restartDocPageNumbers[self.restartDocIndex-1] + 1
                if len(self.restartDocPageNumbers) > self.restartDocIndex:
                    total_pages = self.restartDocPageNumbers[self.restartDocIndex] - self.restartDocPageNumbers[self.restartDocIndex-1] + 1
            else:
                total_pages = self.restartDocPageNumbers[0]

        if self.bottomTableHeight:
            total_pages -= 1

            if self.bottomTableIsLast and current_page==1:
                total_pages = max(1, total_pages-1)

        # Ensure total pages is always at least 1
        total_pages = max(1, total_pages)

        return (current_page, total_pages)

    def page_index_string(self):
        """<commit_msg>fix total pagecount with bottom-table<commit_after># coding=utf-8

from reportlab.lib import colors
from reportlab.lib.enums import TA_LEFT, TA_RIGHT
from reportlab.lib.fonts import addMapping
from reportlab.lib.pagesizes import A4, landscape, portrait
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
from reportlab.lib.units import cm, mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas
from reportlab.platypus import (BaseDocTemplate, Spacer, Frame,
    PageTemplate, NextPageTemplate, PageBreak, Table, TableStyle, Image,
    Preformatted, Flowable, XPreformatted, KeepTogether, CondPageBreak,
    Paragraph as _Paragraph)
from reportlab.platypus.flowables import HRFlowable

import os
import copy
from datetime import date, datetime
import unicodedata


def register_fonts_from_paths(regular, italic=None, bold=None, bolditalic=None,
        font_name='Reporting'):
    """
    Pass paths to TTF files which should be used for the PDFDocument
    """

    pdfmetrics.registerFont(TTFont('%s' % font_name, regular))
    pdfmetrics.registerFont(TTFont('%s-Italic' % font_name, italic or regular))
    pdfmetrics.registerFont(TTFont('%s-Bold' % font_name, bold or regular))
    pdfmetrics.registerFont(TTFont('%s-BoldItalic' % font_name, bolditalic or bold or regular))

    addMapping('%s' % font_name, 0, 0, '%s' % font_name) # regular
    addMapping('%s' % font_name, 0, 1, '%s-Italic' % font_name) # italic
    addMapping('%s' % font_name, 1, 0, '%s-Bold' % font_name) # bold
    addMapping('%s' % font_name, 1, 1, '%s-BoldItalic' % font_name) # bold & italic


class Empty(object):
    pass


def sanitize(text):
    REPLACE_MAP = [ (u'&', '&#38;'),
                    (u'<', '&#60;'),
                    (u'>', '&#62;'),
                    (u'ç', '&#231;'),
                    (u'Ç', '&#199;'),
                    (u'\n', '<br />'),
                    (u'\r', ''), ]

    for p, q in REPLACE_MAP:
        text = text.replace(p, q)
    return text


def normalize(text):
    """
    Some layers of reportlab, PDF or font handling or whatever cannot handle
    german umlauts in decomposed form correctly. Normalize everything to
    NFKC.
    """
    if not isinstance(text, unicode):
        text = unicode(text)
    return unicodedata.normalize('NFKC', text)


def MarkupParagraph(txt, *args, **kwargs):
    if not txt: return _Paragraph(u'', *args, **kwargs)
    return _Paragraph(normalize(txt), *args, **kwargs)


def Paragraph(txt, *args, **kwargs):
    if not txt: return _Paragraph(u'', *args, **kwargs)
    return _Paragraph(sanitize(normalize(txt)), *args, **kwargs)


class BottomTable(Table):
    """
    This table will automatically be moved to the bottom of the page using the
    BottomSpacer right before it.
    """
    pass


class BottomSpacer(Spacer):
    def wrap(self, availWidth, availHeight):
        my_height = availHeight-self._doc.bottomTableHeight

        if my_height<=0:
            return (self.width, availHeight)
        else:
            return (self.width, my_height)


class RestartPageBreak(PageBreak):
    """
    Insert a page break and restart the page numbering.
    """
    pass


class ReportingDocTemplate(BaseDocTemplate):
    def __init__(self, *args, **kwargs):
        BaseDocTemplate.__init__(self, *args, **kwargs)
        self.bottomTableHeight = 0
        self.bottomTableIsLast = False
        self.numPages = 0
        self._lastNumPages = 0
        self.setProgressCallBack(self._onProgress_cb)

        # For batch reports with several PDFs concatenated
        self.restartDoc = False
        self.restartDocIndex = 0
        self.restartDocPageNumbers = []

    def afterFlowable(self, flowable):
        self.numPages = max(self.canv.getPageNumber(), self.numPages)
        self.bottomTableIsLast = False

        if isinstance(flowable, BottomTable):
            self.bottomTableHeight = reduce(
                lambda p, q: p+q,
                flowable._rowHeights,
                0)

            self.bottomTableIsLast = True

        elif isinstance(flowable, RestartPageBreak):
            self.restartDoc = True
            self.restartDocIndex += 1
            self.restartDocPageNumbers.append(self.page)

    # here the real hackery starts ... thanks Ralph
    def _allSatisfied(self):
        """ Called by multi-build - are all cross-references resolved? """
        if self._lastNumPages < self.numPages:
            return 0
        return BaseDocTemplate._allSatisfied(self)

    def _onProgress_cb(self, what, arg):
        if what=='STARTED':
            self._lastNumPages = self.numPages
            self.restartDocIndex = 0
            #self.restartDocPageNumbers = []

    def page_index(self):
        """
        Return the current page index as a tuple (current_page, total_pages)

        This is the ugliest thing I've done in the last two years.
        For this I'll burn in programmer hell.

        At least it is contained here.

        (Determining the total number of pages in reportlab is a mess anyway...)
        """

        current_page = self.page
        total_pages = self.numPages

        if self.restartDoc:
            if self.restartDocIndex:
                current_page = current_page - self.restartDocPageNumbers[self.restartDocIndex-1] + 1
                if len(self.restartDocPageNumbers) > self.restartDocIndex:
                    total_pages = self.restartDocPageNumbers[self.restartDocIndex] - self.restartDocPageNumbers[self.restartDocIndex-1] + 1
            else:
                total_pages = self.restartDocPageNumbers[0]

        if self.bottomTableHeight:
            total_pages -= 1

            if self.bottomTableIsLast and current_page==1:
                total_pages = max(1, total_pages)

        # Ensure total pages is always at least 1
        total_pages = max(1, total_pages)

        return (current_page, total_pages)

    def page_index_string(self):
        """
{'fraction_non_alphanumeric': 0.101, 'fraction_numerical': 0.0069166666666666664, 'mean_word_length': 2.6756508422664624, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1271934', 'n_tokens_mistral': 3734, 'n_tokens_neox': 3519, 'n_words': 962}