From de4846b472ac81a22f4aa34c5dd85f0fbc1be306 Mon Sep 17 00:00:00 2001 From: lpm0073 Date: Tue, 14 Nov 2023 11:10:12 -0600 Subject: [PATCH 1/3] refactor: requirements and init --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 0ba89fe..23cb685 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ pre-commit: pre-commit run --all-files requirements: - rm -rf venv .tox node_modules + rm -rf .tox $(PIP) install --upgrade pip wheel $(PIP) install -r requirements/local.txt && \ npm install && \ @@ -18,7 +18,7 @@ requirements: pre-commit autoupdate init: - rm -rf .pytest_cache __pycache__ .pytest_cache + rm -rf venv .pytest_cache __pycache__ .pytest_cache node_modules python3.11 -m venv venv && \ . venv/bin/activate && \ make requirements From dfd4e3e243c8fea200aaced4389d5dcfa71c2c38 Mon Sep 17 00:00:00 2001 From: lpm0073 Date: Tue, 5 Dec 2023 10:19:48 -0600 Subject: [PATCH 2/3] refactor: standardize repo resources to YT channel standard. lint and reformat --- .gitattributes | 2 + .github/FUNDING.yml | 4 +- .github/dependabot.yml | 18 +- .github/workflows/checkPullRequest.yml | 25 --- .github/workflows/mergeMainNext.yml | 39 ---- .github/workflows/precommitVersionBumps.yml | 102 ++++++++++ .github/workflows/pullRequestController.yml | 116 ++++++++++++ .github/workflows/pushMain.yml | 102 ++++++++++ .github/workflows/release.yml | 69 ------- .github/workflows/runTests.yml | 29 +++ ...ersionBump.yml => semanticVersionBump.yml} | 30 ++- .github/workflows/tests.yml | 33 ---- .github/workflows/versionBumpMerge.yml | 89 --------- .gitignore | 115 ++++-------- .pre-commit-config.yaml | 120 ++++++------ .prettierignore | 0 .prettierrc | 3 + .pylintrc | 11 ++ CHANGELOG.md | 74 ++++---- CODE_OF_CONDUCT.md | 2 +- Makefile | 25 ++- README.md | 164 +++++++++++++++++ README.rst | 174 ------------------ SECURITY.md | 2 +- __version__.py | 3 +- codespell.txt | 1 + package copy.json | 15 ++ pyproject.toml | 26 ++- requirements/local.txt | 15 ++ run_pylint.sh | 3 + secure_logger/decorators.py | 19 +- secure_logger/masked_dict.py | 23 +-- secure_logger/tests/tests.py | 57 ++++-- setup.py | 101 ++-------- setup_test.py | 3 +- setup_utils.py | 40 +++- tox.ini | 21 ++- 37 files changed, 893 insertions(+), 782 deletions(-) create mode 100644 .gitattributes delete mode 100644 .github/workflows/checkPullRequest.yml delete mode 100644 .github/workflows/mergeMainNext.yml create mode 100644 .github/workflows/precommitVersionBumps.yml create mode 100644 .github/workflows/pullRequestController.yml create mode 100644 .github/workflows/pushMain.yml delete mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/runTests.yml rename .github/workflows/{versionBump.yml => semanticVersionBump.yml} (80%) delete mode 100644 .github/workflows/tests.yml delete mode 100644 .github/workflows/versionBumpMerge.yml create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .pylintrc create mode 100644 README.md delete mode 100644 README.rst create mode 100644 codespell.txt create mode 100644 package copy.json create mode 100755 run_pylint.sh diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3cf6bea --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +# * text eol=lf diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 9f02710..fe662b4 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,4 +1,4 @@ # These are supported funding model platforms -github: lpm0073 -patreon: lpm0073 +github: FullStackWithLawrence +patreon: FullStackWithLawrence diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9a5f000..f0caef1 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,30 +3,30 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "monthly" + interval: "weekly" assignees: - - "lpm0073" + - "FullStackWithLawrence" reviewers: - - "lpm0073" + - "FullStackWithLawrence" - package-ecosystem: "pip" directory: "/requirements/" schedule: - interval: "monthly" + interval: "weekly" labels: - "dependencies" - "python" assignees: - - "lpm0073" + - "FullStackWithLawrence" reviewers: - - "lpm0073" + - "FullStackWithLawrence" - package-ecosystem: "npm" directory: "/" schedule: - interval: "monthly" + interval: "weekly" labels: - "dependencies" - "javascript" assignees: - - "lpm0073" + - "FullStackWithLawrence" reviewers: - - "lpm0073" + - "FullStackWithLawrence" diff --git a/.github/workflows/checkPullRequest.yml b/.github/workflows/checkPullRequest.yml deleted file mode 100644 index 43b8d3a..0000000 --- a/.github/workflows/checkPullRequest.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Check Pull Request - -on: - pull_request: - branches: - - main - -jobs: - check-pull-request: - name: release - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Semantic Release - uses: cycjimmy/semantic-release-action@v4 - with: - branch: main - extra_plugins: | - @semantic-release/git - @semantic-release/changelog - dry_run: true - env: - GITHUB_TOKEN: ${{ secrets.PAT }} diff --git a/.github/workflows/mergeMainNext.yml b/.github/workflows/mergeMainNext.yml deleted file mode 100644 index f8b1b30..0000000 --- a/.github/workflows/mergeMainNext.yml +++ /dev/null @@ -1,39 +0,0 @@ -#------------------------------------------------------------------------------ -# Lawrence McDaniel - https://lawrencemcdaniel.com -# Version Bump Workflow -# -# Used mostly to propagate Dependabot pushed to main to the next branch. Use -# cases: -# - Dependabot pushes to main -# - Manual push to main -# - back propagation of modifications to __version__.py -#------------------------------------------------------------------------------ -name: Merge main into next - -on: - workflow_dispatch: - push: - branches: - - main - -jobs: - merge: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - persist-credentials: false - - - name: Merge main into next - run: | - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - git checkout main - git pull - git checkout next - git merge main - git push https://${{ secrets.PAT }}@github.com/${{ github.repository }}.git HEAD:next - env: - GITHUB_TOKEN: ${{ secrets.PAT }} diff --git a/.github/workflows/precommitVersionBumps.yml b/.github/workflows/precommitVersionBumps.yml new file mode 100644 index 0000000..aca048a --- /dev/null +++ b/.github/workflows/precommitVersionBumps.yml @@ -0,0 +1,102 @@ +--- +#------------------------------------------------------------------------------ +# Lawrence McDaniel - https://lawrencemcdaniel.com +# Version Bump Workflow for .pre-commit-config.yaml +# +# This workflow runs on a cron schedule and checks for updates to the +# .pre-commit-config.yaml file. If updates are found, the workflow +# commits the changes to the next branch and pushes the changes to GitHub. +# +# This is a workaround for the fact that the pre-commit autoupdate command +# is not supported by Dependabot. +#------------------------------------------------------------------------------ +name: pre-commit Version Bumps + +on: + schedule: + - cron: "0 0 * * 3" + workflow_dispatch: + +jobs: + evaluate_precommit_config: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Checkout next branch + run: | + git fetch + git checkout next + git pull origin next + + - name: Cache NPM dependencies + uses: actions/cache@v3 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node + + - name: Cache Python dependencies + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + + - name: locate site-packages path + shell: bash + run: | + echo "SITE_PACKAGES_PATH=$(python -c 'import site; print(site.getsitepackages()[0])')" >> $GITHUB_ENV + + - name: Install pip + shell: bash + run: | + python -m pip install --upgrade pip + + - name: Install dependencies + shell: bash + run: | + pip install -r ./requirements.txt + env: + SITE_PACKAGES_PATH: ${{ env.SITE_PACKAGES_PATH }} + + - name: Setup Node.js environment + uses: actions/setup-node@v4 + with: + node-version: "20.9.0" + + - name: Install npm dev dependencies + run: npm install + + - name: Update .pre-commit-config.yaml + run: | + pre-commit autoupdate + + - name: Check for unstaged changes + id: check_changes + run: | + if [[ -n "$(git status --porcelain .pre-commit-config.yaml)" ]]; then + echo "::set-output name=changes::true" + else + echo "::set-output name=changes::false" + fi + + - name: Commit and push changes + if: steps.check_changes.outputs.changes == 'true' + shell: bash + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add .pre-commit-config.yaml + git commit -m "chore: [gh] version bumps in .pre-commit-config.yaml [skip ci]" + git push https://${{ secrets.PAT }}@github.com/${{ github.repository }}.git HEAD:next diff --git a/.github/workflows/pullRequestController.yml b/.github/workflows/pullRequestController.yml new file mode 100644 index 0000000..23a4834 --- /dev/null +++ b/.github/workflows/pullRequestController.yml @@ -0,0 +1,116 @@ +--- +#------------------------------------------------------------------------------ +# Pull Request Workflow Controller. +# +# Triggers: +# - Called automatically on relevant actions performed on pull requests. +# - Can also be run manually by clicking the "Run workflow" button. +# +# Actions: +# - Use semantic release rules to determine if a new release will be published. +# - run Python tests, but only if Python-related files have changed. +# - run Terraform tests, but only if Terraform-related files have changed. +# - run ReactJS tests, but only if ReactJS-related files have changed. +# - run pre-commit hooks to ensure code is formatted correctly. +# +# To-Do: +# If a new release is to be published then we want to consider running QA tests +# to ensure formatting and documentation is correct. +#------------------------------------------------------------------------------ +name: Pull Request Controller + +on: + workflow_dispatch: + # GitHub Copilot: The `pull_request` and `pull_request_target` are two different + # event types in GitHub Actions that trigger workflows when activity related + # to pull requests occurs. + # - `pull_request`: This event triggers a workflow run whenever a pull + # request is opened, synchronized, or closed. The workflow runs in the context of the + # pull request, meaning it has access to the code and environment variables of the head + # branch of the pull request. This is safe for pull requests within the same repository, + # but for pull requests from a fork, this could potentially expose sensitive information. + # + # - `pull_request_target`: This event is similar to `pull_request`, but it runs in the context + # of the base of the pull request, rather than the head. This means it has access to the code + # and environment variables of the base branch, not the head branch. This is safer for + # pull requests from forks, as it prevents the fork from accessing sensitive information + # in the base repository. However, it means the workflow does not have access to the code + # in the pull request by default. If you need to access the code in the pull request, + # you can use the `actions/checkout` action with the `ref` input + # set to `github.event.pull_request.head.ref`. + # + # In general, use `pull_request` for workflows that need to access the code in the pull request, + # and `pull_request_target` for workflows that need to be safe for pull requests from forks. + pull_request_target: + types: [opened, synchronize] + paths: + - "**.py" + - "**.requirements.txt" + - "**.package.json" + - "./secure_logger/**" + +env: + python-version: "3.11" + +jobs: + check_for_pending_release: + name: test-semantic-release + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Semantic Release + uses: cycjimmy/semantic-release-action@v4 + id: semantic + with: + dry_run: true + branches: | + [ + '+([0-9])?(.{+([0-9]),x}).x', + 'main', + 'next', + 'next-major', + { + name: 'beta', + prerelease: true + }, + { + name: 'alpha', + prerelease: true + } + ] + extra_plugins: | + @semantic-release/git + @semantic-release/changelog + env: + GITHUB_TOKEN: ${{ secrets.PAT }} + + - name: Test Outputs + if: steps.semantic.outputs.new_release_published == 'true' + run: | + echo ${{ steps.semantic.outputs.new_release_version }} + echo ${{ steps.semantic.outputs.new_release_major_version }} + echo ${{ steps.semantic.outputs.new_release_minor_version }} + echo ${{ steps.semantic.outputs.new_release_patch_version }} + + python_tests: + needs: check_for_pending_release + runs-on: ubuntu-latest + + steps: + - name: Checkout code + id: checkout + uses: actions/checkout@v4 + + - name: Check for changed files + id: file_changes + run: | + echo "::set-output name=files_changed::$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep '\.py$' || true)" + echo "::set-output name=requirements_changed::$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep 'requirements.txt$' || true)" + + - name: Run Python tests + if: steps.file_changes.outputs.files_changed != '' || steps.file_changes.outputs.requirements_changed != '' + uses: ./.github/actions/tests/python + with: + python-version: "${{ env.python-version}}" diff --git a/.github/workflows/pushMain.yml b/.github/workflows/pushMain.yml new file mode 100644 index 0000000..6805ed0 --- /dev/null +++ b/.github/workflows/pushMain.yml @@ -0,0 +1,102 @@ +--- +#--------------------------------------------------------- +# - Create a semantical release +# - Merge main into next, alpha, beta, and next-major +#--------------------------------------------------------- +name: Push to main + +on: + workflow_dispatch: + push: + branches: + - main +jobs: + merge-main-to-dev-branches: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.PAT }} + + steps: + - name: Checkout code + id: checkout + uses: actions/checkout@v4 + + - name: Merge main into next + uses: ./.github/actions/merge-branch + with: + github-token: ${{ env.GITHUB_TOKEN }} + source-branch: main + target-branch: next + + - name: Merge main into next-major + uses: ./.github/actions/merge-branch + with: + github-token: ${{ env.GITHUB_TOKEN }} + source-branch: main + target-branch: next-major + + - name: Merge main into alpha + uses: ./.github/actions/merge-branch + with: + github-token: ${{ env.GITHUB_TOKEN }} + source-branch: main + target-branch: alpha + + - name: Merge main into beta + uses: ./.github/actions/merge-branch + with: + github-token: ${{ env.GITHUB_TOKEN }} + source-branch: main + target-branch: beta + + semantic-release: + needs: merge-main-to-dev-branches + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.PAT }} + + steps: + - uses: actions/checkout@v4 + id: checkout + with: + persist-credentials: false + + - name: Semantic Release + uses: cycjimmy/semantic-release-action@v4 + id: semantic + with: + branches: | + [ + '+([0-9])?(.{+([0-9]),x}).x', + 'main', + 'next', + 'next-major', + { + name: 'beta', + prerelease: true + }, + { + name: 'alpha', + prerelease: true + } + ] + extra_plugins: | + @semantic-release/git + @semantic-release/changelog + env: + GIT_COMMITTER_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + + - name: Publish To GitHub Package Registry + id: publish + if: steps.semantic.outputs.new_release_published == 'true' + run: echo "new release was published" + shell: bash + + - name: Push updates to branch for major version + id: push_major + if: steps.semantic.outputs.new_release_published == 'true' + run: "git push https://x-access-token:${{ env.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git HEAD:refs/heads/v${{steps.semantic.outputs.new_release_major_version}}" + shell: bash diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 60a6212..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,69 +0,0 @@ -#--------------------------------------------------------- -# - Create a semantical release -# - Set latest tag -#--------------------------------------------------------- -name: Create a new release - -on: - workflow_dispatch: - push: - branches: - - main - -jobs: - release: - runs-on: ubuntu-latest - - steps: - # required antecedent - - uses: actions/checkout@v4 - with: - persist-credentials: false - - - name: Setup Node.js environment - uses: actions/setup-node@v4 - with: - node-version: '20.9.0' - - - name: Install npm dev dependencies - run: npm install --only=dev - - - name: Semantic Release - uses: cycjimmy/semantic-release-action@v4 - id: semantic - with: - branches: | - [ - '+([0-9])?(.{+([0-9]),x}).x', - 'main', - 'next', - 'next-major', - { - name: 'beta', - prerelease: true - }, - { - name: 'alpha', - prerelease: true - } - ] - extra_plugins: | - @semantic-release/git - @semantic-release/changelog - env: - GITHUB_TOKEN: ${{ secrets.PAT }} - GIT_COMMITTER_NAME: github-actions[bot] - GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com - GIT_AUTHOR_NAME: github-actions[bot] - GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com - - - name: Publish To GitHub Package Registry - if: steps.semantic.outputs.new_release_published == 'true' - run: echo "new release was published" - shell: bash - - - name: Push updates to branch for major version - if: steps.semantic.outputs.new_release_published == 'true' - run: "git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git HEAD:refs/heads/v${{steps.semantic.outputs.new_release_major_version}}" - env: - GITHUB_TOKEN: ${{ secrets.PAT }} diff --git a/.github/workflows/runTests.yml b/.github/workflows/runTests.yml new file mode 100644 index 0000000..41c0edb --- /dev/null +++ b/.github/workflows/runTests.yml @@ -0,0 +1,29 @@ +--- +#------------------------------------------------------------------------------ +# Run all tests +#------------------------------------------------------------------------------ +name: Unit Tests + +on: + workflow_dispatch: + +env: + python-version: "3.11" + +jobs: + tests: + runs-on: ubuntu-latest + steps: + - name: Checkout code + id: checkout + uses: actions/checkout@v4 + + - name: Run Python tests + uses: ./.github/actions/tests/python + with: + python-version: "${{ env.python-version}}" + openai-api-organization: "${{ secrets.OPENAI_API_ORGANIZATION }}" + openai-api-key: "${{ secrets.OPENAI_API_KEY }}" + pinecone-api-key: "${{ secrets.PINECONE_API_KEY }}" + pinecone-environment: "${{ secrets.PINECONE_ENVIRONMENT }}" + pinecone-index-name: "${{ secrets.PINECONE_INDEX_NAME }}" diff --git a/.github/workflows/versionBump.yml b/.github/workflows/semanticVersionBump.yml similarity index 80% rename from .github/workflows/versionBump.yml rename to .github/workflows/semanticVersionBump.yml index df460af..b1a8c14 100644 --- a/.github/workflows/versionBump.yml +++ b/.github/workflows/semanticVersionBump.yml @@ -1,39 +1,53 @@ +--- #------------------------------------------------------------------------------ # Lawrence McDaniel - https://lawrencemcdaniel.com -# Version Bump Workflow +# Version Bump Workflow for Python package openai_utils # # Calculate the version of the 'next' branch based on semantic-release rules. # Compares the existing value of __version__.py to the calculated value. # If they are different, it will update __version__.py and push the changes # to the main branch. #------------------------------------------------------------------------------ -name: Bump version in next branch +name: Semantic Version Bump (next) on: workflow_dispatch: push: branches: + - alpha + - beta - next - next-major jobs: bump-version-next: runs-on: ubuntu-latest + env: + VERSION_FILE: __version__.py + PACKAGE_PATH: ${{ github.workspace }}/secure_logger/ steps: - uses: actions/checkout@v4 with: persist-credentials: false + - name: Cache NPM dependencies + uses: actions/cache@v3 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node + - name: Set up Python 3.11 uses: actions/setup-python@v4 with: - python-version: '3.11' + python-version: "3.11" - name: Setup Node.js environment uses: actions/setup-node@v4 with: - node-version: '20.9.0' + node-version: "20.9.0" - name: Install npm dev dependencies run: npm install @@ -43,6 +57,7 @@ jobs: # the current version persisted to __version__.py id: current_version run: | + cd ${{ env.PACKAGE_PATH }} echo "CURRENT_VERSION=$(python -c 'from __version__ import __version__; print(__version__)')" >> $GITHUB_ENV env: GITHUB_TOKEN: ${{ secrets.PAT }} @@ -87,7 +102,6 @@ jobs: id: null_step3 run: echo "i ensure that CURRENT_VERSION, NEXT_VERSION and VERSION_CHANGED are set." - - name: Update __version__.py # step 4 # if VERSION_CHANGED is true, update __version__.py and push the changes to the @@ -95,13 +109,15 @@ jobs: if: env.VERSION_CHANGED == 'true' id: update_version run: | - echo "__version__ = '${{ env.NEXT_VERSION }}'" > __version__.py + echo "# -*- coding: utf-8 -*-" > ${{ env.VERSION_FILE }} + echo "__version__ = \"${{ env.NEXT_VERSION }}\"" >> ${{ env.VERSION_FILE }} git config --local user.email "action@github.com" git config --local user.name "GitHub Action" - git add __version__.py + git add ${{ env.VERSION_FILE }} git commit -m "chore: [gh] Update __version__.py to ${{ env.NEXT_VERSION }} [skip ci]" git push https://${{ secrets.PAT }}@github.com/${{ github.repository }}.git HEAD:${{ github.ref }} env: + VERSION_FILE: ${{ env.PACKAGE_PATH }}${{ env.VERSION_FILE }} GITHUB_TOKEN: ${{ secrets.PAT }} NEXT_VERSION: ${{ env.NEXT_VERSION }} VERSION_CHANGED: ${{ env.VERSION_CHANGED }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml deleted file mode 100644 index fe7226f..0000000 --- a/.github/workflows/tests.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Unit Tests - -on: - pull_request: - push: - -jobs: - tests: - name: tests - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Python 3.x - uses: actions/setup-python@v4 - with: - python-version: "3.11" - - - name: Install requirements - run: | - python -m pip install --upgrade pip - pip install -r ./requirements/local.txt - - - name: secure_logger Unit tests - run: | - export PYTHONPATH=$PYTHONPATH:$(pwd) - python -m unittest discover -s secure_logger/tests/ - - - name: setup.py tests - run: | - export PYTHONPATH=$PYTHONPATH:$(pwd) - python -m unittest setup_test diff --git a/.github/workflows/versionBumpMerge.yml b/.github/workflows/versionBumpMerge.yml deleted file mode 100644 index bbdcb5a..0000000 --- a/.github/workflows/versionBumpMerge.yml +++ /dev/null @@ -1,89 +0,0 @@ -#------------------------------------------------------------------------------ -# Lawrence McDaniel - https://lawrencemcdaniel.com -# Version Bump and Merge Workflow -# -# Calculate the next version in the main branch. Compares the raw value of -# __version__.py to the calculated value in setup.py. If they are different, -# it will update __version__.py and push the changes to the main branch. -#------------------------------------------------------------------------------ -name: Bump version in main branch - -on: - push: - branches: - - main - -jobs: - set-version-main: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - - name: Set up Python 3.11 - uses: actions/setup-python@v4 - with: - python-version: '3.11' - - - name: Get current version - # step 1 - # the current version persisted to __version__.py - id: current_version - run: | - echo "CURRENT_VERSION=$(python -c 'from __version__ import __version__; print(__version__)')" >> $GITHUB_ENV - env: - GITHUB_TOKEN: ${{ secrets.PAT }} - - - name: Get next version - # step 2 - # retrieve the the next version based on the logic in setup.py, which - # strips the pre-release tag from the current version. - id: next_version - run: | - echo "NEXT_VERSION=$(python -c 'from setup_utils import get_semantic_version; print(get_semantic_version())')" >> $GITHUB_ENV - env: - GITHUB_TOKEN: ${{ secrets.PAT }} - - - name: null step - id: null_step - run: echo "i ensure that NEXT_VERSION is set." - - - name: Check versions - # step 3 - # calculate the next version based on a comparison of the current version - # to the version calucalated in setup.py. If they are different, then - # the version used in setup.py takes precedence. - id: check_versions - run: | - if [ "$CURRENT_VERSION" != "$NEXT_VERSION" ]; then - echo "VERSION_CHANGED=true" >> $GITHUB_ENV - else - echo "VERSION_CHANGED=false" >> $GITHUB_ENV - fi - env: - CURRENT_VERSION: ${{ env.CURRENT_VERSION }} - NEXT_VERSION: ${{ env.NEXT_VERSION }} - - - name: another null step - id: another_null_step - run: echo "i ensure that CURRENT_VERSION, NEXT_VERSION and VERSION_CHANGED are set." - - - - name: Update __version__.py - # step 4 - # if VERSION_CHANGED is true, update __version__.py and push the changes to the - # main branch. - if: env.VERSION_CHANGED == 'true' - id: update_version - run: | - echo "__version__ = '${{ env.NEXT_VERSION }}'" > __version__.py - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - git add __version__.py - git commit -m "chore: [gh] Update __version__.py to ${{ env.NEXT_VERSION }} [skip ci]" - git push https://${{ secrets.PAT }}@github.com/${{ github.repository }}.git HEAD:${{ github.ref }} - env: - GITHUB_TOKEN: ${{ secrets.PAT }} - NEXT_VERSION: ${{ env.NEXT_VERSION }} - VERSION_CHANGED: ${{ env.VERSION_CHANGED }} diff --git a/.gitignore b/.gitignore index 2abfc60..e07699a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,93 +1,44 @@ -.env -venv -package-lock.json -# .gitignore for edx-platform. -# There's a lot here, please try to keep it organized. +# Jupyter Notebook +.ipynb_checkpoints +data -### Files private to developers - -# Files that should be git-ignored, but are hand-edited or otherwise valued, -# and so should not be destroyed by "make clean". -# start-noclean -requirements/private.txt -# end-noclean +.DS_Store +# Local .terraform directories +.terraform/ +.env +lambda_dist_pkg +*.zip +__pycache__ +.pytest_cache -### Python artifacts +# Python +venv +.venv +.pytest_cache *.pyc -__pycache__/ - -### Editor and IDE artifacts -*~ +*.pyo +*.pyd *.swp -*.orig -/nbproject -.idea/ -.redcar/ -codekit-config.json -.pycharm_helpers/ -/_mac/* -/IntelliLang.xml -/conda_packages.xml -/databaseSettings.xml -/diff.xml -/debugger.xml -/editor.xml -/ide.general.xml -/inspection/Default.xml -/other.xml -/packages.xml -/web-browsers.xml +*.log -### OS X artifacts -*.DS_Store -.AppleDouble -:2e_* -:2e# +# .tfstate files +.terraform.lock.hcl +*.tfstate +*.tfstate.* -### Testing artifacts -.testids/ -.noseids -nosetests.xml -.cache/ -.coverage -.coverage.* -coverage.xml -.pytest_cache/ -pytest_task*.txt -.tddium* -test_root/ -django-pyfs -.tox/ -### Installation artifacts -*.egg-info -.pip_download_cache/ -.prereqs_cache -.vagrant/ -node_modules -bin/ +# ignore this file +!tfmodule-template.tf -### Logging artifacts -log/ -logs -chromedriver.log -ghostdriver.log +# tardigrade-ci +tardigrade-ci/ +.tardigrade-ci -### Unknown artifacts -database.sqlite -courseware/static/js/mathjax/* -flushdb.sh -build -/src/ -\#*\# -.env/ -autodeploy.properties -.ws_migrations_complete -dist -*.bak +# go tests +tests/go.* -# Visual Studio Code -# .vscode +# ReactJS +client/node_modules/ +node_modules -# Locally generated PII reports -pii_report +package-lock.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bc5f0aa..dfb1f87 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,81 +2,73 @@ default_language_version: # default language version for each language python: python3.11 repos: - - repo: https://github.com/ambv/black - rev: 23.11.0 - hooks: + - repo: https://github.com/codespell-project/codespell + rev: v2.2.6 + hooks: + - id: codespell + args: ["--ignore-words=codespell.txt"] + exclude: 'codespell.txt|\.svg$' + - repo: https://github.com/psf/black + rev: 23.11.0 + hooks: - id: black + - repo: https://github.com/PyCQA/flake8 + rev: 6.1.0 + hooks: + - id: flake8 + - repo: https://github.com/PyCQA/isort + rev: 5.12.0 + hooks: + - id: isort + args: ["--settings-path=pyproject.toml"] + - repo: local + hooks: + - id: pylint + name: pylint + entry: ./run_pylint.sh + language: script + types: [python] + - repo: https://github.com/PyCQA/bandit + rev: 1.7.5 + hooks: + - id: bandit + args: ["-ll"] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: # See https://pre-commit.com/hooks.html for more hooks - - id: check-added-large-files - args: - - --maxkb=128 - - id: check-docstring-first - - id: check-json - - id: check-xml - - id: detect-private-key - - id: mixed-line-ending - args: [ '--fix=lf' ] - description: Forces to replace line ending by the UNIX 'lf' character. + #- id: check-added-large-files + - id: fix-byte-order-marker - id: fix-encoding-pragma - - id: name-tests-test - args: - - --django - exclude: ^tests/testapp|^tests/management/|^tests/collisions/|^tests/pythonrc.py|^tests/runner.py - - id: check-ast - id: check-case-conflict - - id: check-executables-have-shebangs + - id: check-json - id: check-merge-conflict - - id: debug-statements - - id: end-of-file-fixer - - id: check-shebang-scripts-are-executable - id: check-symlinks + - id: check-toml + - id: check-xml - id: check-yaml - - id: debug-statements - exclude: tests/ - id: destroyed-symlinks + - id: detect-aws-credentials + - id: detect-private-key - id: end-of-file-fixer - exclude: tests/test_changes/ - files: \.(py|sh|rst|yml|yaml)$ + - id: forbid-new-submodules - id: trailing-whitespace - files: \.(py|sh|rst|yml|yaml)$ - - repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 - hooks: - - id: flake8 - args: [--ignore=D100] - additional_dependencies: [ - 'flake8-blind-except', - 'flake8-bugbear', - 'flake8-comprehensions', - 'flake8-docstrings', - 'flake8-implicit-str-concat', - 'pydocstyle', - 'flake8-coding', - 'flake8-debugger', - 'flake8-deprecated', - 'flake8-pep3101', - 'flake8-polyfill', - 'flake8-print', - 'flake8-string-format', - ] - exclude: ^tests/test_cases/no_closing_bracket\.py$ - - repo: https://github.com/rstcheck/rstcheck - rev: v6.2.0 - hooks: - - id: rstcheck - args: [ - --report-level=warning, - ] - - repo: https://github.com/codespell-project/codespell - rev: v2.2.6 - hooks: - - id: codespell - files: \.(py|sh|rst|yml|yaml)$ - - repo: https://github.com/trbs/pre-commit-hooks-trbs.git - rev: 1.2.4 + - id: check-case-conflict + - id: check-merge-conflict + - id: debug-statements + - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook + rev: v9.10.0 hooks: - - id: forbid-executables - exclude: manage.py|setup.py + - id: commitlint + stages: [commit-msg] + additional_dependencies: ["@commitlint/config-angular"] +ci: + # for more information, see https://pre-commit.ci + autofix_commit_msg: | + [pre-commit.ci] auto fixes from pre-commit.com hooks + autofix_prs: true + autoupdate_branch: "" + autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate" + autoupdate_schedule: weekly + skip: [shellcheck, markdown-link-check, commitlint] + submodules: false diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..e69de29 diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..75fa134 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "tabWidth": 2 +} diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..f74e19c --- /dev/null +++ b/.pylintrc @@ -0,0 +1,11 @@ +[MASTER] +init-hook='import sys; print(sys.executable); print(sys.path)' +ignore-paths = +ignore = + __version__.py + +[FORMAT] +max-line-length=120 + +[MESSAGES CONTROL] +disable=C0103,W0102,E0401 diff --git a/CHANGELOG.md b/CHANGELOG.md index c5a2c67..79a9633 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,94 +1,94 @@ -## [0.1.17](https://github.com/lpm0073/secure-logger/compare/v0.1.16...v0.1.17) (2023-11-14) +## [0.1.17](https://github.com/FullStackWithLawrence/secure-logger/compare/v0.1.16...v0.1.17) (2023-11-14) ### Bug Fixes -* add regex expressions to correctly evaluate all possible values of __version__.py ([1ac6246](https://github.com/lpm0073/secure-logger/commit/1ac6246f4840457a62d6a7a6ccf03065c28643c7)) -* restore npx semantic-release logic in next branch ([e8e4b1d](https://github.com/lpm0073/secure-logger/commit/e8e4b1db87d3e04e8e263080ca8adc4fda989d86)) +* add regex expressions to correctly evaluate all possible values of __version__.py ([1ac6246](https://github.com/FullStackWithLawrence/secure-logger/commit/1ac6246f4840457a62d6a7a6ccf03065c28643c7)) +* restore npx semantic-release logic in next branch ([e8e4b1d](https://github.com/FullStackWithLawrence/secure-logger/commit/e8e4b1db87d3e04e8e263080ca8adc4fda989d86)) -## [0.1.16](https://github.com/lpm0073/secure-logger/compare/v0.1.15...v0.1.16) (2023-11-14) +## [0.1.16](https://github.com/FullStackWithLawrence/secure-logger/compare/v0.1.15...v0.1.16) (2023-11-14) ### Bug Fixes -* convert prerelease version to strict semantic equivalent ([f463db5](https://github.com/lpm0073/secure-logger/commit/f463db5d53499166968fe0d9a36a36e3327d36d4)) -* remove pre-commit ([12c3da0](https://github.com/lpm0073/secure-logger/commit/12c3da0042cd7ff03783c278fddf1c3bb6b4f69a)) -* set prerelease to true for next and nexst-major ([b830102](https://github.com/lpm0073/secure-logger/commit/b8301020b57a5e1bc09517100d3d2724e9c7d716)) +* convert prerelease version to strict semantic equivalent ([f463db5](https://github.com/FullStackWithLawrence/secure-logger/commit/f463db5d53499166968fe0d9a36a36e3327d36d4)) +* remove pre-commit ([12c3da0](https://github.com/FullStackWithLawrence/secure-logger/commit/12c3da0042cd7ff03783c278fddf1c3bb6b4f69a)) +* set prerelease to true for next and nexst-major ([b830102](https://github.com/FullStackWithLawrence/secure-logger/commit/b8301020b57a5e1bc09517100d3d2724e9c7d716)) -## [0.1.15](https://github.com/lpm0073/secure-logger/compare/v0.1.14...v0.1.15) (2023-11-14) +## [0.1.15](https://github.com/FullStackWithLawrence/secure-logger/compare/v0.1.14...v0.1.15) (2023-11-14) ### Bug Fixes -* add npx semantic-release --dry-run --no-ci ([d0133ab](https://github.com/lpm0073/secure-logger/commit/d0133ab6d966370b5eabf44e3543c81d3fe6b850)) +* add npx semantic-release --dry-run --no-ci ([d0133ab](https://github.com/FullStackWithLawrence/secure-logger/commit/d0133ab6d966370b5eabf44e3543c81d3fe6b850)) -## [0.1.14](https://github.com/lpm0073/secure-logger/compare/v0.1.13...v0.1.14) (2023-11-14) +## [0.1.14](https://github.com/FullStackWithLawrence/secure-logger/compare/v0.1.13...v0.1.14) (2023-11-14) ### Bug Fixes -* fix requirements path for semantic release ([f2ad049](https://github.com/lpm0073/secure-logger/commit/f2ad049e7a146a3eadc75606db87651c0e89e59a)) -* must add next and next-major ([7434ecf](https://github.com/lpm0073/secure-logger/commit/7434ecfc7e82cf3c6c9b2e771ea410883a722343)) +* fix requirements path for semantic release ([f2ad049](https://github.com/FullStackWithLawrence/secure-logger/commit/f2ad049e7a146a3eadc75606db87651c0e89e59a)) +* must add next and next-major ([7434ecf](https://github.com/FullStackWithLawrence/secure-logger/commit/7434ecfc7e82cf3c6c9b2e771ea410883a722343)) -## [0.1.13](https://github.com/lpm0073/secure-logger/compare/v0.1.12...v0.1.13) (2023-11-14) +## [0.1.13](https://github.com/FullStackWithLawrence/secure-logger/compare/v0.1.12...v0.1.13) (2023-11-14) ### Bug Fixes -* long_description_content_type='text/x-rst' ([d551597](https://github.com/lpm0073/secure-logger/commit/d551597c208b3de6d635947ae2247c755928816e)) +* long_description_content_type='text/x-rst' ([d551597](https://github.com/FullStackWithLawrence/secure-logger/commit/d551597c208b3de6d635947ae2247c755928816e)) -## [0.1.12](https://github.com/lpm0073/secure-logger/compare/v0.1.11...v0.1.12) (2023-11-14) +## [0.1.12](https://github.com/FullStackWithLawrence/secure-logger/compare/v0.1.11...v0.1.12) (2023-11-14) ### Bug Fixes -* refactor python code blocks using readme_renderer compliant directives ([49a3423](https://github.com/lpm0073/secure-logger/commit/49a34234bb95ed37676f0620eb481a221302b73a)) +* refactor python code blocks using readme_renderer compliant directives ([49a3423](https://github.com/FullStackWithLawrence/secure-logger/commit/49a34234bb95ed37676f0620eb481a221302b73a)) -## [0.1.11](https://github.com/lpm0073/secure-logger/compare/v0.1.10...v0.1.11) (2023-11-14) +## [0.1.11](https://github.com/FullStackWithLawrence/secure-logger/compare/v0.1.10...v0.1.11) (2023-11-14) ### Bug Fixes -* CURRENT_VERSION was unassigned ([528fa71](https://github.com/lpm0073/secure-logger/commit/528fa71dc0fc008bd7098686cab94198a961f5c3)) +* CURRENT_VERSION was unassigned ([528fa71](https://github.com/FullStackWithLawrence/secure-logger/commit/528fa71dc0fc008bd7098686cab94198a961f5c3)) -## [0.1.10](https://github.com/lpm0073/secure-logger/compare/v0.1.9...v0.1.10) (2023-11-14) +## [0.1.10](https://github.com/FullStackWithLawrence/secure-logger/compare/v0.1.9...v0.1.10) (2023-11-14) ### Bug Fixes -* add a dedicated version bump workflow ([8c59680](https://github.com/lpm0073/secure-logger/commit/8c596807fda14a7d1ec927267d68db776ef1d822)) -* need to git pull ([24f177d](https://github.com/lpm0073/secure-logger/commit/24f177da2ef4b70ba73c69b9c1c51133a6d29c3c)) -* need to git pull ([2e60dbb](https://github.com/lpm0073/secure-logger/commit/2e60dbbd5922649e0dc5b0177f145d49f7b476dd)) -* need to git pull ([e173922](https://github.com/lpm0073/secure-logger/commit/e173922d290eba66addda88f408aa0d576382214)) -* remove version bump ([7b71ae9](https://github.com/lpm0073/secure-logger/commit/7b71ae9c484486cd124b751bc201f16cc2d627bf)) +* add a dedicated version bump workflow ([8c59680](https://github.com/FullStackWithLawrence/secure-logger/commit/8c596807fda14a7d1ec927267d68db776ef1d822)) +* need to git pull ([24f177d](https://github.com/FullStackWithLawrence/secure-logger/commit/24f177da2ef4b70ba73c69b9c1c51133a6d29c3c)) +* need to git pull ([2e60dbb](https://github.com/FullStackWithLawrence/secure-logger/commit/2e60dbbd5922649e0dc5b0177f145d49f7b476dd)) +* need to git pull ([e173922](https://github.com/FullStackWithLawrence/secure-logger/commit/e173922d290eba66addda88f408aa0d576382214)) +* remove version bump ([7b71ae9](https://github.com/FullStackWithLawrence/secure-logger/commit/7b71ae9c484486cd124b751bc201f16cc2d627bf)) -## [0.1.9](https://github.com/lpm0073/secure-logger/compare/v0.1.8...v0.1.9) (2023-11-13) +## [0.1.9](https://github.com/FullStackWithLawrence/secure-logger/compare/v0.1.8...v0.1.9) (2023-11-13) ### Bug Fixes -* have to skip CI automated unit tests when commit __version__.py ([0e939c8](https://github.com/lpm0073/secure-logger/commit/0e939c87eb3ab0aafe6475691f1380127ea1860b)) -* refactor call to npx semantic-release ([2c7d768](https://github.com/lpm0073/secure-logger/commit/2c7d768c8875a11f68ff47700e4c8a107a98c89b)) +* have to skip CI automated unit tests when commit __version__.py ([0e939c8](https://github.com/FullStackWithLawrence/secure-logger/commit/0e939c87eb3ab0aafe6475691f1380127ea1860b)) +* refactor call to npx semantic-release ([2c7d768](https://github.com/FullStackWithLawrence/secure-logger/commit/2c7d768c8875a11f68ff47700e4c8a107a98c89b)) -## [0.1.8](https://github.com/lpm0073/secure-logger/compare/v0.1.7...v0.1.8) (2023-11-13) +## [0.1.8](https://github.com/FullStackWithLawrence/secure-logger/compare/v0.1.7...v0.1.8) (2023-11-13) ### Bug Fixes -* required upgrade to node 20.9.0 ([756ea63](https://github.com/lpm0073/secure-logger/commit/756ea6366bfe828783be17f4d581e8b4cd7f6574)) -* required upgrade to node 20.9.0 ([9bc8871](https://github.com/lpm0073/secure-logger/commit/9bc88718b3ffbfdd002d9156dcbad3db974b723f)) +* required upgrade to node 20.9.0 ([756ea63](https://github.com/FullStackWithLawrence/secure-logger/commit/756ea6366bfe828783be17f4d581e8b4cd7f6574)) +* required upgrade to node 20.9.0 ([9bc8871](https://github.com/FullStackWithLawrence/secure-logger/commit/9bc88718b3ffbfdd002d9156dcbad3db974b723f)) -## [0.1.7](https://github.com/lpm0073/secure-logger/compare/v0.1.6...v0.1.7) (2023-11-13) +## [0.1.7](https://github.com/FullStackWithLawrence/secure-logger/compare/v0.1.6...v0.1.7) (2023-11-13) ### Bug Fixes -* add missing package descriptors ([72bc5b3](https://github.com/lpm0073/secure-logger/commit/72bc5b3c296e3f5d809ecad894c8b25aa1e0e0fa)) -* correct path to python requirements ([cdc0557](https://github.com/lpm0073/secure-logger/commit/cdc05577f5b6e5c1bb46b141ff61ff00a0eca899)) -* fix calls to unit tests ([9b98d18](https://github.com/lpm0073/secure-logger/commit/9b98d18016cfe99b38298bd910831c1de3988db0)) -* fix path to secure_logger ([1d6a1d9](https://github.com/lpm0073/secure-logger/commit/1d6a1d90c233464746a85dcb0add3ba6e0f8297a)) -* move __version__.py to the root ([da0beac](https://github.com/lpm0073/secure-logger/commit/da0beac04ec3144936aa92fb5deca8b97945b439)) -* remove reference to django migrations ([e0a62be](https://github.com/lpm0073/secure-logger/commit/e0a62be13deb323f683d39134f42b203e413ff49)) +* add missing package descriptors ([72bc5b3](https://github.com/FullStackWithLawrence/secure-logger/commit/72bc5b3c296e3f5d809ecad894c8b25aa1e0e0fa)) +* correct path to python requirements ([cdc0557](https://github.com/FullStackWithLawrence/secure-logger/commit/cdc05577f5b6e5c1bb46b141ff61ff00a0eca899)) +* fix calls to unit tests ([9b98d18](https://github.com/FullStackWithLawrence/secure-logger/commit/9b98d18016cfe99b38298bd910831c1de3988db0)) +* fix path to secure_logger ([1d6a1d9](https://github.com/FullStackWithLawrence/secure-logger/commit/1d6a1d90c233464746a85dcb0add3ba6e0f8297a)) +* move __version__.py to the root ([da0beac](https://github.com/FullStackWithLawrence/secure-logger/commit/da0beac04ec3144936aa92fb5deca8b97945b439)) +* remove reference to django migrations ([e0a62be](https://github.com/FullStackWithLawrence/secure-logger/commit/e0a62be13deb323f683d39134f42b203e413ff49)) # CHANGE LOG diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index ca5d3e8..e6947b9 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -39,7 +39,7 @@ The following behaviors are considered harassment and are unacceptable within ou ## 5. Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [lpm0073@gmail.com](mailto:lpm0073@gmail.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [FullStackWithLawrence@gmail.com](mailto:FullStackWithLawrence@gmail.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. diff --git a/Makefile b/Makefile index 23cb685..c3dbd30 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,19 @@ PYTHON = python3 PIP = $(PYTHON) -m pip -.PHONY: pre-commit requirements init clean report build release-test release-prod help +.PHONY: pre-commit requirements init clean report test build release-test release-prod help # Default target executed when no arguments are given to make. all: help +init: + make clean && \ + npm install && \ + python3.11 -m venv venv && \ + source venv/bin/activate && \ + pip install --upgrade pip && \ + make requirements && \ + pre-commit install + pre-commit: pre-commit install pre-commit run --all-files @@ -17,19 +26,20 @@ requirements: pre-commit install && \ pre-commit autoupdate -init: - rm -rf venv .pytest_cache __pycache__ .pytest_cache node_modules - python3.11 -m venv venv && \ - . venv/bin/activate && \ - make requirements - +lint: + pre-commit run --all-files && \ + black . clean: + rm -rf venv .pytest_cache __pycache__ .pytest_cache node_modules && \ rm -rf build dist secure_logger.egg-info report: cloc . --exclude-ext=svg,json,zip --vcs=git +test: + cd secure_logger && pytest -v -s tests/ + python -m setup_test build: npx semantic-release --doctor --dry-run @@ -72,6 +82,7 @@ help: @echo '====================================================================' @echo 'pre-commit - install and configure pre-commit hooks' @echo 'requirements - install Python, npm and pre-commit requirements' + @echo 'lint - run black and pre-commit hooks' @echo 'init - build virtual environment and install requirements' @echo 'clean - destroy all build artifacts' @echo 'repository - runs cloc report' diff --git a/README.md b/README.md new file mode 100644 index 0000000..bafbe48 --- /dev/null +++ b/README.md @@ -0,0 +1,164 @@ +# Secure Logger + +[![FullStackWithLawrence](https://a11ybadges.com/badge?text=FullStackWithLawrence&badgeColor=orange&logo=youtube&logoColor=282828)](https://www.youtube.com/@FullStackWithLawrence)
+[![Tests](https://github.com/FullStackWithLawrence/secure-logger/actions/workflows/runTests.yml/badge.svg)](https://github.com/FullStackWithLawrence/secure-logger/actions) +[![Release Notes](https://img.shields.io/github/release/FullStackWithLawrence/openai-embeddings)](https://github.com/FullStackWithLawrence/openai-embeddings/releases) +![Releasae](https://img.shields.io/github/actions/workflow/status/FullStackWithLawrence/openai-embeddings/release.yml?branch=main) +[![Source +code](https://img.shields.io/static/v1?logo=github&label=Git&style=flat-square&color=brightgreen&message=Source%20code)](https://github.com/FullStackWithLawrence/secure-logger) +[![PyPI +releases](https://img.shields.io/pypi/v/secure-logger?logo=python&logoColor=white)](https://pypi.org/project/secure-logger) +[![License: AGPL +v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) +[![hack.d Lawrence +McDaniel](https://img.shields.io/badge/hack.d-Lawrence%20McDaniel-orange.svg)](https://lawrencemcdaniel.com) + +A Python decorator to generate redacted and nicely formatted log +entries. Works on all callables: class, class methods, Python module +functions. Recursively redacts Python dictionary key values based on a +customizable list of case-insensitive keys. Prevents your sensitive +application data like cloud provider key-pairs from leaking into your +application logs. + +## Usage + +### As a decorator + +``` python +from secure_logger.decorators import secure_logger + +class Foo(object): + + @secure_logger() + def bar(self, dict_data, list_data): + pass + +# call your method, passing some sensitive data +dict_data = { + 'not_a_sensitive_key': 'you-can-see-me', + 'aws-access-key_id': conf.AWS_ACCESS_KEY_ID, + 'aws-secret-access-key': conf.AWS_SECRET_ACCESS_KEY +} +list_data = ['foo', 'bar'] +foo = Foo() +foo.bar(dict_data=dict_data, list_data=list_data) +``` + +Log output: + +``` log +INFO:secure_logger: __main__.Foo().bar() keyword args: { + "dict_data": { + "not_a_sensitive_key": "you-can-see-me", + "aws-access-key-id": "*** -- secure_logger() -- ***", + "aws-secret-access-key": "*** -- secure_logger() -- ***" + }, + "list_data": [ + "foo", + "bar" + ] +} +``` + +### As library functions + +``` python +from secure_logger.masked_dict import masked_dict, masked_dict2str + +dict_data = { + 'not_a_sensitive_key': 'you-can-see-me', + 'aws-access-key_id': conf.AWS_ACCESS_KEY_ID, + 'aws-secret-access-key': conf.AWS_SECRET_ACCESS_KEY +} +print(masked_dict2str(dict_data)) +``` + +Output: + +``` bash +{ + "not_a_sensitive_key": "you-can-see-me", + "aws-access-key-id": "*** -- secure_logger() -- ***", + "aws-secret-access-key": "*** -- secure_logger() -- ***" +} +``` + +## Installation + +``` bash +pip install secure-logger +``` + +## Configuration + +secure_logger accepts optional parameters. + +- sensitive_keys: a Python list of dictionary keys. Not case + sensitive. +- message: a string value that will replace the sensitive key values +- indent: number of characters to indent JSON string output when + logging output + +``` python +class MyClass(): + + @secure_logger(sensitive_keys=["password", "token", "crown_jewels"], message="***", indent=4) + def another_def(self): + pass +``` + +## Configuration Defaults + +``` python +DEFAULT_REDACTION_MESSAGE = "*** -- secure_logger() -- ***" +DEFAULT_INDENT = 4 +DEFAULT_SENSITIVE_KEYS = [ + "password", + "token", + "client_id", + "client_secret", + "Authorization", + "secret", + "access_key_id", + "secret_access_key", + "access-key-id", + "secret-access-key", + "aws_access_key_id", + "aws_secret_access_key", + "aws-access-key-id", + "aws-secret-access-key", +] +``` + +### Contributing + +Pull requests are welcome, and you can also contact [Lawrence +McDaniel](https://lawrencemcdaniel.com/contact) directly. + +### Getting Started With Local development + +- Use the same virtual environment that you use for edx-platform +- Ensure that your Python interpreter to 3.11 +- install black: +- install flake8: +- install flake8-coding: + +``` bash +# Run these from within your edx-platform virtual environment +python3 -m venv venv +source venv/bin/activate + +pip install -r requirements/local.txt +pip install pre-commit black flake8 +pre-commit install +``` + +#### Local development good practices + +- run `black` on modified code before committing. +- run + `flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics` +- run + `flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics` +- run `pre-commit run --all-files` before pushing. see: + diff --git a/README.rst b/README.rst deleted file mode 100644 index 00df4a3..0000000 --- a/README.rst +++ /dev/null @@ -1,174 +0,0 @@ -Secure Logger -============= - -|Tests| |Source code| |PyPI releases| |License: AGPL v3| |hack.d -Lawrence McDaniel| - -A Python decorator to generate redacted and nicely formatted log -entries. Works on all callables: class, class methods, Python module -functions. Recursively redacts Python dictionary key values based on a -customizable list of case-insensitive keys. Prevents your sensitive -application data like cloud provider key-pairs from leaking into your -application logs. - -Usage ------ - -As a decorator -~~~~~~~~~~~~~~ - -.. code-block:: python - - from secure_logger.decorators import secure_logger - - class Foo(object): - - @secure_logger() - def bar(self, dict_data, list_data): - pass - - # call your method, passing some sensitive data - dict_data = { - 'not_a_sensitive_key': 'you-can-see-me', - 'aws-access-key_id': conf.AWS_ACCESS_KEY_ID, - 'aws-secret-access-key': conf.AWS_SECRET_ACCESS_KEY - } - list_data = ['foo', 'bar'] - foo = Foo() - foo.bar(dict_data=dict_data, list_data=list_data) - -Log output: - -.. code:: log - - INFO:secure_logger: __main__.Foo().bar() keyword args: { - "dict_data": { - "not_a_sensitive_key": "you-can-see-me", - "aws-access-key-id": "*** -- secure_logger() -- ***", - "aws-secret-access-key": "*** -- secure_logger() -- ***" - }, - "list_data": [ - "foo", - "bar" - ] - } - -As library functions -~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - from secure_logger.masked_dict import masked_dict, masked_dict2str - - dict_data = { - 'not_a_sensitive_key': 'you-can-see-me', - 'aws-access-key_id': conf.AWS_ACCESS_KEY_ID, - 'aws-secret-access-key': conf.AWS_SECRET_ACCESS_KEY - } - print(masked_dict2str(dict_data)) - -Output: - -.. code:: bash - - { - "not_a_sensitive_key": "you-can-see-me", - "aws-access-key-id": "*** -- secure_logger() -- ***", - "aws-secret-access-key": "*** -- secure_logger() -- ***" - } - -Installation ------------- - -.. code:: bash - - pip install secure-logger - -Configuration -------------- - -secure_logger accepts optional parameters. - -- sensitive_keys: a Python list of dictionary keys. Not case sensitive. -- message: a string value that will replace the sensitive key values -- indent: number of characters to indent JSON string output when - logging output - -.. code-block:: python - - class MyClass(): - - @secure_logger(sensitive_keys=["password", "token", "crown_jewels"], message="***", indent=4) - def another_def(self): - pass - -Configuration Defaults ----------------------- - -.. code-block:: python - - DEFAULT_REDACTION_MESSAGE = "*** -- secure_logger() -- ***" - DEFAULT_INDENT = 4 - DEFAULT_SENSITIVE_KEYS = [ - "password", - "token", - "client_id", - "client_secret", - "Authorization", - "secret", - "access_key_id", - "secret_access_key", - "access-key-id", - "secret-access-key", - "aws_access_key_id", - "aws_secret_access_key", - "aws-access-key-id", - "aws-secret-access-key", - ] - -Contributing -~~~~~~~~~~~~ - -Pull requests are welcome, and you can also contact `Lawrence -McDaniel `__ directly. - -Getting Started With Local development -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Use the same virtual environment that you use for edx-platform -- Ensure that your Python interpreter to 3.11 -- install black: https://pypi.org/project/black/ -- install flake8: https://flake8.pycqa.org/en/latest/ -- install flake8-coding: https://pypi.org/project/flake8-coding/ - -.. code:: bash - - # Run these from within your edx-platform virtual environment - python3 -m venv venv - source venv/bin/activate - - pip install -r requirements/local.txt - pip install pre-commit black flake8 - pre-commit install - -Local development good practices -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- run ``black`` on modified code before committing. -- run - ``flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics`` -- run - ``flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics`` -- run ``pre-commit run --all-files`` before pushing. see: - https://pre-commit.com/ - -.. |Tests| image:: https://github.com/lpm0073/secure-logger/actions/workflows/tests.yml/badge.svg - :target: https://github.com/lpm0073/secure-logger/actions -.. |Source code| image:: https://img.shields.io/static/v1?logo=github&label=Git&style=flat-square&color=brightgreen&message=Source%20code - :target: https://github.com/lpm0073/secure-logger -.. |PyPI releases| image:: https://img.shields.io/pypi/v/secure-logger?logo=python&logoColor=white - :target: https://pypi.org/project/secure-logger -.. |License: AGPL v3| image:: https://img.shields.io/badge/License-AGPL_v3-blue.svg - :target: https://www.gnu.org/licenses/agpl-3.0 -.. |hack.d Lawrence McDaniel| image:: https://img.shields.io/badge/hack.d-Lawrence%20McDaniel-orange.svg - :target: https://lawrencemcdaniel.com diff --git a/SECURITY.md b/SECURITY.md index 3eb90e9..101ea9e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -11,7 +11,7 @@ Only the latest version of this project is currently being supported with securi ## Reporting a Vulnerability -If you discover a security vulnerability within this project, please send an email to [lpm0073@gmail.com](mailto:lpm0073@gmail.com). All security vulnerabilities will be promptly addressed. +If you discover a security vulnerability within this project, please send an email to [FullStackWithLawrence@gmail.com](mailto:FullStackWithLawrence@gmail.com). All security vulnerabilities will be promptly addressed. Please do not publicly disclose the issue until it has been addressed by the team. diff --git a/__version__.py b/__version__.py index b04cffb..718bd48 100644 --- a/__version__.py +++ b/__version__.py @@ -1 +1,2 @@ -__version__ = '0.1.17' +# -*- coding: utf-8 -*- +__version__ = "0.1.17" diff --git a/codespell.txt b/codespell.txt new file mode 100644 index 0000000..e3cd622 --- /dev/null +++ b/codespell.txt @@ -0,0 +1 @@ +OCE diff --git a/package copy.json b/package copy.json new file mode 100644 index 0000000..c2ac7b2 --- /dev/null +++ b/package copy.json @@ -0,0 +1,15 @@ +{ + "private": true, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "devDependencies": { + "@semantic-release/changelog": "^6.0.3", + "@semantic-release/commit-analyzer": "^11.1.0", + "@semantic-release/git": "^10.0.1", + "@semantic-release/github": "^9.2.3", + "@semantic-release/release-notes-generator": "^12.1.0", + "prettier": "^3.1.0", + "typescript": "^5.2.2" + } +} diff --git a/pyproject.toml b/pyproject.toml index 775be13..2b766c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,13 @@ +[build-system] +requires = ["flake8", "gitlint", "bump2version"] + +[tool.isort] +profile = "black" +lines_after_imports = 2 + [tool.black] line-length = 120 +target-version = ['py311'] include = '\.pyi?$' exclude = ''' /( @@ -8,13 +16,23 @@ exclude = ''' | \.mypy_cache | \.tox | \.venv - | _build + | venv + | node_modules + | build | buck-out | build | dist )/ ''' -[build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta:__legacy__" +[tool.flake8] +ignore = "D205,D413,D400,D401" +max-line-length =120 +max-complexity = 10 +exclude = "venv" +extend-exclude = "*__init__.py,*__version__.py,venv" +select = "C101" + +[tool.codespell] +skip = '*.svg,models/prompt_templates.py' +ignore-words = 'codespell.txt' diff --git a/requirements/local.txt b/requirements/local.txt index cd0197b..6e45234 100644 --- a/requirements/local.txt +++ b/requirements/local.txt @@ -1,3 +1,18 @@ +# dev and test +# ------------ +pytest==7.4.3 +pytest_mock==3.12.0 + +# Code linters, formatters, and security scanners +# ------------ black==23.11.0 flake8==6.1.0 +flake8-coding==1.3.2 pre-commit==3.5.0 +isort==5.12.0 +mypy==1.7.1 +pylint==3.0.2 +bandit==1.7.5 +pydocstringformatter==0.7.3 +tox==4.11.4 +codespell==2.2.6 diff --git a/run_pylint.sh b/run_pylint.sh new file mode 100755 index 0000000..bbccb2c --- /dev/null +++ b/run_pylint.sh @@ -0,0 +1,3 @@ +#!/bin/bash +# Called from pre-commit. Run pylint on all python files in the current directory +python -m pylint "$@" diff --git a/secure_logger/decorators.py b/secure_logger/decorators.py index 61546d6..fd8ab8d 100644 --- a/secure_logger/decorators.py +++ b/secure_logger/decorators.py @@ -2,11 +2,17 @@ """Python Secure Logger.""" # python stuff import inspect -from functools import wraps import logging +from functools import wraps # our stuff -from .masked_dict import masked_dict2str, DEFAULT_SENSITIVE_KEYS, DEFAULT_REDACTION_MESSAGE, DEFAULT_INDENT +from .masked_dict import ( + DEFAULT_INDENT, + DEFAULT_REDACTION_MESSAGE, + DEFAULT_SENSITIVE_KEYS, + masked_dict2str, +) + # module initializations logger = logging.getLogger(__name__) @@ -71,11 +77,10 @@ def wrapper(*args, **kwargs): ) logger.info( - "secure_logger: {name_spec} {args} {kwargs}".format( - name_spec=name_spec, - args=positional_args if len(positional_args) > 0 else "", - kwargs=kwargs_dict_repr, - ) + "secure_logger: %s %s %s", + name_spec, + positional_args if positional_args else "", + kwargs_dict_repr, ) return func(*args, **kwargs) diff --git a/secure_logger/masked_dict.py b/secure_logger/masked_dict.py index 1e8e65f..15593e6 100644 --- a/secure_logger/masked_dict.py +++ b/secure_logger/masked_dict.py @@ -5,6 +5,7 @@ import json from unittest.mock import MagicMock + # our stuff DEFAULT_SENSITIVE_KEYS = [ "password", @@ -29,16 +30,16 @@ class _JSONEncoder(json.JSONEncoder): """encode json object for serialization.""" - def default(self, obj): + def default(self, o): """Handle unit test, unicode, and anything else that might throw a wrench in things.""" - if isinstance(obj, bytes): - return str(obj, encoding="utf-8") - if isinstance(obj, MagicMock): + if isinstance(o, bytes): + return str(o, encoding="utf-8") + if isinstance(o, MagicMock): return "" try: - return json.JSONEncoder.default(self, obj) - except Exception: # noqa: B902 - # obj probably is not json serializable. + return json.JSONEncoder.default(self, o) + except Exception: # pylint: disable=broad-except + # o probably is not json serializable. return "" @@ -51,21 +52,21 @@ def masked_dict( Masks the value of specified key. obj: a dict or a string representation of a dict, or None """ - if type(source_dict) == str: + if isinstance(source_dict, str): source_dict = json.loads(source_dict) - if type(source_dict) != dict: + if not isinstance(source_dict, dict): raise TypeError("source_dict must be a dict or a json serializable string") recursed_dict = {} for key in source_dict: value = source_dict[key] - if type(value) == dict: + if isinstance(value, dict): value = masked_dict(source_dict=value, sensitive_keys=sensitive_keys, message=message) recursed_dict[key] = value for lower_case_sensitive_key in [x.lower() for x in sensitive_keys]: - if lower_case_sensitive_key in [x.lower() for x in recursed_dict.keys()]: + if lower_case_sensitive_key in [x.lower() for x in recursed_dict]: for original_key in recursed_dict: if original_key.lower() == lower_case_sensitive_key: recursed_dict[original_key] = message diff --git a/secure_logger/tests/tests.py b/secure_logger/tests/tests.py index 3207b6a..33c80fc 100644 --- a/secure_logger/tests/tests.py +++ b/secure_logger/tests/tests.py @@ -1,19 +1,15 @@ # -*- coding: utf-8 -*- -# flake8: noqa -""" -Simple test bank. - -Test the three use cases that we care about. -""" -import unittest -import logging +# pylint: disable=too-few-public-methods +"""Simple test bank.""" import json +import logging +import unittest from secure_logger.decorators import secure_logger from secure_logger.masked_dict import ( + DEFAULT_REDACTION_MESSAGE, masked_dict, masked_dict2str, - DEFAULT_REDACTION_MESSAGE, ) @@ -21,6 +17,8 @@ # TEST BANK ############################################################################### class TestMaskedDict(unittest.TestCase): + """Test the masked_dict function.""" + test_dict = { "insensitive_key": "you-can-see-me", "aws_access_key_id": "i-am-hidden", @@ -33,16 +31,20 @@ class TestMaskedDict(unittest.TestCase): } def test_masked_dict(self): + """Test the masked_dict function.""" md = masked_dict(self.test_dict) self.assertDictEqual(md, self.expected_dict) def test_masked_dict2str(self): + """Test the masked_dict2str function.""" md2s = masked_dict2str(self.test_dict) md2s_to_json = json.loads(md2s) self.assertDictEqual(md2s_to_json, self.expected_dict) class TestMaskedDictCaseSensitivity(unittest.TestCase): + """Test the masked_dict function with case sensitivity.""" + test_dict = { "insensitive_key": "you-can-see-me", "AWs_AcCEss_KeY_iD": "i-am-very-hidden", @@ -55,22 +57,27 @@ class TestMaskedDictCaseSensitivity(unittest.TestCase): } def test_masked_dict(self): + """Test the masked_dict function.""" md = masked_dict(self.test_dict) self.assertDictEqual(md, self.expected_dict) def test_masked_dict2str(self): + """Test the masked_dict2str function.""" md2s = masked_dict2str(self.test_dict) md2s_to_json = json.loads(md2s) self.assertDictEqual(md2s_to_json, self.expected_dict) class TestCustomParams(unittest.TestCase): + """Test the masked_dict function with custom parameters.""" + visible_value = "i should be visible" custom_keys = ["foo", "bar"] custom_message = "--REDACTED--" test_dict = {"foo": "i should be hidden", "bar": "me too", "visible_key": visible_value} def test_custom_keys(self): + """Test the masked_dict function with custom keys.""" expected_result = { "foo": DEFAULT_REDACTION_MESSAGE, "bar": DEFAULT_REDACTION_MESSAGE, @@ -80,24 +87,28 @@ def test_custom_keys(self): self.assertDictEqual(masked_test_dict, expected_result) def test_custom_keys_and_message(self): + """Test the masked_dict function with custom keys and message.""" expected_result = {"foo": self.custom_message, "bar": self.custom_message, "visible_key": self.visible_value} masked_test_dict = masked_dict(self.test_dict, self.custom_keys, self.custom_message) self.assertDictEqual(masked_test_dict, expected_result) class TestModuleDefDecorator(unittest.TestCase): + """Test module function logging.""" + @secure_logger() def mock_decorated_def(self, msg): """Test 1: a simple module function.""" - pass def test_decorator_output(self): + """Test 1: a simple module function.""" hello_world = json.dumps(["'hello world'"]) hello_world = "'hello world'" + # noqa: C0301 expected_output = ( - "INFO:secure_logger.decorators:secure_logger: tests.mock_decorated_def() ['', " - + hello_world + "INFO:secure_logger.decorators:secure_logger: tests.mock_decorated_def() " + "['', " + hello_world ) with self.assertLogs(level=logging.DEBUG) as cm: self.mock_decorated_def("hello world") @@ -106,18 +117,18 @@ def test_decorator_output(self): class TestClassMethodDecorator(unittest.TestCase): - class MockClass(object): + """Test class method logging.""" + + class MockClass: """Test class method logging.""" @secure_logger() def decorator_with_defaults(self, test_dict, test_list): """Test class input parameter as objects.""" - pass @secure_logger(sensitive_keys=["aws_secret_access_key"], indent=10, message="-- Forbidden! --") def decorator_with_custom_params(self, test_dict, test_list): """Test class input parameter as objects.""" - pass test_dict = { "insensitive_key": "you-can-see-me", @@ -128,7 +139,11 @@ def decorator_with_custom_params(self, test_dict, test_list): mock_class = MockClass() def test_class_method_with_default_params(self): - expected_output = "INFO:secure_logger.decorators:secure_logger: tests.decorator_with_defaults() [' str: - """Stringify the README.""" - with io.open(os.path.join(HERE, "README.rst"), "rt", encoding="utf8") as f: - readme = f.read() - # Replace img src for publication on pypi - return readme.replace( - "./doc/", - "https://github.com/lpm0073/secure-logger/raw/main/doc/", - ) - - -def load_about() -> Dict[str, str]: - """Stringify the __about__ module.""" - about: Dict[str, str] = {} - with io.open(os.path.join(HERE, "__about__.py"), "rt", encoding="utf-8") as f: - exec(f.read(), about) # pylint: disable=exec-used - return about - - -CHANGELOG = open(os.path.join(os.path.dirname(__file__), "CHANGELOG.md")).read() -ABOUT = load_about() setup( name="secure-logger", @@ -84,17 +13,17 @@ def load_about() -> Dict[str, str]: long_description=load_readme(), long_description_content_type="text/x-rst", author="Lawrence McDaniel", - author_email="lpm0073@gmail.com", + author_email="FullStackWithLawrence@gmail.com", maintainer="Lawrence McDaniel", - maintainer_email="lpm0073@gmail.com", - url="https://github.com/lpm0073/secure-logger", + maintainer_email="FullStackWithLawrence@gmail.com", + url="https://github.com/FullStackWithLawrence/secure-logger", license="AGPLv3", license_files=("LICENSE.txt",), platforms=["any"], packages=find_packages(), - package_data={"": ["*.html"]}, # include any Mako templates found in this repo. - include_package_data=True, - cmdclass=cmdclasses, + package_data={ + "secure_logger": ["*.md"], + }, python_requires=">=3.6", install_requires=[], extras_require={}, @@ -117,11 +46,11 @@ def load_about() -> Dict[str, str]: ], keywords="logging, security, redaction", project_urls={ - "Source": "https://github.com/lpm0073/secure-logger", + "Source": "https://github.com/FullStackWithLawrence/secure-logger", "Documentation": "https://pypi.org/project/secure-logger/", - "Changelog": "https://github.com/lpm0073/secure-logger/blob/main/CHANGELOG.md", - "Security": "https://github.com/lpm0073/secure-logger/blob/main/SECURITY.md", - "Code of Conduct": "https://github.com/lpm0073/secure-logger/blob/main/CODE_OF_CONDUCT.md", - "Tracker": "https://github.com/lpm0073/secure-logger/issues", + "Changelog": "https://github.com/FullStackWithLawrence/secure-logger/blob/main/CHANGELOG.md", + "Security": "https://github.com/FullStackWithLawrence/secure-logger/blob/main/SECURITY.md", + "Code of Conduct": "https://github.com/FullStackWithLawrence/secure-logger/blob/main/CODE_OF_CONDUCT.md", + "Tracker": "https://github.com/FullStackWithLawrence/secure-logger/issues", }, ) diff --git a/setup_test.py b/setup_test.py index 06c7d87..1a5a8b1 100644 --- a/setup_test.py +++ b/setup_test.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +"""Test setup.py.""" import subprocess import unittest @@ -8,7 +9,7 @@ class TestSetup(unittest.TestCase): def test_setup_syntax(self): """Test setup.py syntax.""" - result = subprocess.run(["python", "setup.py", "check"], capture_output=True, text=True) + result = subprocess.run(["python", "setup.py", "check"], capture_output=True, text=True, check=False) assert result.returncode == 0, f"setup.py failed with output:\n{result.stdout}\n{result.stderr}" assert not result.stderr, "Expected no error output" diff --git a/setup_utils.py b/setup_utils.py index ab704ac..e07c155 100644 --- a/setup_utils.py +++ b/setup_utils.py @@ -1,23 +1,29 @@ # -*- coding: utf-8 -*- +# pylint: disable=duplicate-code +# pylint: disable=duplicate-code """Lawrence McDaniel https://lawrencemcdaniel.com.""" -# pylint: disable=open-builtin +import importlib.util import io import os import re from typing import Dict + +MODULE_NAME = "models" HERE = os.path.abspath(os.path.dirname(__file__)) +PROJECT_ROOT = os.path.abspath(os.path.join(HERE, MODULE_NAME)) # allow setup.py to be run from any path os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir))) def load_version() -> Dict[str, str]: - """Stringify the __about__ module.""" - version: Dict[str, str] = {} - with io.open(os.path.join(HERE, "__version__.py"), "rt", encoding="utf-8") as f: - exec(f.read(), version) # pylint: disable=exec-used - return version + """Stringify the __version__ module.""" + version_file_path = os.path.join(PROJECT_ROOT, "__version__.py") + spec = importlib.util.spec_from_file_location("__version__", version_file_path) + version_module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(version_module) + return version_module.__dict__ VERSION = load_version() @@ -44,3 +50,25 @@ def get_semantic_version() -> str: version = VERSION["__version__"] version = re.sub(r"-next\.\d+", "", version) return re.sub(r"-next-major\.\d+", "", version) + + +def load_readme() -> str: + """Stringify the README.""" + with io.open(os.path.join(HERE, "README.rst"), "rt", encoding="utf8") as f: + readme = f.read() + # Replace img src for publication on pypi + return readme.replace( + "./doc/", + "https://github.com/lpm0073/secure-logger/raw/main/doc/", + ) + + +def load_about() -> Dict[str, str]: + """Stringify the __about__ module.""" + about: Dict[str, str] = {} + about_path = os.path.join(HERE, "__about__.py") + spec = importlib.util.spec_from_file_location("__about__", about_path) + about_module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(about_module) + about = {attr: getattr(about_module, attr) for attr in dir(about_module) if not attr.startswith("_")} + return about diff --git a/tox.ini b/tox.ini index bad1bc7..c4b98dc 100644 --- a/tox.ini +++ b/tox.ini @@ -4,19 +4,21 @@ envlist = py3.11,flake8 skip_missing_interpreters = true +[tool.isort] +profile = "black" +skip =venv,node_modules + [gh-actions] python = - 3.11: gitlint,py311,flake8 + 3.8: gitlint,py38,flake8 + 3.9: gitlint,py39,flake8 + 3.10: gitlint,py310,flake8 + 3.11: gitlint,py311,flake8,mypy,black,pylint [testenv] -deps = -rrequirements/local.txt +deps = -rrequirements.txt commands = pytest -[flake8] -ignore = D100,D205,D400,D401,D403,D413 -max-line-length =120 -max-complexity = 10 - [testenv:flake8] skip_install = True deps = flake8 @@ -39,3 +41,8 @@ passenv = GPG_AGENT_INFO deps = bump2version commands = bump2version {posargs} + +[testenv:pylint] +deps = pylint +commands = + pylint . --disable=W0102 From a57d6a42b6558edff3eb15441f439df859cc67e6 Mon Sep 17 00:00:00 2001 From: lpm0073 Date: Tue, 5 Dec 2023 10:45:28 -0600 Subject: [PATCH 3/3] refactor: cleanup file locations and unit test details --- Makefile | 4 +++- __init__.py | 6 ------ __about__.py => secure_logger/__about__.py | 0 secure_logger/__init__.py | 6 ------ .../__version__.py | 0 secure_logger/tests/__init__.py | 2 -- secure_logger/tests/tests.py | 20 ++++++++++++------- setup_utils.py | 6 +++--- 8 files changed, 19 insertions(+), 25 deletions(-) delete mode 100644 __init__.py rename __about__.py => secure_logger/__about__.py (100%) rename __version__.py => secure_logger/__version__.py (100%) diff --git a/Makefile b/Makefile index c3dbd30..4203db5 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ report: cloc . --exclude-ext=svg,json,zip --vcs=git test: - cd secure_logger && pytest -v -s tests/ + cd secure_logger && python -m unittest tests/tests.py python -m setup_test build: @@ -55,6 +55,8 @@ build: $(PYTHON) -m pip install --upgrade twine twine check dist/* +release: + git commit -m "fix: force a new release" --allow-empty && git push # ------------------------------------------------------------------------- # upload to PyPi Test diff --git a/__init__.py b/__init__.py deleted file mode 100644 index 9a01900..0000000 --- a/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Lawrence McDaniel https://lawrencemcdaniel.com. - -Python Secure Logger -""" diff --git a/__about__.py b/secure_logger/__about__.py similarity index 100% rename from __about__.py rename to secure_logger/__about__.py diff --git a/secure_logger/__init__.py b/secure_logger/__init__.py index 9a01900..e69de29 100644 --- a/secure_logger/__init__.py +++ b/secure_logger/__init__.py @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Lawrence McDaniel https://lawrencemcdaniel.com. - -Python Secure Logger -""" diff --git a/__version__.py b/secure_logger/__version__.py similarity index 100% rename from __version__.py rename to secure_logger/__version__.py diff --git a/secure_logger/tests/__init__.py b/secure_logger/tests/__init__.py index 08eff90..e69de29 100644 --- a/secure_logger/tests/__init__.py +++ b/secure_logger/tests/__init__.py @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -"""This is the initialization file for the Python package tests.""" diff --git a/secure_logger/tests/tests.py b/secure_logger/tests/tests.py index 33c80fc..f875482 100644 --- a/secure_logger/tests/tests.py +++ b/secure_logger/tests/tests.py @@ -3,10 +3,16 @@ """Simple test bank.""" import json import logging +import sys import unittest -from secure_logger.decorators import secure_logger -from secure_logger.masked_dict import ( + +sys.path.append("../") # noqa: E402 + +from secure_logger.decorators import ( # noqa: E402, pylint: disable=wrong-import-position + secure_logger, +) +from secure_logger.masked_dict import ( # noqa: E402, pylint: disable=wrong-import-position DEFAULT_REDACTION_MESSAGE, masked_dict, masked_dict2str, @@ -107,8 +113,8 @@ def test_decorator_output(self): # noqa: C0301 expected_output = ( - "INFO:secure_logger.decorators:secure_logger: tests.mock_decorated_def() " - "['', " + hello_world + "INFO:secure_logger.decorators:secure_logger: tests.tests.mock_decorated_def() " + "['', " + hello_world ) with self.assertLogs(level=logging.DEBUG) as cm: self.mock_decorated_def("hello world") @@ -141,8 +147,8 @@ def decorator_with_custom_params(self, test_dict, test_list): def test_class_method_with_default_params(self): """Test class method with default parameters.""" expected_output = ( - "INFO:secure_logger.decorators:secure_logger: tests.decorator_with_defaults() " - "[' str: def load_readme() -> str: """Stringify the README.""" - with io.open(os.path.join(HERE, "README.rst"), "rt", encoding="utf8") as f: + with io.open(os.path.join(HERE, "README.md"), "rt", encoding="utf8") as f: readme = f.read() # Replace img src for publication on pypi return readme.replace( @@ -66,7 +66,7 @@ def load_readme() -> str: def load_about() -> Dict[str, str]: """Stringify the __about__ module.""" about: Dict[str, str] = {} - about_path = os.path.join(HERE, "__about__.py") + about_path = os.path.join(PROJECT_ROOT, "__about__.py") spec = importlib.util.spec_from_file_location("__about__", about_path) about_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(about_module)