Repository: chezou/tabula-py
Pull request #35 (2017-05-28 07:55:25)

Add Convert batch mode
This PR introduces `convert_into_by_batch` method. This method converts all the pdfs in a directory. Output files are saved in the same directory.

Usage:

```py
convert_into_by_batch('dir_path_for_pdfs')
```


Patch:
diff --git a/README.md b/README.md
index 7ebfeef..3689cd4 100644
--- a/README.md
+++ b/README.md
@@ -41,6 +41,9 @@ df2 = tabula.read_pdf("https://github.com/tabulapdf/tabula-java/raw/master/src/t
 
 # convert PDF into CSV
 tabula.convert_into("test.pdf", "output.csv", output_format="csv")
+
+# convert all PDFs in a directory
+tabula.convert_into_by_batch("input_directory", output_format='csv')
 ```
 
 See [example notebook](./examples/tabula_example.ipynb)
diff --git a/tabula/__init__.py b/tabula/__init__.py
index c7bed19..22fcdda 100644
--- a/tabula/__init__.py
+++ b/tabula/__init__.py
@@ -1,3 +1,4 @@
 from .wrapper import read_pdf_table
 from .wrapper import read_pdf
 from .wrapper import convert_into
+from .wrapper import convert_into_by_batch
diff --git a/tabula/wrapper.py b/tabula/wrapper.py
index f96532c..345edbe 100644
--- a/tabula/wrapper.py
+++ b/tabula/wrapper.py
@@ -104,26 +104,14 @@ def convert_into(input_path, output_path, **kwargs):
             Dictionary of option for tabula-java. Details are shown in `build_options()`
 
     Returns:
-        Extracted pandas DataFrame or list.
+        Nothing. Output file will be saved into `output_path`
     '''
 
     if output_path is None or len(output_path) is 0:
         raise AttributeError("'output_path' shoud not be None or empty")
 
     kwargs['output_path'] = output_path
-
-    output_format = kwargs.get('output_format', 'csv')
-    if output_format == 'csv':
-        kwargs['format'] = 'CSV'
-
-    elif output_format == 'json':
-        kwargs['format'] = 'JSON'
-
-    elif output_format == 'tsv':
-        kwargs['format'] = 'TSV'
-
-    elif output_format == 'dataframe':
-        raise AttributeError("'output_format' has no attribute 'dataframe'")
+    kwargs['format'] = extract_format_for_conversion(kwargs.get('output_format'))
 
     java_options = kwargs.get('java_options', [])
     if isinstance(java_options, str):
@@ -139,6 +127,56 @@ def convert_into(input_path, output_path, **kwargs):
         if is_url:
             os.unlink(path)
 
+def convert_into_by_batch(input_dir, **kwargs):
+    '''Convert tables from PDFs in a directory.
+
+    Args:
+        input_dir (str):
+            Directory path.
+        output_format (str, optional):
+            Output format of this function (csv, json or tsv)
+        java_options (list, optional):
+            Set java options like `-Xmx256m`.
+        kwargs (dict):
+            Dictionary of option for tabula-java. Details are shown in `build_options()`
+
+    Returns:
+        Nothing. Outputs are saved into the same directory with `input_dir`
+    '''
+
+    if input_dir is None or not os.path.isdir(input_dir):
+        raise AttributeError("'input_dir' shoud be directory path")
+
+    kwargs['format'] = extract_format_for_conversion(kwargs.get('output_format'))
+
+    java_options = kwargs.get('java_options', [])
+    if isinstance(java_options, str):
+        java_options = [java_options]
+
+    # Option for batch
+    kwargs['batch'] = input_dir
+
+    options = build_options(kwargs)
+
+    args = ["java"] + java_options + ["-jar", JAR_PATH] + options
+
+    subprocess.check_output(args)
+
+
+def extract_format_for_conversion(output_format='csv'):
+    if output_format == 'csv':
+        return 'CSV'
+
+    if output_format == 'json':
+        return 'JSON'
+
+    if output_format == 'tsv':
+        return 'TSV'
+
+    if output_format == 'dataframe':
+        raise AttributeError("'output_format' has no attribute 'dataframe'")
+
+
 def extract_from(raw_json):
     '''Extract tables from json.
 
@@ -206,7 +244,7 @@ def build_options(kwargs={}):
             Force PDF not to be extracted using spreadsheet-style extraction
             (if there are ruling lines separating each cell, as in a PDF of an
              Excel spreadsheet)
-        password (bool, optional):
+        password (str, optional):
             Password to decrypt document. Default is empty
         silent (bool, optional):
             Suppress all stderr output.
@@ -215,6 +253,8 @@ def build_options(kwargs={}):
             Example: [10.1, 20.2, 30.3]
         format (str, optional):
             Format for output file or extracted object. (CSV, TSV, JSON)
+        batch (str, optional):
+            Convert all .pdfs in the provided directory. This argument should be direcotry.
         output_path (str, optional):
             Output file path. File format of it is depends on `format`.
             Same as `--outfile` option of tabula-java.
@@ -275,6 +315,10 @@ def build_options(kwargs={}):
     if password:
         __options += ["--password", password]
 
+    batch = kwargs.get('batch')
+    if batch:
+        __options += ["--batch", batch]
+
     silent = kwargs.get('silent')
     if silent:
         __options.append("--silent")


Test patch:
diff --git a/tests/test_read_pdf_table.py b/tests/test_read_pdf_table.py
index 7afcc02..1076971 100644
--- a/tests/test_read_pdf_table.py
+++ b/tests/test_read_pdf_table.py
@@ -5,10 +5,10 @@ import filecmp
 import json
 import os
 import pandas as pd
+import shutil
 
 
 class TestReadPdfTable(unittest.TestCase):
-
     def test_read_pdf(self):
         pdf_path = 'tests/resources/data.pdf'
         expected_csv1 = 'tests/resources/data_1.csv'
@@ -65,6 +65,20 @@ class TestReadPdfTable(unittest.TestCase):
         tabula.convert_into(pdf_path, temp.name, output_format='json')
         self.assertTrue(filecmp.cmp(temp.name, expected_json))
 
+    def test_convert_into_by_batch(self):
+        pdf_path = 'tests/resources/data.pdf'
+        expected_csv = 'tests/resources/data_1.csv'
+        temp_dir = tempfile.mkdtemp()
+        temp_pdf = temp_dir + '/data.pdf'
+        converted_csv = temp_dir + '/data.csv'
+        shutil.copyfile(pdf_path, temp_pdf)
+
+        try:
+            tabula.convert_into_by_batch(temp_dir, output_format='csv')
+            self.assertTrue(filecmp.cmp(converted_csv, expected_csv))
+        finally:
+            shutil.rmtree(temp_dir)
+
     def test_convert_remote_file(self):
         uri = "https://github.com/tabulapdf/tabula-java/raw/master/src/test/resources/technology/tabula/12s0324.pdf"
         temp = tempfile.NamedTemporaryFile()