From f328eb3ba5418da50d95c254029aa96686543c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vit=C3=B3rio=20A=2E=20Cavalheiro?= Date: Fri, 10 Oct 2025 08:33:00 -0300 Subject: [PATCH 1/5] ci: add CI workflow and branch deletion automation Add GitHub Actions workflows for continuous integration testing and automated deletion of merged branches. The CI workflow includes steps for Python setup, dependency installation with Poetry, running tests, and linting with Black, isort, and detect-secrets. The branch deletion workflow removes merged branches upon PR closure. --- .github/workflows/ci.yml | 34 +++++++++++++++++++++++++++++ .github/workflows/delete-branch.yml | 19 ++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/delete-branch.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f118a5b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,34 @@ +name: CI + +on: + push: + branches: [ main, development ] + pull_request: + branches: [ main, development ] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.13' + - name: Install Poetry + run: | + curl -sSL https://install.python-poetry.org | python3 - + echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: Install dependencies + run: | + poetry config virtualenvs.create false + poetry install --with dev + - name: Install pytest + run: poetry add --group dev pytest + - name: Run tests + run: poetry run pytest + - name: Run linting + run: | + poetry run black --check . + poetry run isort --check-only . + poetry run detect-secrets scan \ No newline at end of file diff --git a/.github/workflows/delete-branch.yml b/.github/workflows/delete-branch.yml new file mode 100644 index 0000000..56d5a61 --- /dev/null +++ b/.github/workflows/delete-branch.yml @@ -0,0 +1,19 @@ +name: Delete merged branch + +on: + pull_request: + types: [closed] + +permissions: + contents: write + +jobs: + delete-branch: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + steps: + - name: Delete merged branch + run: gh branch delete ${{ github.head_ref }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + \ No newline at end of file From eb2023e431d182d52a65b7c0fdfc45eb3131b07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vit=C3=B3rio=20A=2E=20Cavalheiro?= Date: Fri, 10 Oct 2025 10:17:30 -0300 Subject: [PATCH 2/5] ci: remove dev and prod CI workflows --- .github/workflows/dev.yml | 110 ------------------------------------ .github/workflows/prod.yml | 113 ------------------------------------- 2 files changed, 223 deletions(-) delete mode 100644 .github/workflows/dev.yml delete mode 100644 .github/workflows/prod.yml diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml deleted file mode 100644 index 4481c95..0000000 --- a/.github/workflows/dev.yml +++ /dev/null @@ -1,110 +0,0 @@ -name: Python CI/CD - Dev - -on: - push: - branches: - - dev - -jobs: - lint: - runs-on: ubuntu-latest - - steps: - - name: Checkout Repository - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - - name: Install Pipenv - run: pip install pipenv - - - name: Install Dependencies - run: pipenv install --dev - - - name: Run Black - run: pipenv run black --check . - - - name: Run Isort - run: pipenv run isort --check-only . - - test: - needs: lint - runs-on: ubuntu-latest - - steps: - - name: Checkout Repository - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - - name: Install Pipenv - run: pip install pipenv - - - name: Install Dependencies - run: pipenv install --dev - - - name: Run Tests - run: pipenv run python -m unittest discover tests - - detect_secrets: - needs: lint - runs-on: ubuntu-latest - - steps: - - name: Checkout Repository - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - - name: Install Dependencies - run: | - pip install detect-secrets - - - name: Run Detect Secrets - run: detect-secrets scan . - - publish_to_testpypi: - name: Publish Python 🐍 distribution 📦 to TestPyPI - needs: [detect_secrets, test] - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Install dependencies - run: | - python -m pip install --upgrade setuptools wheel - python -m pip install --upgrade twine - - - name: Build package - run: | - python setup.py sdist bdist_wheel - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: python-package-distributions - path: dist/ - - - name: Download artifact - uses: actions/download-artifact@v3 - with: - name: python-package-distributions - path: dist/ - - - name: Publish to TestPyPI - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_TEST_TOKEN }} - run: | - twine upload --repository-url https://test.pypi.org/legacy/ --verbose dist/* \ No newline at end of file diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml deleted file mode 100644 index 9eec009..0000000 --- a/.github/workflows/prod.yml +++ /dev/null @@ -1,113 +0,0 @@ -name: Python CI/CD - Prod - -on: - pull_request: - branches: - - prod - release: - types: [created] - -jobs: - lint: - runs-on: ubuntu-latest - - steps: - - name: Checkout Repository - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - - name: Install Pipenv - run: pip install pipenv - - - name: Install Dependencies - run: pipenv install --dev - - - name: Run Black - run: pipenv run black --check . - - - name: Run Isort - run: pipenv run isort --check-only . - - test: - needs: lint - runs-on: ubuntu-latest - - steps: - - name: Checkout Repository - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - - name: Install Pipenv - run: pip install pipenv - - - name: Install Dependencies - run: pipenv install --dev - - - name: Run Tests - run: pipenv run python -m unittest discover tests - - detect_secrets: - needs: lint - runs-on: ubuntu-latest - - steps: - - name: Checkout Repository - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - - name: Install Dependencies - run: pip install detect-secrets - - - name: Run Detect Secrets - run: detect-secrets scan . - - - publish_to_pypi: - name: Publish Python 🐍 distribution 📦 to PyPI - needs: [detect_secrets, test] - if: github.event_name == 'release' && github.ref == 'refs/heads/prod' - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Install dependencies - run: | - python -m pip install --upgrade setuptools wheel - python -m pip install --upgrade twine - - - name: Build package - run: | - python setup.py sdist bdist_wheel - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: python-package-distributions - path: dist/ - - - name: Download artifact - uses: actions/download-artifact@v3 - with: - name: python-package-distributions - path: dist/ - - - name: Publish to PyPI - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} - run: | - twine upload --repository-url https://upload.pypi.org/legacy/ --verbose dist/* \ No newline at end of file From 18b8f7aea13648151ad21ef4405c7b97dd720ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vit=C3=B3rio=20Augusto=20Cavalheiro?= <88901960+oVitorio-ac@users.noreply.github.com> Date: Fri, 10 Oct 2025 10:40:03 -0300 Subject: [PATCH 3/5] chore: add pre-commit configuration and update dev dependencies (#11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add pre-commit hooks for code quality checks including trailing whitespace, end-of-file fixes, YAML validation, large file checks, Black formatting, isort imports, Flake8 linting, and Pylint analysis. Update pyproject.toml with corresponding dev dependencies for flake8, pylint, and pre-commit. Co-authored-by: Vitório A. Cavalheiro --- .pre-commit-config.yaml | 29 +++++++++++++++++++++++++++++ pyproject.toml | 3 +++ 2 files changed, 32 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..50cfcce --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,29 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + + - repo: https://github.com/psf/black + rev: 25.9.0 + hooks: + - id: black + + - repo: https://github.com/pycqa/isort + rev: 6.1.0 + hooks: + - id: isort + + - repo: https://github.com/pycqa/flake8 + rev: 7.3.0 + hooks: + - id: flake8 + + - repo: https://github.com/pycqa/pylint + rev: v3.3.9 + hooks: + - id: pylint + args: [--rcfile=.pylintrc] diff --git a/pyproject.toml b/pyproject.toml index 73f6dc8..2faf85b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,9 @@ reportlab = "4.2.*" [tool.poetry.group.dev.dependencies] black = "24.4.*" isort = "*" +flake8 = "*" +pylint = "*" +pre-commit = "*" detect-secrets = "1.5.0" [build-system] From b58612ba2b0f318010a36df2d10756020071af67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vit=C3=B3rio=20Augusto=20Cavalheiro?= <88901960+oVitorio-ac@users.noreply.github.com> Date: Fri, 10 Oct 2025 10:49:46 -0300 Subject: [PATCH 4/5] chore: add pre-commit configuration and update dev dependencies (#12) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: add pre-commit configuration and update dev dependencies Add pre-commit hooks for code quality checks including trailing whitespace, end-of-file fixes, YAML validation, large file checks, Black formatting, isort imports, Flake8 linting, and Pylint analysis. Update pyproject.toml with corresponding dev dependencies for flake8, pylint, and pre-commit. * ci: update branch deletion to use API call in delete-branch workflow The change replaces `gh branch delete` with a direct GitHub API DELETE request for more reliable branch deletion in the CI workflow. --------- Co-authored-by: Vitório A. Cavalheiro --- .github/workflows/delete-branch.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/delete-branch.yml b/.github/workflows/delete-branch.yml index 56d5a61..842424c 100644 --- a/.github/workflows/delete-branch.yml +++ b/.github/workflows/delete-branch.yml @@ -13,7 +13,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Delete merged branch - run: gh branch delete ${{ github.head_ref }} + run: gh api -X DELETE repos/${{ github.repository }}/git/refs/heads/${{ github.head_ref }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - \ No newline at end of file From 17859bca10a1ae06df2fe6ba4349a58dab05be0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vit=C3=B3rio=20Augusto=20Cavalheiro?= <88901960+oVitorio-ac@users.noreply.github.com> Date: Fri, 10 Oct 2025 12:52:35 -0300 Subject: [PATCH 5/5] refactor(generator): streamline module imports and enhance type safety (#13) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce __all__ declarations in package init files to clearly define the public API for LoremIpsum, PDFGenerator, and related classes. Convert absolute imports to relative paths for better encapsulation and add type hints to method signatures in PDFGenerator for improved code clarity and maintainability. Co-authored-by: Vitório A. Cavalheiro --- .flake8 | 2 ++ .pylintrc | 8 ++++-- pyloremgen/generator/__init__.py | 12 +++++++++ pyloremgen/generator/lorem_pdf.py | 40 ++++++++++++++++++++++++++---- pyloremgen/generator/lorem_text.py | 24 +++++++++--------- pyproject.toml | 7 ++++-- 6 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..2bcd70e --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 88 diff --git a/.pylintrc b/.pylintrc index d040b9c..fcd6005 100644 --- a/.pylintrc +++ b/.pylintrc @@ -337,7 +337,7 @@ indent-after-paren=4 indent-string=' ' # Maximum number of characters on a single line. -max-line-length=100 +max-line-length=88 # Maximum number of lines in a module. max-module-lines=1000 @@ -430,7 +430,11 @@ disable=raw-checker-failed, deprecated-pragma, use-symbolic-message-instead, use-implicit-booleaness-not-comparison-to-string, - use-implicit-booleaness-not-comparison-to-zero + use-implicit-booleaness-not-comparison-to-zero, + missing-module-docstring, + attribute-defined-outside-init, + too-few-public-methods, + import-error # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/pyloremgen/generator/__init__.py b/pyloremgen/generator/__init__.py index e69de29..66a6356 100644 --- a/pyloremgen/generator/__init__.py +++ b/pyloremgen/generator/__init__.py @@ -0,0 +1,12 @@ +from .lorem_pdf import PDFGenerator +from .lorem_text import LoremIpsum, LoremIpsumError +from .pdf_utils.cover_page_template import CoverPageBuilder +from .pdf_utils.pdf_page_settings import PagesConfigPDF + +__all__ = [ + "LoremIpsum", + "PDFGenerator", + "LoremIpsumError", + "PagesConfigPDF", + "CoverPageBuilder", +] diff --git a/pyloremgen/generator/lorem_pdf.py b/pyloremgen/generator/lorem_pdf.py index 9c0b77d..8ec0c0e 100644 --- a/pyloremgen/generator/lorem_pdf.py +++ b/pyloremgen/generator/lorem_pdf.py @@ -1,17 +1,47 @@ +from typing import Optional + from reportlab.lib.styles import getSampleStyleSheet from reportlab.platypus import PageBreak, Paragraph -from pyloremgen.generator.lorem_text import LoremIpsum -from pyloremgen.generator.pdf_utils.cover_page_template import CoverPageBuilder -from pyloremgen.generator.pdf_utils.pdf_page_settings import PagesConfigPDF +from .lorem_text import LoremIpsum +from .pdf_utils.cover_page_template import CoverPageBuilder +from .pdf_utils.pdf_page_settings import PagesConfigPDF class PDFGenerator: - def __init__(self, pages_config=None): + """ + PDFGenerator class for creating PDF documents with Lorem Ipsum content. + + This class provides functionality to generate + PDF files filled with Lorem Ipsum text, + with options for customizing page settings and including cover pages. + + Attributes: + pages_config (PagesConfigPDF): Configuration for PDF page settings. + lorem (LoremIpsum): Instance of LoremIpsum for generating text content. + + Methods: + generate_pdf(filename: str, num_pages: int = 1, + cover_page_count: bool = True) -> None: + Generates a PDF document with the specified number of pages. + """ + + def __init__(self, pages_config: Optional[PagesConfigPDF] = None) -> None: self.pages_config = pages_config or PagesConfigPDF() self.lorem = LoremIpsum() - def generate_pdf(self, filename, num_pages=1, cover_page_count=True): + def generate_pdf( + self, filename: str, num_pages: int = 1, cover_page_count: bool = True + ) -> None: + """ + Generate a PDF document with Lorem Ipsum content. + + Args: + filename (str): The name of the output PDF file. + num_pages (int, optional): The number of pages to generate. Defaults to 1. + cover_page_count (bool, optional): + Whether to include a cover page. Defaults to True. + """ self.num_pages = num_pages doc = self.pages_config.create_document(filename) content = [] diff --git a/pyloremgen/generator/lorem_text.py b/pyloremgen/generator/lorem_text.py index fbfed3d..76b9b68 100644 --- a/pyloremgen/generator/lorem_text.py +++ b/pyloremgen/generator/lorem_text.py @@ -1,6 +1,6 @@ import random -from pyloremgen.utilities.file_helper import get_data_json +from ..utilities.file_helper import get_data_json class LoremIpsumError(Exception): @@ -17,7 +17,7 @@ class LoremIpsum: LoremIpsum class This class generates lorem ipsum text. - It provides methods for generating paragraphs, words, and a shopping list of random items. + It provides methods for generating paragraphs, words, and shopping lists. Methods: __init__(): @@ -63,8 +63,8 @@ def __init__(self) -> None: - `paragraph_lorem`: A list to store lorem ipsum paragraphs. - `words_lorem`: A list to store lorem ipsum words. - `items_lorem`: A list to store lorem ipsum items. - - `paragraphs_words`: A variable to store the number of words in each paragraph. - - `start_with_lorem_ipsum`: A string that represents the start of a lorem ipsum text. + - `paragraphs_words`: Number of words in each paragraph. + - `start_with_lorem_ipsum`: Start lorem ipsum string. Parameters: None @@ -126,10 +126,10 @@ def paragraphs( Parameters: paragraphs_numbers (int): The number of paragraphs to generate. - size (str, optional): The size of the paragraphs. Can be "small", "medium", or "large". Defaults to "medium". - start_with_lorem_ipsum (bool, optional): - start_with_lorem_ipsum (bool, optional): - Whether to start with a "Lorem ipsum" paragraph. Defaults to False. + size (str, optional): Size of paragraphs + ("small", "medium", "large"). Default "medium". + start_with_lorem_ipsum (bool, optional): Start with + "Lorem ipsum" paragraph. Default True. Returns: str: The generated paragraphs joined by newline characters. @@ -180,7 +180,7 @@ def shopping_list(self, items_count: int = None) -> str: Returns: str: The shopping list as a string, with each item on a new line. Raises: - LoremIpsumError: If an error occurs during the generation of the shopping list. + LoremIpsumError: If an error occurs. """ items_count = random.randint(5, 100) if items_count is None else items_count try: @@ -194,8 +194,8 @@ def shopping_list(self, items_count: int = None) -> str: items = random.choices(repeated_data, k=items_count) else: items = random.choices(data_json, k=items_count) - self.items_lorem.append("Shopping List:") - self.items_lorem.extend(items) - return "\n".join(self.items_lorem) + self.items_lorem.append("Shopping List:") + self.items_lorem.extend(items) + return "\n".join(self.items_lorem) except Exception as e: raise LoremIpsumError(f"Error generating shopping list: {str(e)}") from e diff --git a/pyproject.toml b/pyproject.toml index 2faf85b..7362465 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,11 +25,14 @@ requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.black] -line-length = 100 +line-length = 88 target-version = ['py38'] skip-string-normalization = true [tool.isort] profile = "black" -line_length = 100 +line_length = 88 + +[tool.flake8] +max-line-length = 88