feat: Comprehensive Fix - Issues #2, #3, #7, #8, #9, #10#11
Conversation
…, SUPAIDEAS#9 - Add CI, Unit Tests, CLI Entry Point, and Docs
|
Pushed a fix (7d58f57) to resolve the CI |
There was a problem hiding this comment.
Pull request overview
This PR addresses multiple issues (#2, #3, #7, #8, #9, #10) to add comprehensive functionality including unit tests for the encrypt_pdf function, CLI entry points, GitHub Actions CI workflow, CLI documentation, and migration from setup.py to Poetry-based dependency management.
Changes:
- Added unit tests for the
encrypt_pdffunction with mocking of PdfReader and PdfWriter - Migrated from setup.py and requirements.txt to Poetry (pyproject.toml and poetry.lock)
- Created GitHub Actions CI workflow to run tests across Python 3.8-3.12 with coverage reporting
- Added CLI documentation describing command-line options
Reviewed changes
Copilot reviewed 8 out of 10 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unittests/test_encryptpdf.py | Added comprehensive unit tests for encrypt_pdf function with mocking; fixed deprecated assertEquals to assertEqual |
| tests/test_encryptpdf_example.py | Fixed deprecated assertEquals to assertEqual |
| tests/integrationtests/test_encryptpdf_integration.py | Fixed deprecated assertEquals to assertEqual and updated test value |
| setup.py | Removed legacy setup.py file as part of Poetry migration |
| requirements.txt | Removed legacy requirements.txt file as part of Poetry migration |
| pyproject.toml | Added Poetry configuration with package metadata, dependencies, and console_scripts entry point |
| poetry.lock | Added Poetry lock file for dependency management |
| docs/CLI_OPTIONS.md | Added comprehensive CLI documentation with option descriptions and usage example |
| README.md | Added reference to CLI Options documentation |
| .github/workflows/ci.yml | Added GitHub Actions CI workflow for testing across multiple Python versions with coverage |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| from encryptpdf import pipeline | ||
| from unittest.mock import patch, mock_open | ||
| from passifypdf.encryptpdf import pipeline, encrypt_pdf |
There was a problem hiding this comment.
The import statement from encryptpdf import pipeline, encrypt_pdf assumes the module is available at the top level. However, with the Poetry configuration in pyproject.toml defining packages as [{include = "passifypdf"}], this should be from passifypdf.encryptpdf import pipeline, encrypt_pdf. This import will fail when tests are run through Poetry or when the package is properly installed.
| ## Example Usage | ||
|
|
||
| ```bash | ||
| python3 passifypdf/encryptpdf.py -i input.pdf -o protected.pdf -p mySecretPassword |
There was a problem hiding this comment.
The example usage shows python3 passifypdf/encryptpdf.py -i input.pdf -o protected.pdf -p mySecretPassword, but with the Poetry setup and the console_scripts entry point defined in pyproject.toml (line 21), the correct usage should be passifypdf -i input.pdf -o protected.pdf -p mySecretPassword (after installation with Poetry). The current example doesn't align with how the package is intended to be used via the CLI entry point.
| python3 passifypdf/encryptpdf.py -i input.pdf -o protected.pdf -p mySecretPassword | |
| passifypdf -i input.pdf -o protected.pdf -p mySecretPassword |
|
|
||
| ## Usage via CLI: | ||
|
|
||
| See [CLI Options](docs/CLI_OPTIONS.md) for full documentation. |
There was a problem hiding this comment.
The documentation reference to CLI Options is helpful. However, note that the section above (lines 19-23) still references pip install -r requirements.txt, but requirements.txt has been removed in this PR. The installation instructions should be updated to use Poetry commands like poetry install.
| [tool.poetry.scripts] | ||
| passifypdf = "passifypdf.encryptpdf:main" |
There was a problem hiding this comment.
The console script entry point references passifypdf.encryptpdf:main, which is correct. However, the encryptpdf.py module (not modified in this PR) has an import statement from cli import get_arg_parser which should be from passifypdf.cli import get_arg_parser or from .cli import get_arg_parser. This will cause the CLI to fail when invoked via the entry point. This needs to be addressed for the CLI to work properly.
| @patch('passifypdf.encryptpdf.PdfReader') | ||
| @patch('passifypdf.encryptpdf.PdfWriter') |
There was a problem hiding this comment.
The mock patches reference encryptpdf.PdfReader and encryptpdf.PdfWriter, but with the Poetry package structure, these should be passifypdf.encryptpdf.PdfReader and passifypdf.encryptpdf.PdfWriter to correctly patch the imports within the module.
|
|
||
| [tool.poetry.dependencies] | ||
| python = "^3.8" | ||
| pypdf = "4.3.1" |
There was a problem hiding this comment.
The pypdf dependency is pinned to an exact version 4.3.1 without using a caret (^). This is overly restrictive and prevents Poetry from installing compatible patch or minor updates. Consider using pypdf = "^4.3.1" to allow compatible updates, or at minimum pypdf = "~4.3.1" to allow patch updates, following standard Poetry practices.
| pypdf = "4.3.1" | |
| pypdf = "^4.3.1" |
| poetry install | ||
| - name: Test with unittest | ||
| run: | | ||
| poetry run coverage run -m unittest discover tests |
There was a problem hiding this comment.
The CI workflow will fail when it tries to run the tests because of the incorrect import statements in the test files (see comments on test files). The tests import from encryptpdf instead of passifypdf.encryptpdf, which will cause ImportError when run through Poetry. This needs to be fixed before the CI can pass.
| poetry run coverage run -m unittest discover tests | |
| PYTHONPATH=passifypdf poetry run coverage run -m unittest discover tests |
| | `-p` | `--passwd` | Yes | Password to use for encryption. | | ||
| | `-v` | `--version` | No | Show the program's version number and exit. | | ||
| | `-h` | `--help` | No | Show the help message and exit. | | ||
|
|
||
| ## Example Usage | ||
|
|
||
| ```bash | ||
| python3 passifypdf/encryptpdf.py -i input.pdf -o protected.pdf -p mySecretPassword |
There was a problem hiding this comment.
The CLI option -p/--passwd encourages passing the PDF encryption password directly on the command line, which exposes the password in process listings (e.g., ps) and in shell history on most systems. An attacker with local access can read these arguments to recover the password and decrypt protected PDFs or reuse the password elsewhere. Consider switching to a safer input method for the password (for example, prompting securely or reading from a protected source) and avoid requiring or documenting plaintext passwords in CLI arguments.
| | `-p` | `--passwd` | Yes | Password to use for encryption. | | |
| | `-v` | `--version` | No | Show the program's version number and exit. | | |
| | `-h` | `--help` | No | Show the help message and exit. | | |
| ## Example Usage | |
| ```bash | |
| python3 passifypdf/encryptpdf.py -i input.pdf -o protected.pdf -p mySecretPassword | |
| | `-p` | `--passwd` | Yes | Password to use for encryption. **Avoid passing sensitive passwords directly on the command line, as they may be exposed via process listings and shell history.** | | |
| | `-v` | `--version` | No | Show the program's version number and exit. | | |
| | `-h` | `--help` | No | Show the help message and exit. | | |
| ## Example Usage | |
| ```bash | |
| # Prefer providing the password via a secure prompt or protected source (for example, an environment variable). | |
| PDF_PASSWORD='example-password' python3 passifypdf/encryptpdf.py -i input.pdf -o protected.pdf -p "$PDF_PASSWORD" |
|
Addresses all code review feedback (Commit 5690157):
|
|
Hi @ambicuity , thanks for the PR. CI looks Green now. |
…and Copilot review Implemented robust error handling in encryptpdf.py. Updated CLI with type hints and return codes. comprehensive unit and integration tests. Addressed all Copilot feedback regarding imports and docs.
- Reorder imports in encryptpdf.py to follow PEP 8 (stdlib → third-party → local) - Fix passifypdf/__init__.py placeholder text from cookiecutter template - Fix unclosed code fence and inline security warning in docs/CLI_OPTIONS.md - Update README.md stale 'Sample Run' section to use Poetry CLI entry point - Clean up blank lines in integration test file - All 8 Copilot suggestions now fully addressed - All tests pass (pytest + unittest)
Resolved Issues:
All changes verified locally.