diff --git a/.envrc b/.envrc index 0e93f4f..a11e651 100644 --- a/.envrc +++ b/.envrc @@ -1,5 +1,10 @@ #!/usr/local/bin/env bash +if [ -f ~/.gnupg/github/sentry_dsn.gpg ]; then + SENTRY_DSN="$(gpg -d -q ~/.gnupg/github/sentry_dsn.gpg)" + export SENTRY_DSN +fi + PIPENV_VENV_IN_PROJECT=1 export PIPENV_VENV_IN_PROJECT diff --git a/.github/workflows/.bandit.txt b/.github/workflows/.bandit.txt new file mode 100644 index 0000000..65e313e --- /dev/null +++ b/.github/workflows/.bandit.txt @@ -0,0 +1,84 @@ +### +# ```{rubric} Bandit +# ``` +# --- +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# +# Bandit is a security linter designed to find common security issues in Python code. +# This action will run Bandit on your codebase. +# The results of the scan will be found under the Security tab of your repository. +# +# [bandit-scan](https://github.com/marketplace/actions/bandit-scan) is ISC +# licensed, by abirismyname +# [bandit](https://pypi.org/project/bandit/) is Apache v2.0 licensed, by PyCQA +# +# ```{literalinclude} .github/workflows/bandit.yml +# :language: yaml +# :start-at: "name: Bandit\n" +# :end-before: "###\n" +# ``` +name: Bandit +permissions: + contents: read +on: + push: + branches: [ "main" ] + pull_request: + ### + # The branches below must be a subset of the branches above + branches: [ "main" ] + schedule: + - cron: '32 4 * * 4' +### +# ```{rubric} Bandit Jobs +# ``` +# --- +# Define the jobs necessary for a useful bandit run. +# +# ```{literalinclude} .github/workflows/bandit.yml +# :language: yaml +# :start-at: "jobs:\n" +# ``` +jobs: + bandit: + permissions: + ### + # for actions/checkout to fetch code + contents: read + ### + # for github/codeql-action/upload-sarif to upload SARIF results + security-events: write + ### + # only required for a private repository by + # github/codeql-action/upload-sarif to get the Action run status + actions: read + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Bandit Scan + uses: shundor/python-bandit-scan@main + ### + # optional arguments + with: + ### + # exit with 0, even with results found + exit_zero: true # optional, default is DEFAULT + ### + # File or directory to run bandit on + # path: # optional, default is . + # Report only issues of a given severity level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything) + # level: # optional, default is UNDEFINED + # Report only issues of a given confidence level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything) + # confidence: # optional, default is UNDEFINED + # comma-separated list of paths (glob patterns supported) to exclude from scan (note that these are in addition to the excluded paths provided in the config file) (default: .svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg) + # excluded_paths: # optional, default is DEFAULT + # comma-separated list of test IDs to skip + # skips: # optional, default is DEFAULT + # path to a .bandit file that supplies command line arguments + # ini_path: # optional, default is DEFAULT + # Github token of the repository (automatically created by Github) + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information. + diff --git a/.github/workflows/codeql.yml b/.github/workflows/.codeql.txt similarity index 100% rename from .github/workflows/codeql.yml rename to .github/workflows/.codeql.txt diff --git a/.github/workflows/.coveralls.txt b/.github/workflows/.coveralls.txt new file mode 100644 index 0000000..3b16c53 --- /dev/null +++ b/.github/workflows/.coveralls.txt @@ -0,0 +1,42 @@ +on: ["push", "pull_request"] +name: Test Coveralls +jobs: + build: + name: Build + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + steps: + - uses: actions/checkout@main + - name: Setup Python + uses: actions/setup-python@main + with: + python-version: ${{ matrix.python-version }} + - name: git config + run: | + git config user.username edwardtheharris + git config user.name 'Xander Harris' + git config user.email 'xandertheharris@gmail.com' + git checkout -b 123-feature-branch-test + - name: Install Dependencies + run: | + pip3 install -U pip pipenv + pipenv requirements --dev > reqs + pip3 install -r reqs + pytest --cov + - name: Coveralls + uses: coverallsapp/github-action@v2 + with: + parallel: true + flag-name: run-${{ matrix.python-version }} + + finish: + needs: build + runs-on: ubuntu-latest + steps: + - name: Close parallel build + uses: coverallsapp/github-action@v1 + with: + parallel-finished: true + carryforward: "run-3.8,run-3.9,run-3.10,run-3.11,run-3.12" diff --git a/.github/workflows/.ossar.txt b/.github/workflows/.ossar.txt new file mode 100644 index 0000000..f17a701 --- /dev/null +++ b/.github/workflows/.ossar.txt @@ -0,0 +1,87 @@ +### +# ```{rubric} OSSAR +# ``` +# --- +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# +# This workflow integrates a collection of open source static analysis tools +# with GitHub code scanning. For documentation, or to provide feedback, visit +# https://github.com/github/ossar-action +# +# ```{literalinclude} .github/workflows/ossar.yml +# :language: yaml +# :start-at: "name: OSSAR\n" +# :end-before: "###\n" +# ``` +name: OSSAR +permissions: + contents: read +on: + push: + branches: [ "main" ] + pull_request: + ### + # The branches below must be a subset of the branches above + branches: [ "main" ] + schedule: + - cron: '43 10 * * 4' +### +# ```{rubric} OSSAR Jobs +# ``` +# --- +# Define the jobs necessary for a useful ossar run. +# +# ```{literalinclude} .github/workflows/ossar.yml +# :language: yaml +# :start-at: "jobs:\n" +# ``` +jobs: + OSSAR-Scan: + ### + # OSSAR runs on windows-latest. + # ubuntu-latest and macos-latest support coming soon + permissions: + ### + # for actions/checkout to fetch code + contents: read + ### + # for github/codeql-action/upload-sarif to upload SARIF results + security-events: write + ### + # only required for a private repository by + # github/codeql-action/upload-sarif to get the Action run status + actions: read + runs-on: windows-latest + steps: + - name: Checkout repository + uses: actions/checkout@main + ### + # Ensure a compatible version of dotnet is installed. + # The [Microsoft Security Code Analysis CLI](https://aka.ms/mscadocs) + # is built with dotnet v3.1.201. + # A version greater than or equal to v3.1.201 of dotnet must be installed + # on the agent in order to run this action. + # GitHub hosted runners already have a compatible version of dotnet + # installed and this step may be skipped. + # For self-hosted runners, ensure dotnet version 3.1.201 or later is + # installed by including this action: + # ```{code-block} yaml + # - name: Install .NET + # uses: actions/setup-dotnet@v2 + # with: + # dotnet-version: '3.1.x' + # ``` + # + # Run open source static analysis tools + - name: Run OSSAR + uses: github/ossar-action@main + id: ossar + ### + # Upload results to the Security tab + - name: Upload OSSAR results + uses: github/codeql-action/upload-sarif@main + with: + sarif_file: ${{ steps.ossar.outputs.sarifFile }} diff --git a/.github/workflows/python-app.yml b/.github/workflows/.python-app.txt similarity index 100% rename from .github/workflows/python-app.yml rename to .github/workflows/.python-app.txt diff --git a/.github/workflows/python-publish.yml b/.github/workflows/.python-publish.txt similarity index 100% rename from .github/workflows/python-publish.yml rename to .github/workflows/.python-publish.txt diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..fac195b --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,136 @@ +### +# ```{rubric} MarkdownLint GitHub Actions +# ``` +# --- +# This is a basic workflow to help you get started with Actions. +# +# ```{literalinclude} /.github/workflows/pages.yml +# :language: yaml +# :start-at: "name: Test, Build, Deploy to GitHub Pages\n" +# :end-before: "###\n" +# ``` +# +# Set a name for the workflow. +name: Test, Build, Deploy to GitHub Pages +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: {} + +### +# ```{rubric} Permissions Updates +# ``` +# Enable read for contents and issues, and write for checks and PRs. +# +# ```{literalinclude} /.github/workflows/pages.yml +# :language: yaml +# :start-at: "permissions:\n" +# :end-before: "###\n" +# ``` +permissions: + contents: read + issues: read + checks: write + pull-requests: write + +### +# ```{rubric} Workflow Jobs +# ``` +# --- +# A workflow run is made up of one or more +# jobs that can run sequentially or in parallel +# +jobs: + ### + # ```{rubric} markdownlint + # ``` + # --- + # Check that the markdown in this repo is up to our (arbitrary) standards. + # + # ```{literalinclude} /.github/workflows/pages.yml + # :language: yaml + # :start-at: "markdownlint:\n" + # :end-before: "###\n" + # ``` + markdownlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Set up NodeJS + uses: actions/setup-node@main + - name: Install the checker + run: npm i -g markdownlint-cli2 markdownlint-cli2-formatter-junit --save-dev + - name: Lint the Markdown + run: markdownlint-cli2 **/*.md + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + if: always() + with: + files: markdownlint-cli2-junit.xml + ### + # ```{rubric} Build GitHub Pages Site + # ``` + # --- + # Build the pages site using Sphinx and upload the resulting artifact. + # + # ```{literalinclude} /.github/workflows/pages.yml + # :language: yaml + # :start-at: " build:\n" + # :end-before: "###\n" + # ``` + build: + needs: markdownlint + runs-on: ubuntu-20.04 + permissions: + pages: write + id-token: write + steps: + - uses: actions/checkout@main + - uses: actions/setup-python@main + with: + python-version: 3.11 + cache: pipenv + - name: Setup pages + uses: actions/configure-pages@main + - name: Install pipenv + run: curl https://raw.githubusercontent.com/pypa/pipenv/master/get-pipenv.py | python + - name: Install Python dependencies + run: | + pipenv install --categories docs + pipenv install -e . + - name: Build the static site + run: pipenv run sphinx-build -a -E . deploy + - name: Upload artifact + uses: actions/upload-pages-artifact@main + with: + path: './deploy' + ### + # ```{rubric} Deploy the Pages site + # ``` + # --- + # Download the artifact and deploy to pages. + # + # ```{literalinclude} /.github/workflows/pages.yml + # :language: yaml + # :start-at: " pages:\n" + # ``` + pages: + needs: build + runs-on: ubuntu-20.04 + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + permissions: + pages: write + id-token: write + steps: + - name: Download pages artifact + id: download + uses: actions/download-artifact@main + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc new file mode 100644 index 0000000..04c1f00 --- /dev/null +++ b/.markdownlint-cli2.jsonc @@ -0,0 +1,5 @@ +{ + "outputFormatters": [ + [ "markdownlint-cli2-formatter-junit" ] + ] +} diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000..1b81e8a --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,338 @@ +# Example markdownlint configuration with all properties +# set to their default value + +# Default state for all rules +default: true + +# Path to configuration file to extend +extends: null + +# MD001/heading-increment : Heading levels should only increment by +# one level at a time : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md001.md +MD001: true + +# MD003/heading-style : Heading style : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md003.md +MD003: + # Heading style + style: "consistent" + +# MD004/ul-style : Unordered list style : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md004.md +MD004: + # List style + style: "consistent" + +# MD005/list-indent : Inconsistent indentation for list items at the +# same level : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md005.md +MD005: true + +# MD007/ul-indent : Unordered list indentation : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md007.md +MD007: + # Spaces for indent + indent: 2 + # Whether to indent the first level of the list + start_indented: false + # Spaces for first level indent (when start_indented is set) + start_indent: 2 + +# MD009/no-trailing-spaces : Trailing spaces : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md009.md +MD009: + # Spaces for line break + br_spaces: 2 + # Allow spaces for empty lines in list items + list_item_empty_lines: false + # Include unnecessary breaks + strict: false + +# MD010/no-hard-tabs : Hard tabs : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md010.md +MD010: + # Include code blocks + code_blocks: true + # Fenced code languages to ignore + ignore_code_languages: [] + # Number of spaces for each hard tab + spaces_per_tab: 1 + +# MD011/no-reversed-links : Reversed link syntax : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md011.md +MD011: true + +# MD012/no-multiple-blanks : Multiple consecutive blank lines : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md012.md +MD012: + # Consecutive blank lines + maximum: 1 + +# MD013/line-length : Line length : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md013.md +MD013: + # Number of characters + line_length: 120 + # Number of characters for headings + heading_line_length: 80 + # Number of characters for code blocks + code_block_line_length: 120 + # Include code blocks + code_blocks: true + # Include tables + tables: true + # Include headings + headings: true + # Strict length checking + strict: false + # Stern length checking + stern: false + +# MD014/commands-show-output : Dollar signs used before commands without +# showing output : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md014.md +MD014: true + +# MD018/no-missing-space-atx : No space after hash on atx style heading : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md018.md +MD018: true + +# MD019/no-multiple-space-atx : Multiple spaces after hash on atx style +# heading : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md019.md +MD019: true + +# MD020/no-missing-space-closed-atx : No space inside hashes on closed +# atx style heading : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md020.md +MD020: true + +# MD021/no-multiple-space-closed-atx : Multiple spaces inside hashes on +# closed atx style heading : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md021.md +MD021: true + +# MD022/blanks-around-headings : Headings should be surrounded by blank +# lines : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md022.md +MD022: + # Blank lines above heading + lines_above: 1 + # Blank lines below heading + lines_below: 1 + +# MD023/heading-start-left : Headings must start at the beginning of +# the line : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md023.md +MD023: true + +# MD024/no-duplicate-heading : Multiple headings with the same content : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md024.md +MD024: + # Only check sibling headings + siblings_only: false + +# MD025/single-title/single-h1 : Multiple top-level headings in the same +# document : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md025.md +MD025: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD026/no-trailing-punctuation : Trailing punctuation in heading : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md026.md +MD026: + # Punctuation characters + punctuation: ".,;:!。,;:!" + +# MD027/no-multiple-space-blockquote : Multiple spaces after blockquote symbol +# : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md027.md +MD027: true + +# MD028/no-blanks-blockquote : Blank line inside blockquote : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md028.md +MD028: true + +# MD029/ol-prefix : Ordered list item prefix : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md029.md +MD029: + # List style + style: "one_or_ordered" + +# MD030/list-marker-space : Spaces after list markers : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md030.md +MD030: + # Spaces for single-line unordered list items + ul_single: 1 + # Spaces for single-line ordered list items + ol_single: 1 + # Spaces for multi-line unordered list items + ul_multi: 1 + # Spaces for multi-line ordered list items + ol_multi: 1 + +# MD031/blanks-around-fences : +# Fenced code blocks should be surrounded by blank lines : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md031.md +MD031: + # Include list items + list_items: true + +# MD032/blanks-around-lists : Lists should be surrounded by blank lines : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md032.md +MD032: true + +# MD033/no-inline-html : Inline HTML : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md033.md +MD033: + # Allowed elements + allowed_elements: [] + +# MD034/no-bare-urls : Bare URL used : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md034.md +MD034: true + +# MD035/hr-style : Horizontal rule style : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md035.md +MD035: + # Horizontal rule style + style: "consistent" + +# MD036/no-emphasis-as-heading : Emphasis used instead of a heading : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md036.md +MD036: + # Punctuation characters + punctuation: ".,;:!?。,;:!?" + +# MD037/no-space-in-emphasis : Spaces inside emphasis markers : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md037.md +MD037: true + +# MD038/no-space-in-code : Spaces inside code span elements : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md038.md +MD038: true + +# MD039/no-space-in-links : Spaces inside link text : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md039.md +MD039: true + +# MD040/fenced-code-language : Fenced code blocks should have a +# language specified : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md040.md +MD040: + # List of languages + allowed_languages: [] + # Require language only + language_only: false + +# MD041/first-line-heading/first-line-h1 : First line in a file should be +# a top-level heading : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md041.md +MD041: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD042/no-empty-links : No empty links : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md042.md +MD042: true + +# MD043/required-headings : Required heading structure : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md043.md +MD043: + # List of headings + headings: ['*'] + # Match case of headings + match_case: false + +# MD044/proper-names : Proper names should have the correct capitalization +# : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md044.md +MD044: + # List of proper names + names: [] + # Include code blocks + code_blocks: true + # Include HTML elements + html_elements: true + +# MD045/no-alt-text : Images should have alternate text (alt text) : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md045.md +MD045: true + +# MD046/code-block-style : Code block style : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md046.md +MD046: + # Block style + style: "consistent" + +# MD047/single-trailing-newline : Files should end with a single newline +# character : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md047.md +MD047: true + +# MD048/code-fence-style : Code fence style : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md048.md +MD048: + # Code fence style + style: "consistent" + +# MD049/emphasis-style : Emphasis style : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md049.md +MD049: + # Emphasis style + style: "consistent" + +# MD050/strong-style : Strong style : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md050.md +MD050: + # Strong style + style: "consistent" + +# MD051/link-fragments : Link fragments should be valid : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md051.md +MD051: true + +# MD052/reference-links-images : Reference links and images should use +# a label that is defined : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md052.md +MD052: + # Include shortcut syntax + shortcut_syntax: false + +# MD053/link-image-reference-definitions : Link and image reference +# definitions should be needed : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md053.md +MD053: + # Ignored definitions + ignored_definitions: + - "//" + +# MD054/link-image-style : Link and image style : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md054.md +MD054: + # Allow autolinks + autolink: true + # Allow inline links and images + inline: true + # Allow full reference links and images + full: true + # Allow collapsed reference links and images + collapsed: true + # Allow shortcut reference links and images + shortcut: true + # Allow URLs as inline links + url_inline: true + +# MD055/table-pipe-style : Table pipe style : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md055.md +MD055: + # Table pipe style + style: "consistent" + +# MD056/table-column-count : Table column count : +# https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md056.md +MD056: true diff --git a/Pipfile b/Pipfile index e50cf2a..cccf747 100644 --- a/Pipfile +++ b/Pipfile @@ -21,9 +21,11 @@ loguru = "*" python-dotenv = "*" requests = "*" tox = "*" +setuptools = "*" +panegyric = {file = ".", editable = true} +sentry-sdk = "*" [docs] -myst-parser = "*" sphinx = "*" sphinx-autobuild = "*" sphinx-copybutton = "*" @@ -31,3 +33,6 @@ sphinx-design = "*" sphinx-git = "*" sphinx-last-updated-by-git = "*" sphinxcontrib-autoyaml = "*" +sphinx-sizzle-theme = "*" +renku-sphinx-theme = "*" +myst-parser = {extras = ["linkify"], version = "*"} diff --git a/Pipfile.lock b/Pipfile.lock index 8f4f695..7718e27 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "02854d7c69e759dacd8ae586c76122041ea47e0bbf1c2003f74c3f20e7cb35bc" + "sha256": "48a64f3d25ada021159c428861c716969a7e24bbec808b840660f066e8383475" }, "pipfile-spec": 6, "requires": {}, @@ -182,6 +182,10 @@ "markers": "python_version >= '3.7'", "version": "==24.0" }, + "panegyric": { + "editable": true, + "file": "." + }, "platformdirs": { "hashes": [ "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068", @@ -288,6 +292,23 @@ "markers": "python_version < '3.13' and platform_python_implementation == 'CPython'", "version": "==0.2.8" }, + "sentry-sdk": { + "hashes": [ + "sha256:4f2d6c43c07925d8cd10dfbd0970ea7cb784f70e79523cca9dbcd72df38e5a46", + "sha256:be4f8f4b29a80b6a3b71f0f31487beb9e296391da20af8504498a328befed53f" + ], + "index": "pypi", + "version": "==1.41.0" + }, + "setuptools": { + "hashes": [ + "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56", + "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==69.1.1" + }, "tox": { "hashes": [ "sha256:b03754b6ee6dadc70f2611da82b4ed8f625fcafd247e15d1d0cb056f90a06d3b", @@ -804,11 +825,11 @@ }, "docutils": { "hashes": [ - "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6", - "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b" + "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c", + "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06" ], - "markers": "python_version >= '3.7'", - "version": "==0.20.1" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.18.1" }, "gitdb": { "hashes": [ @@ -850,6 +871,13 @@ "markers": "python_version >= '3.7'", "version": "==3.1.3" }, + "linkify-it-py": { + "hashes": [ + "sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048", + "sha256:6bcbc417b0ac14323382aef5c5192c0075bf8a9d6b41820a2b66371eac6b6d79" + ], + "version": "==2.0.3" + }, "livereload": { "hashes": [ "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869", @@ -948,11 +976,13 @@ "version": "==0.1.2" }, "myst-parser": { + "extras": [ + "linkify" + ], "hashes": [ "sha256:7c36344ae39c8e740dad7fdabf5aa6fc4897a813083c6cc9990044eb93656b14", "sha256:ea929a67a6a0b1683cdbe19b8d2e724cd7643f8aa3e7bb18dd65beac3483bead" ], - "index": "pypi", "markers": "python_version >= '3.8'", "version": "==2.0.0" }, @@ -1029,6 +1059,14 @@ "markers": "python_version >= '3.6'", "version": "==6.0.1" }, + "renku-sphinx-theme": { + "hashes": [ + "sha256:1374990e37120fe09e75914688a697cbe44e245b173c1438611ef9c79b8bf687", + "sha256:4901d7ca7074469deb25ddd3c4c0651627eaffbb04bc5fcfd5bc65f0e911b0f3" + ], + "index": "pypi", + "version": "==0.4.0" + }, "requests": { "hashes": [ "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", @@ -1121,6 +1159,22 @@ "markers": "python_version >= '3.7'", "version": "==0.3.6" }, + "sphinx-rtd-theme": { + "hashes": [ + "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0", + "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.3.0" + }, + "sphinx-sizzle-theme": { + "hashes": [ + "sha256:18df0f66a9c1b4028c703896b5df896b875962970ef3a12fb968c7240060c4b0", + "sha256:5a10ea76952011164f6a1b12de35e18bdfaa4efcc338391f26373277e3e2c196" + ], + "index": "pypi", + "version": "==0.1.3" + }, "sphinxcontrib-applehelp": { "hashes": [ "sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619", @@ -1154,6 +1208,14 @@ "markers": "python_version >= '3.9'", "version": "==2.0.5" }, + "sphinxcontrib-jquery": { + "hashes": [ + "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a", + "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae" + ], + "markers": "python_version >= '2.7'", + "version": "==4.1" + }, "sphinxcontrib-jsmath": { "hashes": [ "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", @@ -1195,6 +1257,14 @@ "markers": "python_version > '2.7'", "version": "==6.4" }, + "uc-micro-py": { + "hashes": [ + "sha256:d321b92cff673ec58027c04015fcaa8bb1e005478643ff4a500882eaab88c48a", + "sha256:db1dffff340817673d7b466ec86114a9dc0e9d4d9b5ba229d9d60e5c12600cd5" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.3" + }, "urllib3": { "hashes": [ "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d", diff --git a/conf.py b/conf.py index 0b4634d..d40cfaf 100644 --- a/conf.py +++ b/conf.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +# pylint: disable=C0103,W0622 """Configuration file for the Sphinx documentation builder. # This file only contains a selection of the most common options. For a full @@ -13,9 +14,8 @@ """ import pathlib import sys -sys.path.insert(0, str(pathlib.Path('.').resolve)) -sys.path.insert(0, str(pathlib.Path('./tests').resolve)) - +cur_dir = pathlib.Path(__file__).resolve +sys.path.insert(0, str(cur_dir)) # -- Project information ---------------------------------------------------- # The full version, including alpha/beta/rc tags @@ -27,7 +27,9 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [".venv/*"] +exclude_patterns = [ + '.venv/*' +] # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -44,6 +46,7 @@ 'sphinx.ext.duration', 'sphinx.ext.githubpages', 'sphinx.ext.graphviz', + 'sphinx.ext.inheritance_diagram', 'sphinx.ext.intersphinx', 'sphinx.ext.linkcode', 'sphinx.ext.todo', @@ -54,14 +57,17 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = 'renku' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -intersphinx_mapping = {'python': ('https://docs.python.org/3', None)} +intersphinx_mapping = { + 'python': ('https://docs.python.org/3', None), + # 'requests': ('https://docs.python-requests.org/en/latest/', None) +} # Add any paths that contain templates here, relative to this directory. myst_enable_extensions = [ "amsmath", diff --git a/docs/index.md b/docs/index.md index 121fcbd..f03dba7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -9,6 +9,7 @@ title: Panegyric Docs Index modules panegyric tests +usage ``` ```{sectionauthor} Xander Harris diff --git a/docs/modules.md b/docs/modules.md new file mode 100644 index 0000000..64162d1 --- /dev/null +++ b/docs/modules.md @@ -0,0 +1,22 @@ +--- +abstract: This is API documentation for Panegyric tests. +authors: Xander Harris +date: 2024-03-12 +title: tests package +--- + +## src + +```{toctree} +:maxdepth: 2 +:caption: panegyric + +panegyric +``` + +```{toctree} +:maxdepth: 2 +:caption: tests + +tests +``` diff --git a/panegyric.md b/docs/panegyric.md similarity index 55% rename from panegyric.md rename to docs/panegyric.md index 1890080..15873eb 100644 --- a/panegyric.md +++ b/docs/panegyric.md @@ -1,12 +1,32 @@ -panegyric package -================= - -Submodules ----------- - -panegyric.text module ---------------------- - +--- +abstract: This is API documentation for Panegyric. +authors: Xander Harris +date: 2024-03-12 +title: panegyric package +--- + +## panegyric package + + +### Submodules + +```{inheritance-diagram} panegyric.text.Text +``` + +#### panegyric.text module + +```{eval-rst} .. automodule:: panegyric.text :exclude-members: Text :show-inheritance: @@ -44,11 +64,14 @@ panegyric.text module .. automethod:: write_messages .. autofunction:: main +``` -Module contents ---------------- +## Module contents -.. automodule:: panegyric +```{eval-rst} +.. automodule:: panegyric.text :members: :undoc-members: :show-inheritance: + :noindex: +``` diff --git a/docs/tests.md b/docs/tests.md new file mode 100644 index 0000000..a3f6f21 --- /dev/null +++ b/docs/tests.md @@ -0,0 +1,30 @@ +--- +abstract: This is API documentation for Panegyric tests. +authors: Xander Harris +date: 2024-03-12 +title: tests package +--- + +## Submodules + +### tests.conftest module + +```{eval-rst} +.. automodule:: tests.conftest + :members: + :undoc-members: + :show-inheritance: +``` + +### tests.test_text module + +```{eval-rst} +.. automodule:: tests.test_text + :members: + :undoc-members: + :show-inheritance: +``` + +```{eval-rst} +.. autosummary:: . +``` diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..0609625 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,58 @@ +--- +abstract: Usage information for Panegyric. +authors: Xander Harris +date: 2024-03-12 +title: Usage +--- + +## Installation + +1. Make sure you've got Python 3 installed with `pipenv`{l=shell} available. + + ```{code-block} shell + pip3 install -U pip pipenv + ``` + +2. Then use pipenv to install the required dependencies and + enter the created virtualenv. + + ```{code-block} shell + pipenv install --dev + pipenv shell + ``` + +3. From this virtualenv you can build and install the package. + + ```{code-block} shell + python setup.py build + python setup.py install + ``` + +### Install with pip + +Or you can use pip to install the package locally. + +```{code-block} shell +pip install -e . +``` + +## Execution + +At the moment there are no arguments, so changing +things like the phone number to text and enabling +non-test executions require updating the `src/panegyric/text.py` +source file directly. + +Eventually there will be a config file or something to make +this kind of thing easier, but for now this will work. + +Once you've got the package installed and the `Text` class +configured you can run the program. + +```{code-block} shell +panegyric +``` + +At the time of writing this is meant to be executed once +a day via a cron job or similar timed program execution +tool. diff --git a/index.md b/index.md index 39768e5..b5d1818 100644 --- a/index.md +++ b/index.md @@ -16,6 +16,10 @@ If you feel like complimenting my wife via text, this is a great way to do it. :caption: Documentation docs/index +docs/modules +docs/panegyric +docs/tests +docs/usage ``` ```{toctree} diff --git a/license.md b/license.md index 3c577b0..cca10cd 100644 --- a/license.md +++ b/license.md @@ -1,4 +1,9 @@ -This is free and unencumbered software released into the public domain. +--- +abstract: This is free and unencumbered software released into the public domain. +authors: Xander Harris +date: 2024-03-12 +title: Unlicensed +--- Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled @@ -13,6 +18,8 @@ successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. +## Warranty + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -21,4 +28,4 @@ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -For more information, please refer to \ No newline at end of file +For more information, please refer to [the website](https://unlicense.org). diff --git a/modules.md b/modules.md deleted file mode 100644 index d50109f..0000000 --- a/modules.md +++ /dev/null @@ -1,7 +0,0 @@ -src -=== - -.. toctree:: - :maxdepth: 4 - - panegyric diff --git a/s.md b/s.md deleted file mode 100644 index 0682a9f..0000000 --- a/s.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -abstract: A security policy, one day. -authors: Xander Harris -date: 2024-03-13 -title: Security Policy ---- - -## Don't do anything stupid diff --git a/setup.py b/setup.py index b8066b2..c0b023f 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,17 @@ #!/usr/bin/env python3 """Setup tools configuration.""" - +# pylint: disable=E0401 +import pathlib import setuptools -with open("README.md", "r", encoding="utf-8") as fh: +def get_version(): + """Get the project's version.""" + vpath = pathlib.Path('version') + with vpath.open('r', encoding='utf-8') as v_fh: + version = v_fh.read() + return version + +with pathlib.Path('readme.md').open("r", encoding="utf-8") as fh: long_description = fh.read() setuptools.setup( @@ -15,7 +23,8 @@ }, install_requires=[ 'requests', - 'ruamel.yaml' + 'ruamel.yaml', + 'sentry-sdk', ], long_description=long_description, long_description_content_type="text/markdown", @@ -26,5 +35,5 @@ "Bug Tracker": "https://github.com/edwardtheharris/panegyric/issues", }, url="https://github.com/edwardtheharris/panegyric", - version='v0.1.0', + version=get_version(), ) diff --git a/src/panegyric/text.py b/src/panegyric/text.py index 854371c..ca8fcb5 100644 --- a/src/panegyric/text.py +++ b/src/panegyric/text.py @@ -5,7 +5,6 @@ import sys import requests -import sentry_sdk from ruamel import yaml @@ -35,19 +34,14 @@ def __init__(self, message_file_path): """Initialize a Text instance. :param str message_file_path: Path to the file containing messages. + + import os + # import sentry_sdk + # sentry_sdk.init(os.environ.get('SENTRY_DSN')) """ self.current_date = datetime.datetime.now().replace( hour=0, minute=0, second=0, microsecond=0) self.message_file_path = message_file_path - sentry_sdk.init( - ("https://a40e278a662e46db86ef8aa4d7a46fbd@o325200" - ".ingest.sentry.io/5955114"), - - # Set traces_sample_rate to 1.0 to capture 100% - # of transactions for performance monitoring. - # We recommend adjusting this value in production. - traces_sample_rate=1.0 - ) def get_message(self): """Get a message to send. @@ -121,7 +115,7 @@ def send_message(self): 'key': self.api_key, } - resp = requests.post(self.url, message_dict) + resp = requests.post(self.url, message_dict, timeout='60s') return resp def write_messages(self): diff --git a/tests/__init__.py b/src/tests/__init__.py similarity index 100% rename from tests/__init__.py rename to src/tests/__init__.py diff --git a/tests/compliments.yml b/src/tests/compliments.yml similarity index 100% rename from tests/compliments.yml rename to src/tests/compliments.yml diff --git a/tests/conftest.py b/src/tests/conftest.py similarity index 90% rename from tests/conftest.py rename to src/tests/conftest.py index e5a97b6..9e19ae3 100644 --- a/tests/conftest.py +++ b/src/tests/conftest.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """Configuration for panegyric tests.""" - +import pathlib import pytest from ruamel import yaml @@ -15,13 +15,19 @@ def message(): def messages(): """Return all messages for testing.""" yml = yaml.YAML(typ='safe', pure='True') - return_messages = yml.load(open('tests/compliments.yml')) + comp_path = pathlib.Path('tests/compliments.yml') + with comp_path.open('r', encoding='utf-8') as cp_fh: + return_messages = yml.load(cp_fh) return return_messages @pytest.fixture def api_response(): - """Return a mocked API reponse.""" + """Return a mocked API response. + + :return: A mock API response + :rtype: dict + """ return { '_content': (b'{ "success": false,' b' "error": "Out of quota",' diff --git a/tests/fixtures/compliments-duplicate-date.yml b/src/tests/fixtures/compliments-duplicate-date.yml similarity index 100% rename from tests/fixtures/compliments-duplicate-date.yml rename to src/tests/fixtures/compliments-duplicate-date.yml diff --git a/tests/fixtures/compliments-no-date.yml b/src/tests/fixtures/compliments-no-date.yml similarity index 100% rename from tests/fixtures/compliments-no-date.yml rename to src/tests/fixtures/compliments-no-date.yml diff --git a/tests/fixtures/compliments-with-date.yml b/src/tests/fixtures/compliments-with-date.yml similarity index 100% rename from tests/fixtures/compliments-with-date.yml rename to src/tests/fixtures/compliments-with-date.yml diff --git a/tests/fixtures/resp.json b/src/tests/fixtures/resp.json similarity index 100% rename from tests/fixtures/resp.json rename to src/tests/fixtures/resp.json diff --git a/tests/fixtures/resp.obj b/src/tests/fixtures/resp.obj similarity index 100% rename from tests/fixtures/resp.obj rename to src/tests/fixtures/resp.obj diff --git a/tests/result/compliments.yml b/src/tests/result/compliments.yml similarity index 100% rename from tests/result/compliments.yml rename to src/tests/result/compliments.yml diff --git a/tests/test_text.py b/src/tests/test_text.py similarity index 84% rename from tests/test_text.py rename to src/tests/test_text.py index fd3b414..e2ca427 100644 --- a/tests/test_text.py +++ b/src/tests/test_text.py @@ -1,9 +1,12 @@ #!/usr/bin/env python3 -"""Tests for the Text class.""" +# pylint: disable=E0401 +"""Tests for the Text class. +import os +""" import datetime import json -import os +import pathlib from unittest.mock import patch from unittest.mock import Mock @@ -11,19 +14,21 @@ import pytest import requests -from pytest_sentry import Client from ruamel.yaml import YAML from panegyric.text import main from panegyric.text import Text -@pytest.mark.sentry_client(Client({ - 'dsn': os.environ.get('PYTEST_SENTRY_DSN'), - 'debug': True} -)) class TestText: - """Test class for Text class.""" + """Test class for Text class. + + # from pytest_sentry import Client + # @pytest.mark.sentry_client(Client({ + # 'dsn': os.environ.get('PYTEST_SENTRY_DSN'), + # 'debug': True} + # )) + """ send_date = (datetime.datetime.now().replace( hour=0, minute=0, second=0, microsecond=0 @@ -51,7 +56,9 @@ def test_get_message(self): test_message = text.get_message() yml = YAML() - test_data = yml.load(open('tests/result/compliments.yml')) + cmp_yml = pathlib.Path('tests/result/compliments.yml') + with cmp_yml.open('r', encoding='utf-8') as cmp_fh: + test_data = yml.load(cmp_fh) assert text.messages == test_data assert isinstance(test_message, dict) assert json.dumps(test_message) @@ -113,13 +120,15 @@ def test_send_message(self, mocked_post): message_dict = { 'phone': '2138765309', 'message': f'{text_text} - {text_from}', - 'key': f'{test_key}_test', + 'key': f'{test_key}_test ', } - response_dict = json.load(open('tests/fixtures/resp.json')) + rsp = pathlib.Path('tests/fixtures/resp.json') + with rsp.open('r', encoding='utf-8') as rsp_fh: + response_dict = json.load(rsp_fh) mocked_post.return_value = Mock( status_code=200, json=lambda: response_dict) - resp = requests.post(text.url, message_dict) + resp = requests.post(text.url, message_dict, timeout='60s') assert resp.status_code == 200 assert isinstance(resp.json(), dict) @@ -132,7 +141,9 @@ def test_write_messages(self): text.write_messages() yml = YAML() - test_data = yml.load(open('tests/compliments.yml')) + cmp_yml = pathlib.Path('tests/compliments.yml') + with cmp_yml.open('r', encoding='utf-8') as cmp_fh: + test_data = yml.load(cmp_fh) assert text.messages == test_data def test_message_rate(self): diff --git a/tests.md b/tests.md deleted file mode 100644 index 8827145..0000000 --- a/tests.md +++ /dev/null @@ -1,29 +0,0 @@ -tests package -============= - -Submodules ----------- - -tests.conftest module ---------------------- - -.. automodule:: tests.conftest - :members: - :undoc-members: - :show-inheritance: - -tests.test\_text module ------------------------ - -.. automodule:: tests.test_text - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: tests - :members: - :undoc-members: - :show-inheritance: diff --git a/version b/version new file mode 100644 index 0000000..d917d3e --- /dev/null +++ b/version @@ -0,0 +1 @@ +0.1.2