Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37481353
en ru br
Репозитории ALT
S:2.12.0-alt3
5.1: 1.1-alt1
www.altlinux.org/Changes

Группа :: Игры/Карты
Пакет: PySolFC

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: 06d2fd5b90c29cbfe9b938676cc85c514cbbcca1.patch
Скачать


From 06d2fd5b90c29cbfe9b938676cc85c514cbbcca1 Mon Sep 17 00:00:00 2001
From: Shlomi Fish <shlomif@shlomifish.org>
Date: Wed, 11 Aug 2021 19:19:01 +0300
Subject: [PATCH] issue217 : formatting.py deprecated fix.
This file is derived from /usr/lib/python3.9/formatter.py . All changes
are placed under CC0.
See:
* https://github.com/shlomif/PySolFC/issues/217
* https://bugzilla.redhat.com/show_bug.cgi?id=1990043
---
 pysollib/formatter.py        | 474 +++++++++++++++++++++++++++++++++++
 pysollib/htmllib2.py         |  10 +-
 pysollib/kivy/tkhtml.py      |   8 +-
 pysollib/pysolgtk/tkhtml.py  |   8 +-
 pysollib/ui/tktile/tkhtml.py |   8 +-
 5 files changed, 492 insertions(+), 16 deletions(-)
 create mode 100644 pysollib/formatter.py
diff --git a/pysollib/formatter.py b/pysollib/formatter.py
new file mode 100644
index 00000000..f572a7bb
--- /dev/null
+++ b/pysollib/formatter.py
@@ -0,0 +1,474 @@
+"""
+
+This file is derived from /usr/lib/python3.9/formatter.py . All changes
+are placed under CC0.
+
+See:
+
+* https://github.com/shlomif/PySolFC/issues/217
+
+* https://bugzilla.redhat.com/show_bug.cgi?id=1990043
+
+----
+
+Generic output formatting.
+
+Formatter objects transform an abstract flow of formatting events into
+specific output events on writer objects. Formatters manage several stack
+structures to allow various properties of a writer object to be changed and
+restored; writers need not be able to handle relative changes nor any sort
+of ``change back'' operation. Specific writer properties which may be
+controlled via formatter objects are horizontal alignment, font, and left
+margin indentations. A mechanism is provided which supports providing
+arbitrary, non-exclusive style settings to a writer as well. Additional
+interfaces facilitate formatting events which are not reversible, such as
+paragraph separation.
+
+Writer objects encapsulate device interfaces. Abstract devices, such as
+file formats, are supported as well as physical devices. The provided
+implementations all work with abstract devices. The interface makes
+available mechanisms for setting the properties which formatter objects
+manage and inserting data into the output.
+"""
+
+import sys
+if False:
+    import warnings
+    warnings.warn('the formatter module is deprecated', DeprecationWarning,
+                  stacklevel=2)
+
+
+AS_IS = None
+
+
+class NullFormatter:
+    """A formatter which does nothing.
+
+    If the writer parameter is omitted, a NullWriter instance is created.
+    No methods of the writer are called by NullFormatter instances.
+
+    Implementations should inherit from this class if implementing a writer
+    interface but don't need to inherit any implementation.
+
+    """
+
+    def __init__(self, writer=None):
+        if writer is None:
+            writer = NullWriter()
+        self.writer = writer
+
+    def end_paragraph(self, blankline): pass
+    def add_line_break(self): pass
+    def add_hor_rule(self, *args, **kw): pass
+    def add_label_data(self, format, counter, blankline=None): pass
+    def add_flowing_data(self, data): pass
+    def add_literal_data(self, data): pass
+    def flush_softspace(self): pass
+    def push_alignment(self, align): pass
+    def pop_alignment(self): pass
+    def push_font(self, x): pass
+    def pop_font(self): pass
+    def push_margin(self, margin): pass
+    def pop_margin(self): pass
+    def set_spacing(self, spacing): pass
+    def push_style(self, *styles): pass
+    def pop_style(self, n=1): pass
+    def assert_line_data(self, flag=1): pass
+
+
+class AbstractFormatter:
+    """The standard formatter.
+
+    This implementation has demonstrated wide applicability to many writers,
+    and may be used directly in most circumstances.  It has been used to
+    implement a full-featured World Wide Web browser.
+
+    """
+
+    #  Space handling policy:  blank spaces at the boundary between elements
+    #  are handled by the outermost context.  "Literal" data is not checked
+    #  to determine context, so spaces in literal data are handled directly
+    #  in all circumstances.
+
+    def __init__(self, writer):
+        self.writer = writer            # Output device
+        self.align = None               # Current alignment
+        self.align_stack = []           # Alignment stack
+        self.font_stack = []            # Font state
+        self.margin_stack = []          # Margin state
+        self.spacing = None             # Vertical spacing state
+        self.style_stack = []           # Other state, e.g. color
+        self.nospace = 1                # Should leading space be suppressed
+        self.softspace = 0              # Should a space be inserted
+        self.para_end = 1               # Just ended a paragraph
+        self.parskip = 0                # Skipped space between paragraphs?
+        self.hard_break = 1             # Have a hard break
+        self.have_label = 0
+
+    def end_paragraph(self, blankline):
+        if not self.hard_break:
+            self.writer.send_line_break()
+            self.have_label = 0
+        if self.parskip < blankline and not self.have_label:
+            self.writer.send_paragraph(blankline - self.parskip)
+            self.parskip = blankline
+            self.have_label = 0
+        self.hard_break = self.nospace = self.para_end = 1
+        self.softspace = 0
+
+    def add_line_break(self):
+        if not (self.hard_break or self.para_end):
+            self.writer.send_line_break()
+            self.have_label = self.parskip = 0
+        self.hard_break = self.nospace = 1
+        self.softspace = 0
+
+    def add_hor_rule(self, *args, **kw):
+        if not self.hard_break:
+            self.writer.send_line_break()
+        self.writer.send_hor_rule(*args, **kw)
+        self.hard_break = self.nospace = 1
+        self.have_label = self.para_end = self.softspace = self.parskip = 0
+
+    def add_label_data(self, format, counter, blankline=None):
+        if self.have_label or not self.hard_break:
+            self.writer.send_line_break()
+        if not self.para_end:
+            self.writer.send_paragraph((blankline and 1) or 0)
+        if isinstance(format, str):
+            self.writer.send_label_data(self.format_counter(format, counter))
+        else:
+            self.writer.send_label_data(format)
+        self.nospace = self.have_label = self.hard_break = self.para_end = 1
+        self.softspace = self.parskip = 0
+
+    def format_counter(self, format, counter):
+        label = ''
+        for c in format:
+            if c == '1':
+                label = label + ('%d' % counter)
+            elif c in 'aA':
+                if counter > 0:
+                    label = label + self.format_letter(c, counter)
+            elif c in 'iI':
+                if counter > 0:
+                    label = label + self.format_roman(c, counter)
+            else:
+                label = label + c
+        return label
+
+    def format_letter(self, case, counter):
+        label = ''
+        while counter > 0:
+            counter, x = divmod(counter-1, 26)
+            # This makes a strong assumption that lowercase letters
+            # and uppercase letters form two contiguous blocks, with
+            # letters in order!
+            s = chr(ord(case) + x)
+            label = s + label
+        return label
+
+    def format_roman(self, case, counter):
+        ones = ['i', 'x', 'c', 'm']
+        fives = ['v', 'l', 'd']
+        label, index = '', 0
+        # This will die of IndexError when counter is too big
+        while counter > 0:
+            counter, x = divmod(counter, 10)
+            if x == 9:
+                label = ones[index] + ones[index+1] + label
+            elif x == 4:
+                label = ones[index] + fives[index] + label
+            else:
+                if x >= 5:
+                    s = fives[index]
+                    x = x-5
+                else:
+                    s = ''
+                s = s + ones[index]*x
+                label = s + label
+            index = index + 1
+        if case == 'I':
+            return label.upper()
+        return label
+
+    def add_flowing_data(self, data):
+        if not data:
+            return
+        prespace = data[:1].isspace()
+        postspace = data[-1:].isspace()
+        data = " ".join(data.split())
+        if self.nospace and not data:
+            return
+        elif prespace or self.softspace:
+            if not data:
+                if not self.nospace:
+                    self.softspace = 1
+                    self.parskip = 0
+                return
+            if not self.nospace:
+                data = ' ' + data
+        self.hard_break = self.nospace = self.para_end = \
+            self.parskip = self.have_label = 0
+        self.softspace = postspace
+        self.writer.send_flowing_data(data)
+
+    def add_literal_data(self, data):
+        if not data:
+            return
+        if self.softspace:
+            self.writer.send_flowing_data(" ")
+        self.hard_break = data[-1:] == '\n'
+        self.nospace = self.para_end = self.softspace = \
+            self.parskip = self.have_label = 0
+        self.writer.send_literal_data(data)
+
+    def flush_softspace(self):
+        if self.softspace:
+            self.hard_break = self.para_end = self.parskip = \
+                              self.have_label = self.softspace = 0
+            self.nospace = 1
+            self.writer.send_flowing_data(' ')
+
+    def push_alignment(self, align):
+        if align and align != self.align:
+            self.writer.new_alignment(align)
+            self.align = align
+            self.align_stack.append(align)
+        else:
+            self.align_stack.append(self.align)
+
+    def pop_alignment(self):
+        if self.align_stack:
+            del self.align_stack[-1]
+        if self.align_stack:
+            self.align = align = self.align_stack[-1]
+            self.writer.new_alignment(align)
+        else:
+            self.align = None
+            self.writer.new_alignment(None)
+
+    def push_font(self, font):
+        size, i, b, tt = font
+        if self.softspace:
+            self.hard_break = self.para_end = self.softspace = 0
+            self.nospace = 1
+            self.writer.send_flowing_data(' ')
+        if self.font_stack:
+            csize, ci, cb, ctt = self.font_stack[-1]
+            if size is AS_IS:
+                size = csize
+            if i is AS_IS:
+                i = ci
+            if b is AS_IS:
+                b = cb
+            if tt is AS_IS:
+                tt = ctt
+        font = (size, i, b, tt)
+        self.font_stack.append(font)
+        self.writer.new_font(font)
+
+    def pop_font(self):
+        if self.font_stack:
+            del self.font_stack[-1]
+        if self.font_stack:
+            font = self.font_stack[-1]
+        else:
+            font = None
+        self.writer.new_font(font)
+
+    def push_margin(self, margin):
+        self.margin_stack.append(margin)
+        fstack = [m for m in self.margin_stack if m]
+        if not margin and fstack:
+            margin = fstack[-1]
+        self.writer.new_margin(margin, len(fstack))
+
+    def pop_margin(self):
+        if self.margin_stack:
+            del self.margin_stack[-1]
+        fstack = [m for m in self.margin_stack if m]
+        if fstack:
+            margin = fstack[-1]
+        else:
+            margin = None
+        self.writer.new_margin(margin, len(fstack))
+
+    def set_spacing(self, spacing):
+        self.spacing = spacing
+        self.writer.new_spacing(spacing)
+
+    def push_style(self, *styles):
+        if self.softspace:
+            self.hard_break = self.para_end = self.softspace = 0
+            self.nospace = 1
+            self.writer.send_flowing_data(' ')
+        for style in styles:
+            self.style_stack.append(style)
+        self.writer.new_styles(tuple(self.style_stack))
+
+    def pop_style(self, n=1):
+        del self.style_stack[-n:]
+        self.writer.new_styles(tuple(self.style_stack))
+
+    def assert_line_data(self, flag=1):
+        self.nospace = self.hard_break = not flag
+        self.para_end = self.parskip = self.have_label = 0
+
+
+class NullWriter:
+    """Minimal writer interface to use in testing & inheritance.
+
+    A writer which only provides the interface definition; no actions are
+    taken on any methods.  This should be the base class for all writers
+    which do not need to inherit any implementation methods.
+
+    """
+    def __init__(self): pass
+    def flush(self): pass
+    def new_alignment(self, align): pass
+    def new_font(self, font): pass
+    def new_margin(self, margin, level): pass
+    def new_spacing(self, spacing): pass
+    def new_styles(self, styles): pass
+    def send_paragraph(self, blankline): pass
+    def send_line_break(self): pass
+    def send_hor_rule(self, *args, **kw): pass
+    def send_label_data(self, data): pass
+    def send_flowing_data(self, data): pass
+    def send_literal_data(self, data): pass
+
+
+class AbstractWriter(NullWriter):
+    """A writer which can be used in debugging formatters, but not much else.
+
+    Each method simply announces itself by printing its name and
+    arguments on standard output.
+
+    """
+
+    def new_alignment(self, align):
+        print("new_alignment(%r)" % (align,))
+
+    def new_font(self, font):
+        print("new_font(%r)" % (font,))
+
+    def new_margin(self, margin, level):
+        print("new_margin(%r, %d)" % (margin, level))
+
+    def new_spacing(self, spacing):
+        print("new_spacing(%r)" % (spacing,))
+
+    def new_styles(self, styles):
+        print("new_styles(%r)" % (styles,))
+
+    def send_paragraph(self, blankline):
+        print("send_paragraph(%r)" % (blankline,))
+
+    def send_line_break(self):
+        print("send_line_break()")
+
+    def send_hor_rule(self, *args, **kw):
+        print("send_hor_rule()")
+
+    def send_label_data(self, data):
+        print("send_label_data(%r)" % (data,))
+
+    def send_flowing_data(self, data):
+        print("send_flowing_data(%r)" % (data,))
+
+    def send_literal_data(self, data):
+        print("send_literal_data(%r)" % (data,))
+
+
+class DumbWriter(NullWriter):
+    """Simple writer class which writes output on the file object passed in
+    as the file parameter or, if file is omitted, on standard output.  The
+    output is simply word-wrapped to the number of columns specified by
+    the maxcol parameter.  This class is suitable for reflowing a sequence
+    of paragraphs.
+
+    """
+
+    def __init__(self, file=None, maxcol=72):
+        self.file = file or sys.stdout
+        self.maxcol = maxcol
+        NullWriter.__init__(self)
+        self.reset()
+
+    def reset(self):
+        self.col = 0
+        self.atbreak = 0
+
+    def send_paragraph(self, blankline):
+        self.file.write('\n'*blankline)
+        self.col = 0
+        self.atbreak = 0
+
+    def send_line_break(self):
+        self.file.write('\n')
+        self.col = 0
+        self.atbreak = 0
+
+    def send_hor_rule(self, *args, **kw):
+        self.file.write('\n')
+        self.file.write('-'*self.maxcol)
+        self.file.write('\n')
+        self.col = 0
+        self.atbreak = 0
+
+    def send_literal_data(self, data):
+        self.file.write(data)
+        i = data.rfind('\n')
+        if i >= 0:
+            self.col = 0
+            data = data[i+1:]
+        data = data.expandtabs()
+        self.col = self.col + len(data)
+        self.atbreak = 0
+
+    def send_flowing_data(self, data):
+        if not data:
+            return
+        atbreak = self.atbreak or data[0].isspace()
+        col = self.col
+        maxcol = self.maxcol
+        write = self.file.write
+        for word in data.split():
+            if atbreak:
+                if col + len(word) >= maxcol:
+                    write('\n')
+                    col = 0
+                else:
+                    write(' ')
+                    col = col + 1
+            write(word)
+            col = col + len(word)
+            atbreak = 1
+        self.col = col
+        self.atbreak = data[-1].isspace()
+
+
+def test(file=None):
+    w = DumbWriter()
+    f = AbstractFormatter(w)
+    if file is not None:
+        fp = open(file)
+    elif sys.argv[1:]:
+        fp = open(sys.argv[1])
+    else:
+        fp = sys.stdin
+    try:
+        for line in fp:
+            if line == '\n':
+                f.end_paragraph(1)
+            else:
+                f.add_flowing_data(line)
+    finally:
+        if fp is not sys.stdin:
+            fp.close()
+    f.end_paragraph(0)
+
+
+if __name__ == '__main__':
+    test()
diff --git a/pysollib/htmllib2.py b/pysollib/htmllib2.py
index 7ff6b2a9..dab753e7 100644
--- a/pysollib/htmllib2.py
+++ b/pysollib/htmllib2.py
@@ -4,7 +4,7 @@
 http://www.w3.org/hypertext/WWW/MarkUp/html-spec/html-spec_toc.html
 """
 
-from formatter import AS_IS
+from pysollib.formatter import AS_IS
 
 from six.moves import html_parser
 
@@ -483,7 +483,7 @@ def unknown_endtag(self, tag):
 
 def test(args=None):
     import sys
-    import formatter
+    import pysollib.formatter
 
     if not args:
         args = sys.argv[1:]
@@ -508,9 +508,11 @@ def test(args=None):
             sys.exit(1)
 
     if silent:
-        f = formatter.NullFormatter()
+        f = pysollib.formatter.NullFormatter()
     else:
-        f = formatter.AbstractFormatter(formatter.DumbWriter())
+        f = pysollib.formatter.AbstractFormatter(
+            pysollib.formatter.DumbWriter()
+        )
 
     p = HTMLParser(f)
     p.feed(data)
diff --git a/pysollib/kivy/tkhtml.py b/pysollib/kivy/tkhtml.py
index 152b281c..54c0db0e 100644
--- a/pysollib/kivy/tkhtml.py
+++ b/pysollib/kivy/tkhtml.py
@@ -21,7 +21,6 @@
 #
 # ---------------------------------------------------------------------------#
 
-import formatter
 import os
 import sys
 
@@ -29,6 +28,7 @@
 from kivy.uix.button import Button
 from kivy.uix.label import Label
 
+import pysollib.formatter
 import pysollib.htmllib2 as htmllib
 from pysollib.kivy.LApp import LPopCommander
 from pysollib.kivy.LApp import LScrollView
@@ -84,9 +84,9 @@ def cmp2(a, b):
     return (a > b) - (a < b)
 
 
-class tkHTMLWriter(formatter.NullWriter):
+class tkHTMLWriter(pysollib.formatter.NullWriter):
     def __init__(self, text, viewer, app):
-        formatter.NullWriter.__init__(self)
+        pysollib.formatter.NullWriter.__init__(self)
 
         self.text = text
         self.viewer = viewer
@@ -630,7 +630,7 @@ def display(self, url, add=1, relpath=1, xview=0, yview=0):
         # self.images = {}
         self.text.textbuffer = ''
         writer = tkHTMLWriter(self.text, self, self.app)
-        fmt = formatter.AbstractFormatter(writer)
+        fmt = pysollib.formatter.AbstractFormatter(writer)
         parser = tkHTMLParser(fmt)
         parser.feed(data)
         parser.close()
diff --git a/pysollib/pysolgtk/tkhtml.py b/pysollib/pysolgtk/tkhtml.py
index 798efda2..f1c18659 100644
--- a/pysollib/pysolgtk/tkhtml.py
+++ b/pysollib/pysolgtk/tkhtml.py
@@ -21,7 +21,6 @@
 #
 # ---------------------------------------------------------------------------
 
-import formatter
 import htmllib
 import os
 import sys
@@ -34,6 +33,7 @@
 
 import pango
 
+import pysollib.formatter
 from pysollib.mfxutil import Struct, openURL
 from pysollib.mygettext import _
 from pysollib.settings import TITLE
@@ -55,9 +55,9 @@
 # *
 # ************************************************************************
 
-class tkHTMLWriter(formatter.NullWriter):
+class tkHTMLWriter(pysollib.formatter.NullWriter):
     def __init__(self, text, viewer, app):
-        formatter.NullWriter.__init__(self)
+        pysollib.formatter.NullWriter.__init__(self)
 
         self.text = text      # gtk.TextBuffer
         self.viewer = viewer  # HTMLViewer
@@ -489,7 +489,7 @@ def display(self, url, add=1, relpath=1, position=(0, 0)):
         self.textbuffer.delete(start, end)
 
         writer = tkHTMLWriter(self.textbuffer, self, self.app)
-        fmt = formatter.AbstractFormatter(writer)
+        fmt = pysollib.formatter.AbstractFormatter(writer)
         parser = tkHTMLParser(fmt)
         parser.feed(data)
         parser.close()
diff --git a/pysollib/ui/tktile/tkhtml.py b/pysollib/ui/tktile/tkhtml.py
index acab5711..afcb7257 100644
--- a/pysollib/ui/tktile/tkhtml.py
+++ b/pysollib/ui/tktile/tkhtml.py
@@ -21,10 +21,10 @@
 #
 # ---------------------------------------------------------------------------
 
-import formatter
 import os
 import sys
 
+import pysollib.formatter
 import pysollib.htmllib2 as htmllib
 from pysollib.mfxutil import openURL
 from pysollib.mygettext import _
@@ -40,9 +40,9 @@
 # ************************************************************************
 
 
-class tkHTMLWriter(formatter.NullWriter):
+class tkHTMLWriter(pysollib.formatter.NullWriter):
     def __init__(self, text, viewer, app):
-        formatter.NullWriter.__init__(self)
+        pysollib.formatter.NullWriter.__init__(self)
 
         self.text = text
         self.viewer = viewer
@@ -379,7 +379,7 @@ def display(self, url, add=1, relpath=1, xview=0, yview=0):
         self.text.delete("1.0", "end")
         # self.images = {}
         writer = tkHTMLWriter(self.text, self, self.app)
-        fmt = formatter.AbstractFormatter(writer)
+        fmt = pysollib.formatter.AbstractFormatter(writer)
         parser = tkHTMLParser(fmt)
         parser.feed(data)
         parser.close()
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin