Repository: chezou/tabula-py
Pull request #180 (2019-10-04 01:29:07)

Read remote template for `read_pdf_with_template()`
`read_pdf_with_template()` works with remote URL.

```py
        template_path = (
            "https://github.com/chezou/tabula-py/raw/master/"
            "tests/resources/data.tabula-template.json"
        )

        dfs = tabula.read_pdf_with_template(pdf_path, template_path)
```


Patch:
diff --git a/tabula/file_util.py b/tabula/file_util.py
index faa5029..c7db3f7 100644
--- a/tabula/file_util.py
+++ b/tabula/file_util.py
@@ -8,7 +8,7 @@ _VALID_URLS = set(uses_relative + uses_netloc + uses_params)
 _VALID_URLS.discard("")
 
 
-def localize_file(path_or_buffer, user_agent=None):
+def localize_file(path_or_buffer, user_agent=None, suffix=".pdf"):
     """Ensure localize target file.
 
     If the target file is remote, this function fetches into local storage.
@@ -16,6 +16,11 @@ def localize_file(path_or_buffer, user_agent=None):
     Args:
         path (str):
             File path or file like object or URL of target file.
+        user_agent (str, optional):
+            Set a custom user-agent when download a pdf from a url. Otherwise
+            it uses the default ``urllib.request`` user-agent.
+        suffix (str, optional):
+            File extension to check.
 
     Returns:
         (str, bool):
@@ -33,9 +38,9 @@ def localize_file(path_or_buffer, user_agent=None):
 
         parsed_url = parse_url(req.geturl())
         filename = os.path.basename(parsed_url.path)
-        if os.path.splitext(filename)[-1] != ".pdf":
+        if os.path.splitext(filename)[-1] != suffix:
             pid = os.getpid()
-            filename = "{0}.pdf".format(pid)
+            filename = "{}{}".format(pid, suffix)
 
         with open(filename, "wb") as f:
             shutil.copyfileobj(req, f)
@@ -44,7 +49,7 @@ def localize_file(path_or_buffer, user_agent=None):
 
     elif is_file_like(path_or_buffer):
         pid = os.getpid()
-        filename = "{0}.pdf".format(pid)
+        filename = "{}{}".format(pid, suffix)
 
         with open(filename, "wb") as f:
             shutil.copyfileobj(path_or_buffer, f)
diff --git a/tabula/wrapper.py b/tabula/wrapper.py
index cf3e347..e789b4b 100644
--- a/tabula/wrapper.py
+++ b/tabula/wrapper.py
@@ -92,13 +92,15 @@ def read_pdf(
     java_options=None,
     pandas_options=None,
     multiple_tables=False,
+    user_agent=None,
     **kwargs
 ):
     """Read tables in PDF.
 
     Args:
-        input_path (file_like_obj):
+        input_path (file_like_obj or str):
             File like object of tareget PDF file.
+            It can be URL, which is downloaded by tabula-py automatically.
         output_format (str, optional):
             Output format for returned object (``"dataframe" or ``"json"``)
         encoding (str, optional):
@@ -267,8 +269,6 @@ def read_pdf(
         if not any("file.encoding" in opt for opt in java_options):
             java_options += ["-Dfile.encoding=UTF8"]
 
-    user_agent = kwargs.pop("user_agent", None)
-
     path, temporary = localize_file(input_path, user_agent)
 
     if not os.path.exists(path):
@@ -323,21 +323,27 @@ def read_pdf_with_template(
     pandas_options=None,
     encoding="utf-8",
     java_options=None,
+    user_agent=None,
     **kwargs
 ):
     """Read tables in PDF with a Tabula App template.
 
     Args:
-        input_path (file_like_obj):
+        input_path (file_like_obj or str):
             File like object of tareget PDF file.
-        template_path (file_like_obj):
+            It can be URL, which is downloaded by tabula-py automatically.
+        template_path (file_like_obj or str):
             File like object for Tabula app template.
+            It can be URL, which is downloaded by tabula-py automatically.
         pandas_options (dict, optional):
             Set pandas options like {'header': None}.
         encoding (str, optional):
             Encoding type for pandas. Default is 'utf-8'
         java_options (list, optional):
             Set java options like `-Xmx256m`.
+        user_agent (str, optional):
+            Set a custom user-agent when download a pdf from a url. Otherwise
+            it uses the default ``urllib.request`` user-agent.
         kwargs (dict):
             Dictionary of option for tabula-java. Details are shown in
             :func:`build_options()`
@@ -348,6 +354,8 @@ def read_pdf_with_template(
 
     Examples:
 
+        You can use template file extracted by tabula app.
+
         >>> import tabula
         >>> tabula.read_pdf_with_template(pdf_path, "/path/to/data.tabula-template.json")
         [             Unnamed: 0   mpg  cyl   disp   hp  ...   qsec  vs  am  gear  carb
@@ -415,21 +423,29 @@ def read_pdf_with_template(
         13        17.3   VC   1.0]
     """  # noqa
 
-    options = load_template(template_path)
+    path, temporary = localize_file(
+        template_path, user_agent=user_agent, suffix=".json"
+    )
+    options = load_template(path)
     dataframes = []
 
-    for option in options:
-        _df = read_pdf(
-            input_path,
-            pandas_options=pandas_options,
-            encoding=encoding,
-            java_options=java_options,
-            **dict(kwargs, **option)
-        )
-        if isinstance(_df, list):
-            dataframes.extend(_df)
-        else:
-            dataframes.append(_df)
+    try:
+        for option in options:
+            _df = read_pdf(
+                input_path,
+                pandas_options=pandas_options,
+                encoding=encoding,
+                java_options=java_options,
+                **dict(kwargs, **option)
+            )
+
+            if isinstance(_df, list):
+                dataframes.extend(_df)
+            else:
+                dataframes.append(_df)
+    finally:
+        if temporary:
+            os.unlink(path)
 
     return dataframes
 


Test patch:
diff --git a/tests/test_read_pdf_table.py b/tests/test_read_pdf_table.py
index 51e473b..32e4063 100644
--- a/tests/test_read_pdf_table.py
+++ b/tests/test_read_pdf_table.py
@@ -219,6 +219,16 @@ class TestReadPdfTable(unittest.TestCase):
         self.assertEqual(len(dfs), 4)
         self.assertTrue(dfs[0].equals(pd.read_csv(self.expected_csv1)))
 
+    def test_read_pdf_with_remote_template(self):
+        template_path = (
+            "https://github.com/chezou/tabula-py/raw/master/"
+            "tests/resources/data.tabula-template.json"
+        )
+
+        dfs = tabula.read_pdf_with_template(self.pdf_path, template_path)
+        self.assertEqual(len(dfs), 4)
+        self.assertTrue(dfs[0].equals(pd.read_csv(self.expected_csv1)))
+
     @patch("subprocess.check_output")
     @patch("tabula.wrapper._jar_path")
     def test_read_pdf_with_jar_path(self, jar_func, mock_fun):