Merge branch 'master' into format-markdown
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
VERSION = (0, 8, 2)
|
||||
VERSION = (0, 9, 0)
|
||||
PRERELEASE = None # alpha, beta or rc
|
||||
REVISION = None
|
||||
|
||||
|
||||
+9
-13
@@ -55,7 +55,9 @@ class TextEdge(object):
|
||||
x = round(self.x, 2)
|
||||
y0 = round(self.y0, 2)
|
||||
y1 = round(self.y1, 2)
|
||||
return f"<TextEdge x={x} y0={y0} y1={y1} align={self.align} valid={self.is_valid}>"
|
||||
return (
|
||||
f"<TextEdge x={x} y0={y0} y1={y1} align={self.align} valid={self.is_valid}>"
|
||||
)
|
||||
|
||||
def update_coords(self, x, y0, edge_tol=50):
|
||||
"""Updates the text edge's x and bottom y coordinates and sets
|
||||
@@ -102,8 +104,7 @@ class TextEdges(object):
|
||||
return None
|
||||
|
||||
def add(self, textline, align):
|
||||
"""Adds a new text edge to the current dict.
|
||||
"""
|
||||
"""Adds a new text edge to the current dict."""
|
||||
x = self.get_x_coord(textline, align)
|
||||
y0 = textline.y0
|
||||
y1 = textline.y1
|
||||
@@ -111,8 +112,7 @@ class TextEdges(object):
|
||||
self._textedges[align].append(te)
|
||||
|
||||
def update(self, textline):
|
||||
"""Updates an existing text edge in the current dict.
|
||||
"""
|
||||
"""Updates an existing text edge in the current dict."""
|
||||
for align in ["left", "right", "middle"]:
|
||||
x_coord = self.get_x_coord(textline, align)
|
||||
idx = self.find(x_coord, align)
|
||||
@@ -304,8 +304,7 @@ class Cell(object):
|
||||
|
||||
@property
|
||||
def bound(self):
|
||||
"""The number of sides on which the cell is bounded.
|
||||
"""
|
||||
"""The number of sides on which the cell is bounded."""
|
||||
return self.top + self.bottom + self.left + self.right
|
||||
|
||||
|
||||
@@ -361,8 +360,7 @@ class Table(object):
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
"""Returns two-dimensional list of strings in table.
|
||||
"""
|
||||
"""Returns two-dimensional list of strings in table."""
|
||||
d = []
|
||||
for row in self.cells:
|
||||
d.append([cell.text.strip() for cell in row])
|
||||
@@ -383,8 +381,7 @@ class Table(object):
|
||||
return report
|
||||
|
||||
def set_all_edges(self):
|
||||
"""Sets all table edges to True.
|
||||
"""
|
||||
"""Sets all table edges to True."""
|
||||
for row in self.cells:
|
||||
for cell in row:
|
||||
cell.left = cell.right = cell.top = cell.bottom = True
|
||||
@@ -526,8 +523,7 @@ class Table(object):
|
||||
return self
|
||||
|
||||
def set_border(self):
|
||||
"""Sets table border edges to True.
|
||||
"""
|
||||
"""Sets table border edges to True."""
|
||||
for r in range(len(self.rows)):
|
||||
self.cells[r][0].left = True
|
||||
self.cells[r][len(self.cols) - 1].right = True
|
||||
|
||||
@@ -81,8 +81,7 @@ class __Ghostscript(object):
|
||||
|
||||
|
||||
def Ghostscript(*args, **kwargs):
|
||||
"""Factory function for setting up a Ghostscript instance
|
||||
"""
|
||||
"""Factory function for setting up a Ghostscript instance"""
|
||||
global __instance__
|
||||
# Ghostscript only supports a single instance
|
||||
if __instance__ is None:
|
||||
|
||||
+1
-3
@@ -167,9 +167,7 @@ class PDFHandler(object):
|
||||
with TemporaryDirectory() as tempdir:
|
||||
for p in self.pages:
|
||||
self._save_page(self.filepath, p, tempdir)
|
||||
pages = [
|
||||
os.path.join(tempdir, f"page-{p}.pdf") for p in self.pages
|
||||
]
|
||||
pages = [os.path.join(tempdir, f"page-{p}.pdf") for p in self.pages]
|
||||
parser = Lattice(**kwargs) if flavor == "lattice" else Stream(**kwargs)
|
||||
for p in pages:
|
||||
t = parser.extract_tables(
|
||||
|
||||
@@ -6,8 +6,7 @@ from ..utils import get_page_layout, get_text_objects
|
||||
|
||||
|
||||
class BaseParser(object):
|
||||
"""Defines a base parser.
|
||||
"""
|
||||
"""Defines a base parser."""
|
||||
|
||||
def _generate_layout(self, filename, layout_kwargs):
|
||||
self.filename = filename
|
||||
|
||||
@@ -211,8 +211,8 @@ class Lattice(BaseParser):
|
||||
from ..ext.ghostscript import Ghostscript
|
||||
|
||||
self.imagename = "".join([self.rootname, ".png"])
|
||||
gs_call = "-q -sDEVICE=png16m -o {} -r300 {}".format(
|
||||
self.imagename, self.filename
|
||||
gs_call = "-q -sDEVICE=png16m -o {} -r{} {}".format(
|
||||
self.imagename, self.resolution, self.filename
|
||||
)
|
||||
gs_call = gs_call.encode().split()
|
||||
null = open(os.devnull, "wb")
|
||||
|
||||
@@ -65,7 +65,7 @@ class Stream(BaseParser):
|
||||
edge_tol=50,
|
||||
row_tol=2,
|
||||
column_tol=0,
|
||||
**kwargs
|
||||
**kwargs,
|
||||
):
|
||||
self.table_regions = table_regions
|
||||
self.table_areas = table_areas
|
||||
@@ -362,10 +362,10 @@ class Stream(BaseParser):
|
||||
if len(elements):
|
||||
ncols = max(set(elements), key=elements.count)
|
||||
else:
|
||||
warnings.warn(
|
||||
f"No tables found in table area {table_idx + 1}"
|
||||
)
|
||||
cols = [(t.x0, t.x1) for r in rows_grouped if len(r) == ncols for t in r]
|
||||
warnings.warn(f"No tables found in table area {table_idx + 1}")
|
||||
cols = [
|
||||
(t.x0, t.x1) for r in rows_grouped if len(r) == ncols for t in r
|
||||
]
|
||||
cols = self._merge_columns(sorted(cols), column_tol=self.column_tol)
|
||||
inner_text = []
|
||||
for i in range(1, len(cols)):
|
||||
|
||||
+3
-7
@@ -34,13 +34,9 @@ class PlotMethods(object):
|
||||
raise ImportError("matplotlib is required for plotting.")
|
||||
|
||||
if table.flavor == "lattice" and kind in ["textedge"]:
|
||||
raise NotImplementedError(
|
||||
f"Lattice flavor does not support kind='{kind}'"
|
||||
)
|
||||
raise NotImplementedError(f"Lattice flavor does not support kind='{kind}'")
|
||||
elif table.flavor == "stream" and kind in ["joint", "line"]:
|
||||
raise NotImplementedError(
|
||||
f"Stream flavor does not support kind='{kind}'"
|
||||
)
|
||||
raise NotImplementedError(f"Stream flavor does not support kind='{kind}'")
|
||||
|
||||
plot_method = getattr(self, kind)
|
||||
fig = plot_method(table)
|
||||
@@ -48,7 +44,7 @@ class PlotMethods(object):
|
||||
if filename is not None:
|
||||
fig.savefig(filename)
|
||||
return None
|
||||
|
||||
|
||||
return fig
|
||||
|
||||
def text(self, table):
|
||||
|
||||
+11
-3
@@ -838,23 +838,27 @@ def compute_whitespace(d):
|
||||
|
||||
def get_page_layout(
|
||||
filename,
|
||||
line_overlap=0.5,
|
||||
char_margin=1.0,
|
||||
line_margin=0.5,
|
||||
word_margin=0.1,
|
||||
boxes_flow=0.5,
|
||||
detect_vertical=True,
|
||||
all_texts=True,
|
||||
):
|
||||
"""Returns a PDFMiner LTPage object and page dimension of a single
|
||||
page pdf. See https://euske.github.io/pdfminer/ to get definitions
|
||||
of kwargs.
|
||||
page pdf. To get the definitions of kwargs, see
|
||||
https://pdfminersix.rtfd.io/en/latest/reference/composable.html.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : string
|
||||
Path to pdf file.
|
||||
line_overlap : float
|
||||
char_margin : float
|
||||
line_margin : float
|
||||
word_margin : float
|
||||
boxes_flow : float
|
||||
detect_vertical : bool
|
||||
all_texts : bool
|
||||
|
||||
@@ -870,11 +874,15 @@ def get_page_layout(
|
||||
parser = PDFParser(f)
|
||||
document = PDFDocument(parser)
|
||||
if not document.is_extractable:
|
||||
raise PDFTextExtractionNotAllowed(f"Text extraction is not allowed: {filename}")
|
||||
raise PDFTextExtractionNotAllowed(
|
||||
f"Text extraction is not allowed: {filename}"
|
||||
)
|
||||
laparams = LAParams(
|
||||
line_overlap=line_overlap,
|
||||
char_margin=char_margin,
|
||||
line_margin=line_margin,
|
||||
word_margin=word_margin,
|
||||
boxes_flow=boxes_flow,
|
||||
detect_vertical=detect_vertical,
|
||||
all_texts=all_texts,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user