Repository: pdfminer/pdfminer.six (python)

Issue:
Create function that returns the extracted text
Currently, you need to use an file-like output argument to get the text from a pdf. For example: 

```python
from io import StringIO
output_string = StringIO()
with open('samples/simple1.pdf', 'rb') as fin:
     extract_text_to_fp(fin, output_string)
```

Having to use an output-argument is annoying since most people just want to do:

```python
text = pdf_to_text('samples/simple1.pdf')
```

Pull request description:
Add simple wrapper to extract text from pdf
**Description**

Added a simple wrapper that allows one to easily extract text from a PDF file.

Fixes #327 

**How Has This Been Tested?**

Erh, gotta work on some actual tests for that. Other than that, I've been using this function everywhere in my projects.

**Checklist**

- [x] I have added tests that prove my fix is effective or that my feature works
- [x] I have updated the [README.md](../README.md) and other documentation, or I am sure that this is not necessary
- [x] I have added a concise human-readable description of the change to [CHANGELOG.md](../CHANGELOG.md)
- [x] I have added docstrings to newly created methods and classes
- [x] I have optimized the code at least one time after creating the initial version


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d6e1e1..db72a80 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,10 +11,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 [#307](https://github.com/pdfminer/pdfminer.six/pull/307))
 
 ### Added
+- Simple wrapper to easily extract text from a PDF file [#330](https://github.com/pdfminer/pdfminer.six/pull/330)
 - Support for extracting JBIG2 encoded images ([#311](https://github.com/pdfminer/pdfminer.six/pull/311) and [#46](https://github.com/pdfminer/pdfminer.six/pull/46))
 
 ### Fixed
-- Unhandled AssertionError when dumping pdf containing reference to object id 0 ([#318](https://github.com/pdfminer/pdfminer.six/pull/318))
+- Unhandled AssertionError when dumping pdf containing reference to object id 0 
+ ([#318](https://github.com/pdfminer/pdfminer.six/pull/318))
+- Debug flag actually changes logging level to debug for pdf2txt.py and
+ dumppdf.py ([#325](https://github.com/pdfminer/pdfminer.six/pull/325))
 
 ### Changed
 - Using argparse instead of getopt for command line interface of dumppdf.py ([#321](https://github.com/pdfminer/pdfminer.six/pull/321))
diff --git a/pdfminer/high_level.py b/pdfminer/high_level.py
index ecc934f..2ce4276 100644
--- a/pdfminer/high_level.py
+++ b/pdfminer/high_level.py
@@ -4,9 +4,16 @@ Functions that encapsulate "usual" use-cases for pdfminer, for use making
 bundled scripts and for using pdfminer as a module for routine tasks.
 """
 
+import logging
 import six
 import sys
 
+# Conditional import because python 2 is stupid
+if sys.version_info > (3, 0):
+    from io import StringIO
+else:
+    from io import BytesIO as StringIO
+
 from .pdfdocument import PDFDocument
 from .pdfparser import PDFParser
 from .pdfinterp import PDFResourceManager, PDFPageInterpreter
@@ -15,6 +22,7 @@ from .pdfpage import PDFPage
 from .converter import XMLConverter, HTMLConverter, TextConverter
 from .cmapdb import CMapDB
 from .image import ImageWriter
+from .layout import LAParams
 
 
 def extract_text_to_fp(inf, outfp,
@@ -50,6 +58,9 @@ def extract_text_to_fp(inf, outfp,
             'upgrade to Python 3. For more information see '
             'https://github.com/pdfminer/pdfminer .six/issues/194')
 
+    if debug:
+        logging.getLogger().setLevel(logging.DEBUG)
+
     if six.PY2 and sys.stdin.encoding:
         password = password.decode(sys.stdin.encoding)
 
@@ -88,3 +99,41 @@ def extract_text_to_fp(inf, outfp,
         interpreter.process_page(page)    
 
     device.close()
+
+
+def extract_text(pdf_file, password='', page_numbers=None, maxpages=0,
+                 caching=True, codec='utf-8', laparams=None):
+    """
+    Parses and returns the text contained in a PDF file.
+    Takes loads of optional arguments but the defaults are somewhat sane.
+    Returns a string containing all of the text extracted.
+
+    :param pdf_file: Path to the PDF file to be worked on
+    :param password: For encrypted PDFs, the password to decrypt.
+    :param page_numbers: List of zero-indexed page numbers to extract.
+    :param maxpages: The maximum number of pages to parse
+    :param caching: If resources should be cached
+    :param codec: Text decoding codec
+    :param laparams: LAParams object from pdfminer.layout.
+    """
+    if laparams is None:
+        laparams = LAParams()
+
+    with open(pdf_file, "rb") as fp, StringIO() as output_string:
+        rsrcmgr = PDFResourceManager()
+        device = TextConverter(rsrcmgr, output_string, codec=codec,
+                               laparams=laparams)
+        interpreter = PDFPageInterpreter(rsrcmgr, device)
+
+        for page in PDFPage.get_pages(
+            fp,
+            page_numbers,
+            maxpages=maxpages,
+            password=password,
+            caching=caching,
+            check_extractable=True,
+        ):
+            interpreter.process_page(page)
+
+        return output_string.getvalue()
+    
diff --git a/tools/dumppdf.py b/tools/dumppdf.py
index 01654d4..0e3a4ee 100755
--- a/tools/dumppdf.py
+++ b/tools/dumppdf.py
@@ -15,6 +15,8 @@ from pdfminer.pdftypes import PDFStream, PDFObjRef, resolve1, stream_value
 from pdfminer.psparser import PSKeyword, PSLiteral, LIT
 from pdfminer.utils import isnumber
 
+logging.basicConfig()
+
 ESC_PAT = re.compile(r'[\000-\037&<>()"\042\047\134\177-\377]')
 
 
diff --git a/tools/pdf2txt.py b/tools/pdf2txt.py
index f243601..41a7e7e 100755
--- a/tools/pdf2txt.py
+++ b/tools/pdf2txt.py
@@ -7,12 +7,15 @@ import argparse
 import logging
 import six
 import sys
+
 import pdfminer.settings
 pdfminer.settings.STRICT = False
 import pdfminer.high_level
 import pdfminer.layout
 from pdfminer.image import ImageWriter
 
+logging.basicConfig()
+
 
 def extract_text(files=[], outfile='-',
             no_laparams=False, all_texts=None, detect_vertical=None, # LAParams
diff --git a/tools/pdfdiff.py b/tools/pdfdiff.py
index bb7b47a..e738b75 100644
--- a/tools/pdfdiff.py
+++ b/tools/pdfdiff.py
@@ -11,6 +11,8 @@ pdfminer.settings.STRICT = False
 import pdfminer.high_level
 import pdfminer.layout
 
+logging.basicConfig()
+
 
 def compare(file1, file2, **kwargs):
     if '_py2_no_more_posargs' in kwargs is not None:
@@ -89,10 +91,12 @@ def main(args=None):
     P.add_argument("-O", "--output-dir", default=None, help="Output directory for images")
     P.add_argument("-C", "--disable-caching", default=False, action="store_true", help="Disable caching")
     P.add_argument("-S", "--strip-control", default=False, action="store_true", help="Strip control in XML mode")
-    
 
     A = P.parse_args(args=args)
 
+    if A.debug:
+        logging.getLogger().setLevel(logging.DEBUG)
+
     if A.page_numbers:
         A.page_numbers = set([x-1 for x in A.page_numbers])
     if A.pagenos:


Test patch:
diff --git a/tests/test_highlevel_extracttext.py b/tests/test_highlevel_extracttext.py
new file mode 100644
index 0000000..7062cd8
--- /dev/null
+++ b/tests/test_highlevel_extracttext.py
@@ -0,0 +1,38 @@
+import unittest
+
+from helpers import absolute_sample_path
+from pdfminer.high_level import extract_text
+
+
+def run(sample_path):
+    absolute_path = absolute_sample_path(sample_path)
+    s = extract_text(absolute_path)
+    return s
+
+
+test_strings = {
+    "simple1.pdf": "Hello \n\nWorld\n\nWorld\n\nHello \n\nH e l l o  \n\nH e l l o  \n\nW o r l d\n\nW o r l d\n\n\f",
+    "simple2.pdf": "\f",
+    "simple3.pdf": "HelloHello\n\nWorld\n\nWorld\n\n\f",
+}
+
+
+class TestExtractText(unittest.TestCase):
+    def test_simple1(self):
+        test_file = "simple1.pdf"
+        s = run(test_file)
+        self.assertEqual(s, test_strings[test_file])
+
+    def test_simple2(self):
+        test_file = "simple2.pdf"
+        s = run(test_file)
+        self.assertEqual(s, test_strings[test_file])
+
+    def test_simple3(self):
+        test_file = "simple3.pdf"
+        s = run(test_file)
+        self.assertEqual(s, test_strings[test_file])
+
+
+if __name__ == "__main__":
+    unittest.main()