diff --git a/.copier-answers.yml b/.copier-answers.yml index da025b0..597d1fa 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: v1.4.1 +_commit: v1.4.3 _src_path: gh:lincc-frameworks/python-project-template author_email: scampos@andrew.cmu.edu author_name: Sandro Campos diff --git a/.github/workflows/asv-main.yml b/.github/workflows/asv-main.yml index a1b562b..0cc09df 100644 --- a/.github/workflows/asv-main.yml +++ b/.github/workflows/asv-main.yml @@ -1,5 +1,6 @@ -# This workflow will run benchmarks with airspeed velocity (asv) -# and publish the results to a dashboard on GH Pages. +# This workflow will run benchmarks with airspeed velocity (asv), +# store the new results in the "benchmarks" branch and publish them +# to a dashboard on GH Pages. name: Run ASV benchmarks for main @@ -75,7 +76,7 @@ jobs: - name: Create ASV machine config file run: asv machine --machine gh-runner --yes - - name: Fetch results from "benchmarks" branch + - name: Fetch previous results from the "benchmarks" branch run: | if git ls-remote --exit-code origin benchmarks > /dev/null 2>&1; then git merge origin/benchmarks \ @@ -87,7 +88,7 @@ jobs: - name: Run ASV for the main branch run: asv run ALL --skip-existing - - name: Submit new results to the "benchmarks" branch + - name: Submit new results to the "benchmarks" branch uses: JamesIves/github-pages-deploy-action@v4 with: branch: benchmarks diff --git a/.github/workflows/asv-pr.yml b/.github/workflows/asv-pr.yml index 31deac5..9bcbfc4 100644 --- a/.github/workflows/asv-pr.yml +++ b/.github/workflows/asv-pr.yml @@ -8,14 +8,14 @@ on: pull_request: branches: [ main ] -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - env: PYTHON_VERSION: "3.10" WORKING_DIR: ${{ github.workspace }}/benchmarks +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: setup-python: @@ -84,24 +84,18 @@ jobs: env: STEP_URL: "${{ steps.jobs.outputs.html_url }}#step:8:1" - - name: Publish comment to PR - uses: actions/github-script@v6 + - name: Find benchmarks comment + uses: peter-evans/find-comment@v2 + id: find-comment + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: view all benchmarks + + - name: Create or update benchmarks comment + uses: peter-evans/create-or-update-comment@v3 with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const fs = require('fs'); - const path = require('path'); - - const workingDir = process.env.WORKING_DIR; - try { - process.chdir(workingDir); - const comment = fs.readFileSync('output', 'utf-8'); - const { data } = await github.rest.issues.createComment({ - ...context.repo, - issue_number: context.issue.number, - body: comment, - }); - console.log('Comment published:', data.html_url); - } catch (err) { - console.error(err); - } \ No newline at end of file + comment-id: ${{ steps.find-comment.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body-path: ${{ env.WORKING_DIR }}/output + edit-mode: replace diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index c63e2b9..257190f 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -16,16 +16,12 @@ concurrency: jobs: build: runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.8', '3.9', '3.10'] - steps: - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} + - name: Set up Python uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version }} + python-version: '3.10' - name: Install dependencies run: | sudo apt-get update diff --git a/.github/workflows/pre-commit-ci.yml b/.github/workflows/pre-commit-ci.yml index f516a2c..8397877 100644 --- a/.github/workflows/pre-commit-ci.yml +++ b/.github/workflows/pre-commit-ci.yml @@ -1,5 +1,6 @@ -# This workflow runs pre-commit hooks to enforce code style. -# It is triggered on pull requests to main. +# This workflow runs pre-commit hooks on pull requests to enforce coding style. +# To ensure correct configuration, please refer to: +# https://lincc-ppt.readthedocs.io/en/latest/practices/ci_precommit.html name: Run pre-commit hooks diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index 928fdca..52f72ce 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -8,6 +8,17 @@ name: Unit test smoke test on: schedule: - cron: 45 6 * * * + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: jobs: build: diff --git a/.gitignore b/.gitignore index 176607d..a7c3220 100644 --- a/.gitignore +++ b/.gitignore @@ -147,4 +147,5 @@ benchmarks/html # Airspeed Velocity performance results _results/ -_html/ \ No newline at end of file +_html/ +.idea/ \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6f405c9..93da1a1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,4 @@ +fail_fast: true repos: # Compare the local template version to the latest remote template version @@ -23,7 +24,7 @@ repos: entry: jupyter nbconvert --clear-output # Run unit tests, verify that they pass. Note that coverage is run against - # the ./src directory here because that is what will be committed. In the + # the ./src directory here because that is what will be committed. In the # github workflow script, the coverage is run against the installed package # and uploaded to Codecov by calling pytest like so: # `python -m pytest --cov= --cov-report=xml` @@ -57,34 +58,17 @@ repos: name: Validate pyproject.toml description: Verify that pyproject.toml adheres to the established schema. - # Run black to format code - - repo: https://github.com/psf/black - rev: 23.7.0 - hooks: - - id: black-jupyter - name: Run black (.py and .ipnyb files) - description: Auto-format code with black. - files: ^(src|tests|docs|benchmarks)/ - language_version: python3.10 # Automatically sort the imports used in .py files - repo: https://github.com/pycqa/isort rev: 5.12.0 hooks: - id: isort - name: Run isort (python files) - description: Sort and organize imports in .py files. - types: [python] - files: ^(src|tests|benchmarks)/ + name: Run isort + description: Sort and organize imports in .py and .pyi files. + types_or: [python, pyi] + - # Automatically sort the imports used in .ipynb files - - repo: https://github.com/nbQA-dev/nbQA - rev: 1.7.0 - hooks: - - id: nbqa-isort - name: Run isort (jupyter notebooks) - files: ^docs/ - args: ["--float-to-top"] # Analyze the src code style and report code that doesn't adhere. - repo: local @@ -106,11 +90,11 @@ repos: - repo: local hooks: - id: pylint - name: pylint (python files in tests/) + name: pylint (python files in tests/ and benchmarks/) entry: pylint language: system types: [python] - files: ^tests/ + files: ^(tests|benchmarks)/ args: [ "-rn", # Only display messages diff --git a/benchmarks/benchmarks/__init__.py b/benchmarks/__init__.py similarity index 100% rename from benchmarks/benchmarks/__init__.py rename to benchmarks/__init__.py diff --git a/benchmarks/asv.conf.json b/benchmarks/asv.conf.json index d424481..9c5ff25 100644 --- a/benchmarks/asv.conf.json +++ b/benchmarks/asv.conf.json @@ -1,13 +1,13 @@ { - // The version of the config file format. Do not change, unless + // The version of the config file format. Do not change, unless // you know what you are doing. "version": 1, - // The name of the project being benchmarked + // The name of the project being benchmarked. "project": "benchmarking-asv", - // The project's homepage + // The project's homepage. "project_url": "https://github.com/lincc-frameworks/benchmarking-asv", // The URL or local path of the source code repository for the - // project being benchmarked + // project being benchmarked. "repo": "..", // List of branches to benchmark. If not provided, defaults to "master" // (for git) or "tip" (for mercurial). @@ -17,12 +17,12 @@ "build_command": [ "python -m build --wheel -o {build_cache_dir} {build_dir}" ], - // The DVCS being used. If not set, it will be automatically + // The DVCS being used. If not set, it will be automatically // determined from "repo" by looking at the protocol in the URL // (if remote), or by looking for special directories, such as // ".git" (if local). "dvcs": "git", - // The tool to use to create environments. May be "conda", + // The tool to use to create environments. May be "conda", // "virtualenv" or other value depending on the plugins in use. // If missing or the empty string, the tool will be automatically // determined by looking for tools on the PATH environment @@ -30,12 +30,12 @@ "environment_type": "virtualenv", // the base URL to show a commit for the project. "show_commit_url": "https://github.com/lincc-frameworks/benchmarking-asv/commit/", - // The Pythons you'd like to test against. If not provided, defaults + // The Pythons you'd like to test against. If not provided, defaults // to the current version of Python used to run `asv`. "pythons": [ "3.10" ], - // The matrix of dependencies to test. Each key is the name of a + // The matrix of dependencies to test. Each key is the name of a // package (in PyPI) and the values are version numbers. An empty // list indicates to just test against the default (latest) // version. @@ -45,28 +45,28 @@ "packaging": [] }, // The directory (relative to the current directory) that benchmarks are - // stored in. If not provided, defaults to "benchmarks" - "benchmark_dir": "benchmarks", + // stored in. If not provided, defaults to "benchmarks". + "benchmark_dir": ".", // The directory (relative to the current directory) to cache the Python - // environments in. If not provided, defaults to "env" + // environments in. If not provided, defaults to "env". "env_dir": "env", // The directory (relative to the current directory) that raw benchmark - // results are stored in. If not provided, defaults to "results". + // results are stored in. If not provided, defaults to "results". "results_dir": "_results", // The directory (relative to the current directory) that the html tree - // should be written to. If not provided, defaults to "html". + // should be written to. If not provided, defaults to "html". "html_dir": "_html", // The number of characters to retain in the commit hashes. // "hash_length": 8, // `asv` will cache wheels of the recent builds in each - // environment, making them faster to install next time. This is + // environment, making them faster to install next time. This is // number of builds to keep, per environment. "build_cache_size": 8 // The commits after which the regression search in `asv publish` // should start looking for regressions. Dictionary whose keys are // regexps matching to benchmark names, and values corresponding to // the commit (exclusive) after which to start looking for - // regressions. The default is to start from the first commit + // regressions. The default is to start from the first commit // with results. If the commit is `null`, regression detection is // skipped for the matching benchmark. // diff --git a/benchmarks/benchmarks/benchmarks.py b/benchmarks/benchmarks.py similarity index 65% rename from benchmarks/benchmarks/benchmarks.py rename to benchmarks/benchmarks.py index 1c23445..da2f974 100644 --- a/benchmarks/benchmarks/benchmarks.py +++ b/benchmarks/benchmarks.py @@ -1,32 +1,37 @@ -import random -import time - import benchmarking_asv as bench -class TimeSuite: - +class TimeSuite: # pylint: disable=too-few-public-methods """An example benchmark that times the performance of various kinds of iterating over dictionaries in Python.""" + def __init__(self): + self.d = {} + def setup(self): self.d = {} for x in range(500): self.d[x] = None def time_keys(self): + """Time first method.""" bench.example_module.run_time_computation() def time_iterkeys(self): + """Time second method.""" bench.example_module.run_time_computation() def time_range(self): + """Time third method.""" bench.example_module.run_time_computation() def time_xrange(self): + """Time fourth method.""" bench.example_module.run_time_computation() -class MemSuite: +class MemSuite: # pylint: disable=too-few-public-methods + """An example benchmark that times memory consumption.""" + def mem_list(self): return bench.example_module.run_mem_computation() diff --git a/docs/index.rst b/docs/index.rst index 971ed00..b9e5450 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,6 +5,43 @@ Welcome to benchmarking_asv's documentation! ======================================================================================== +Dev Guide - Getting Started +--------------------------- + +Before installing any dependencies or writing code, it's a great idea to create a +virtual environment. LINCC-Frameworks engineers primarily use `conda` to manage virtual +environments. If you have conda installed locally, you can run the following to +create and activate a new environment. + +.. code-block:: bash + + >> conda create env -n python=3.10 + >> conda activate + + +Once you have created a new environment, you can install this project for local +development using the following commands: + +.. code-block:: bash + + >> pip install -e .'[dev]' + >> pre-commit install + >> conda install pandoc + + +Notes: + +1) The single quotes around ``'[dev]'`` may not be required for your operating system. +2) ``pre-commit install`` will initialize pre-commit for this local repository, so + that a set of tests will be run prior to completing a local commit. For more + information, see the Python Project Template documentation on + `pre-commit `_. +3) Install ``pandoc`` allows you to verify that automatic rendering of Jupyter notebooks + into documentation for ReadTheDocs works as expected. For more information, see + the Python Project Template documentation on + `Sphinx and Python Notebooks `_. + + .. toctree:: :hidden: diff --git a/docs/requirements.txt b/docs/requirements.txt index 5c0f7d8..62972b9 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,6 @@ -sphinx==6.1.3 -sphinx-rtd-theme==1.2.0 -sphinx-autoapi==2.0.1 +sphinx +sphinx-rtd-theme +sphinx-autoapi nbsphinx ipython jupytext diff --git a/pyproject.toml b/pyproject.toml index 54a89f0..1ff2884 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,9 +23,9 @@ dev = [ "pytest", "pytest-cov", # Used to report total code coverage "pre-commit", # Used to run checks before finalizing a git commit - "sphinx==6.1.3", # Used to automatically generate documentation - "sphinx-rtd-theme==1.2.0", # Used to render documentation - "sphinx-autoapi==2.0.1", # Used to automatically generate api documentation + "sphinx", # Used to automatically generate documentation + "sphinx-rtd-theme", # Used to render documentation + "sphinx-autoapi", # Used to automatically generate api documentation "pylint", # Used for static linting of files # if you add dependencies here while experimenting in a notebook and you # want that notebook to render in your documentation, please add the @@ -35,6 +35,7 @@ dev = [ "ipython", # Also used in building notebooks into Sphinx "matplotlib", # Used in sample notebook intro_notebook.ipynb "numpy", # Used in sample notebook intro_notebook.ipynb + "asv==0.5.1", # Used to compute performance benchmarks ] [build-system] @@ -51,3 +52,6 @@ write_to = "src/benchmarking_asv/_version.py" testpaths = [ "tests", ] + +[tool.coverage.run] +omit=["src/benchmarking_asv/_version.py"] diff --git a/src/.pylintrc b/src/.pylintrc index ac138f1..3fd6eeb 100644 --- a/src/.pylintrc +++ b/src/.pylintrc @@ -183,6 +183,7 @@ good-names=i, k, ex, Run, + ra, _ # Good variable names regexes, separated by a comma. If names match any regex, @@ -277,19 +278,19 @@ exclude-too-few-public-methods= ignored-parents= # Maximum number of arguments for function / method. -max-args=5 +max-args=10 # Maximum number of attributes for a class (see R0902). -max-attributes=7 +max-attributes=20 # Maximum number of boolean expressions in an if statement (see R0916). max-bool-expr=5 # Maximum number of branch for function / method body. -max-branches=12 +max-branches=20 # Maximum number of locals for function / method body. -max-locals=15 +max-locals=20 # Maximum number of parents for a class (see R0901). max-parents=7 @@ -329,7 +330,7 @@ indent-after-paren=4 indent-string=' ' # Maximum number of characters on a single line. -max-line-length=100 +max-line-length=110 # Maximum number of lines in a module. max-module-lines=1000 @@ -502,7 +503,7 @@ ignore-imports=yes ignore-signatures=yes # Minimum lines number of a similarity. -min-similarity-lines=4 +min-similarity-lines=6 [SPELLING] diff --git a/tests/.pylintrc b/tests/.pylintrc index c3cf2bf..4f41ec3 100644 --- a/tests/.pylintrc +++ b/tests/.pylintrc @@ -183,6 +183,7 @@ good-names=i, k, ex, Run, + ra, _ # Good variable names regexes, separated by a comma. If names match any regex, @@ -277,19 +278,19 @@ exclude-too-few-public-methods= ignored-parents= # Maximum number of arguments for function / method. -max-args=5 +max-args=10 # Maximum number of attributes for a class (see R0902). -max-attributes=7 +max-attributes=20 # Maximum number of boolean expressions in an if statement (see R0916). max-bool-expr=5 # Maximum number of branch for function / method body. -max-branches=12 +max-branches=20 # Maximum number of locals for function / method body. -max-locals=15 +max-locals=30 # Maximum number of parents for a class (see R0901). max-parents=7 @@ -329,7 +330,7 @@ indent-after-paren=4 indent-string=' ' # Maximum number of characters on a single line. -max-line-length=100 +max-line-length=110 # Maximum number of lines in a module. max-module-lines=1000 @@ -503,7 +504,7 @@ ignore-imports=yes ignore-signatures=yes # Minimum lines number of a similarity. -min-similarity-lines=4 +min-similarity-lines=6 [SPELLING] diff --git a/tests/benchmarking_asv/conftest.py b/tests/benchmarking_asv/conftest.py deleted file mode 100644 index e69de29..0000000