diff --git a/README.md b/README.md index f0d3e60..6cdf4b1 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,8 @@ with pdfplumber.open("path/to/file.pdf") as pdf: Both methods return an instance of the `pdfplumber.PDF` class. +To load a password-protected PDF, pass the `password` keyword argument, e.g., `pdfplumber.open("file.pdf", password = "test")`. + ### The `pdfplumber.PDF` class The top-level `pdfplumber.PDF` class represents a single PDF and has two main properties: diff --git a/pdfplumber/pdf.py b/pdfplumber/pdf.py index 89b1a8a..a9ee980 100644 --- a/pdfplumber/pdf.py +++ b/pdfplumber/pdf.py @@ -13,13 +13,19 @@ from pdfminer.psparser import PSLiteral class PDF(Container): cached_properties = Container.cached_properties + [ "_pages" ] - def __init__(self, stream, pages=None, laparams=None, precision=0.001): + def __init__(self, + stream, + pages = None, + laparams = None, + precision = 0.001, + password = b"" + ): self.laparams = None if laparams == None else LAParams(**laparams) self.stream = stream self.pages_to_parse = pages self.precision = precision rsrcmgr = PDFResourceManager() - self.doc = PDFDocument(PDFParser(stream)) + self.doc = PDFDocument(PDFParser(stream), password = password) self.metadata = {} for info in self.doc.info: self.metadata.update(info) diff --git a/tests/pdfs/password-example.pdf b/tests/pdfs/password-example.pdf new file mode 100644 index 0000000..e5c650e Binary files /dev/null and b/tests/pdfs/password-example.pdf differ diff --git a/tests/test-basics.py b/tests/test-basics.py index 9af482f..d736243 100644 --- a/tests/test-basics.py +++ b/tests/test-basics.py @@ -50,3 +50,9 @@ class Test(unittest.TestCase): assert(rotated.pages[0].cropbox == self.pdf.pages[0].cropbox) assert(rotated.pages[0].bbox != self.pdf.pages[0].bbox) + + def test_password(self): + path = os.path.join(HERE, "pdfs/password-example.pdf") + pdf = pdfplumber.open(path, password = "test") + assert(len(pdf.chars) > 0) + pdf.close()