├── {{cookiecutter.repo_name}} ├── tests │ ├── __init__.py │ └── test_cli.py ├── src │ └── {{cookiecutter.package_name}} │ │ ├── __main__.py │ │ ├── __init__.py │ │ └── cli.py ├── .git_archival.txt ├── .gitattributes ├── .codacy.yml ├── README.rst ├── .travis.yml ├── .pre-commit-config.yaml ├── .gitignore ├── .circleci │ └── config.yml ├── appveyor.yml ├── conda.recipe │ └── meta.yaml ├── pyproject.toml └── LICENSE ├── pytest.ini ├── .coveragerc ├── cookiecutter.json ├── hooks └── post_gen_project.py ├── .github ├── workflows │ ├── project.yml │ ├── cla.yml │ ├── issues.yml │ ├── labels.yml │ ├── lock.yml │ ├── stale.yml │ └── update.yml ├── PULL_REQUEST_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── 2_documentation.yml │ ├── 0_bug.yml │ ├── 1_feature.yml │ └── epic.yml └── template-files │ └── config.yml ├── setup.py ├── LICENSE ├── .gitignore ├── tests └── test_template.py ├── README.md ├── HOW_WE_USE_GITHUB.md └── CODE_OF_CONDUCT.md /{{cookiecutter.repo_name}}/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | testpaths = tests/test_template.py -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [report] 2 | omit = 3 | setup.py 4 | tests/* -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/src/{{cookiecutter.package_name}}/__main__.py: -------------------------------------------------------------------------------- 1 | from {{ cookiecutter.package_name }} import cli 2 | 3 | cli.cli() 4 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/.git_archival.txt: -------------------------------------------------------------------------------- 1 | node: 8bf6bbc6e3a57fd92216f47cb38ced36a8ba5ab1 2 | node-date: 2025-08-26T09:47:08-05:00 3 | describe-name: -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/.gitattributes: -------------------------------------------------------------------------------- 1 | src/{{cookiecutter.package_name}}/_version.py export-subst 2 | * text=auto eol=lf 3 | .git_archival.txt export-subst 4 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/tests/test_cli.py: -------------------------------------------------------------------------------- 1 | from {{ cookiecutter.package_name }} import cli 2 | 3 | 4 | def test_cli_template(): 5 | assert cli.cli() is None 6 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/.codacy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | exclude_paths: 3 | - '{{cookiecutter.package_name}}/_version.py' 4 | - 'tests/**/*' 5 | - 'tests/*' 6 | - 'benchmarks/**/*' 7 | - 'setup.py' 8 | - 'versioneer.py' 9 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/src/{{cookiecutter.package_name}}/__init__.py: -------------------------------------------------------------------------------- 1 | try: 2 | from {{ cookiecutter.package_name }}._version import version as __version__ 3 | except ImportError: # pragma: no cover 4 | __version__ = "unknown" 5 | -------------------------------------------------------------------------------- /cookiecutter.json: -------------------------------------------------------------------------------- 1 | { 2 | "full_name": "Full Name", 3 | "email": "Email Address", 4 | "github_username": "Destination github org or username", 5 | "repo_name": "repository-name", 6 | "package_name": "{{ cookiecutter.repo_name.lower().replace(' ', '_').replace('-','_') }}", 7 | "project_short_description": "Short description", 8 | "noarch_python": "y", 9 | "include_cli": "y", 10 | "open_source_license": ["MIT", "BSD", "ISC", "Apache", "GNUv3", "Proprietary"] 11 | } 12 | -------------------------------------------------------------------------------- /hooks/post_gen_project.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | 4 | PROJECT_DIRECTORY = os.path.realpath(os.path.curdir) 5 | 6 | 7 | def remove_file(filepath): 8 | os.remove(os.path.join(PROJECT_DIRECTORY, filepath)) 9 | 10 | 11 | if __name__ == '__main__': 12 | 13 | if '{{ cookiecutter.open_source_license }}' == 'Proprietary': 14 | remove_file('LICENSE') 15 | 16 | if '{{ cookiecutter.include_cli }}' != 'y': 17 | remove_file('src/{{ cookiecutter.package_name }}/__main__.py') 18 | remove_file('src/{{ cookiecutter.package_name }}/cli.py') 19 | remove_file('tests/test_cli.py') 20 | -------------------------------------------------------------------------------- /.github/workflows/project.yml: -------------------------------------------------------------------------------- 1 | name: Add to Project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | pull_request_target: 8 | types: 9 | - opened 10 | 11 | jobs: 12 | add_to_project: 13 | if: '!github.event.repository.fork' 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 17 | with: 18 | # issues are added to the Planning project 19 | # PRs are added to the Review project 20 | project-url: https://github.com/orgs/conda/projects/${{ github.event_name == 'issues' && 2 || 16 }} 21 | github-token: ${{ secrets.PROJECT_TOKEN }} 22 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/README.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | {{ cookiecutter.package_name }} 3 | =============================== 4 | 5 | 6 | .. image:: https://img.shields.io/travis/{{ cookiecutter.github_username }}/{{ cookiecutter.repo_name }}.svg 7 | :target: https://travis-ci.org/{{ cookiecutter.github_username }}/{{ cookiecutter.repo_name }} 8 | .. image:: https://circleci.com/gh/{{ cookiecutter.github_username }}/{{ cookiecutter.repo_name }}.svg?style=svg 9 | :target: https://circleci.com/gh/{{ cookiecutter.github_username }}/{{ cookiecutter.repo_name }} 10 | .. image:: https://codecov.io/gh/{{ cookiecutter.github_username }}/{{ cookiecutter.repo_name }}/branch/master/graph/badge.svg 11 | :target: https://codecov.io/gh/{{ cookiecutter.github_username }}/{{ cookiecutter.repo_name }} 12 | 13 | 14 | {{ cookiecutter.project_short_description }} 15 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 3 | 4 | ### Description 5 | 6 | 10 | 11 | 12 | 13 | 23 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/.travis.yml: -------------------------------------------------------------------------------- 1 | # Config file for automatic testing at travis-ci.org 2 | 3 | language: python 4 | python: 5 | - "2.7" 6 | - "3.6" 7 | 8 | install: 9 | - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then 10 | wget https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh -O miniconda.sh; 11 | else 12 | wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; 13 | fi 14 | - bash miniconda.sh -b -p $HOME/miniconda 15 | - export PATH="$HOME/miniconda/bin:$PATH" 16 | - hash -r 17 | - conda config --set always_yes yes 18 | - conda update -q conda 19 | - conda install conda-build anaconda-client pytest pytest-cov 20 | - conda config --set auto_update_conda no 21 | - conda build conda.recipe --no-test 22 | - conda install --use-local {{ cookiecutter.package_name }} 23 | - conda info -a 24 | script: 25 | - pytest -v --color=yes --cov={{ cookiecutter.package_name }} tests 26 | after_success: 27 | - conda install -c conda-forge codecov 28 | - codecov 29 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/src/{{cookiecutter.package_name}}/cli.py: -------------------------------------------------------------------------------- 1 | from argparse import ArgumentParser 2 | from typing import Optional, Sequence 3 | from {{ cookiecutter['package_name'] }} import __version__ 4 | 5 | 6 | def cli(args: Optional[Sequence[str]] = None) -> None: 7 | p = ArgumentParser(description="{{ cookiecutter['project_short_description']}}", conflict_handler="resolve") 8 | p.add_argument( 9 | "-V", 10 | "--version", 11 | action="version", 12 | help="Show the conda-prefix-replacement version number and exit.", 13 | version="{{ cookiecutter['package_name']}} %s" % __version__, 14 | ) 15 | 16 | parsed, unknown = p.parse_known_args(args) 17 | 18 | # do something with the args 19 | print("CLI template - fix me up!") 20 | 21 | # No return value means no error. 22 | # Return a value of 1 or higher to signify an error. 23 | # See https://docs.python.org/3/library/sys.html#sys.exit 24 | 25 | 26 | if __name__ == "__main__": 27 | import sys 28 | 29 | cli(sys.argv[1:]) 30 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name='cookiecutter-conda-python', 5 | packages=[], 6 | version='0.1.0', 7 | description='Cookiecutter template for a Python conda package', 8 | author='Continuum Analytics, Inc.', 9 | author_email='conda@continuum.io', 10 | url='https://github.com/conda/cookiecutter-conda-package', 11 | keywords=['cookiecutter', 'template', 'package', 'conda', 'python'], 12 | classifiers=[ 13 | 'Development Status :: 4 - Beta', 14 | 'Environment :: Console', 15 | 'Intended Audience :: Developers', 16 | 'Natural Language :: English', 17 | 'Programming Language :: Python', 18 | 'Programming Language :: Python :: 2', 19 | 'Programming Language :: Python :: 2.7', 20 | 'Programming Language :: Python :: 3', 21 | 'Programming Language :: Python :: 3.4', 22 | 'Programming Language :: Python :: 3.5', 23 | 'Programming Language :: Python :: Implementation :: CPython', 24 | 'Topic :: Software Development', 25 | ], 26 | ) 27 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # This is the configuration for pre-commit, a local framework for managing pre-commit hooks 2 | # Check out the docs at: https://pre-commit.com/ 3 | 4 | exclude: ^(.*/env/.*|envs/.*|src/{{ cookiecutter.package_name }}/_version.py) # Exclude conda environments and version file 5 | 6 | repos: 7 | - repo: https://github.com/pre-commit/pre-commit-hooks 8 | rev: v4.6.0 9 | hooks: 10 | - id: end-of-file-fixer 11 | - id: trailing-whitespace 12 | - repo: https://github.com/astral-sh/ruff-pre-commit 13 | rev: v0.4.3 14 | hooks: 15 | # lint & attempt to correct failures (e.g. pyupgrade) 16 | - id: ruff 17 | args: [--fix] 18 | # compatible replacement for black 19 | - id: ruff-format 20 | - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks 21 | rev: v2.13.0 22 | hooks: 23 | - id: pretty-format-toml 24 | args: [--autofix] 25 | - repo: https://github.com/codespell-project/codespell 26 | rev: v2.2.6 27 | hooks: 28 | - id: codespell 29 | args: [--write] 30 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | # pyenv python configuration file 62 | .python-version 63 | 64 | # hatch-vcs version file 65 | src/{{ cookiecutter.package_name }}/_version.py 66 | -------------------------------------------------------------------------------- /.github/workflows/cla.yml: -------------------------------------------------------------------------------- 1 | name: CLA 2 | 3 | on: 4 | issue_comment: 5 | types: 6 | - created 7 | pull_request_target: 8 | 9 | jobs: 10 | check: 11 | if: >- 12 | !github.event.repository.fork 13 | && ( 14 | github.event.issue.pull_request 15 | && github.event.comment.body == '@conda-bot check' 16 | || github.event_name == 'pull_request_target' 17 | ) 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Check CLA 21 | uses: conda/actions/check-cla@eb545bb8ab48d499b31c057a6df3cf46753fdbcb # v25.3.1 22 | with: 23 | # [required] 24 | # A token with ability to comment, label, and modify the commit status 25 | # (`pull_request: write` and `statuses: write` for fine-grained PAT; `repo` for classic PAT) 26 | # (default: secrets.GITHUB_TOKEN) 27 | token: ${{ secrets.CLA_ACTION_TOKEN }} 28 | # [required] 29 | # Label to apply to contributor's PR once CLA is signed 30 | label: cla-signed 31 | 32 | # [required] 33 | # Token for opening signee PR in the provided `cla_repo` 34 | # (`pull_request: write` for fine-grained PAT; `repo` and `workflow` for classic PAT) 35 | cla_token: ${{ secrets.CLA_FORK_TOKEN }} 36 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: continuumio/miniconda3 6 | 7 | working_directory: ~/repo 8 | 9 | steps: 10 | - checkout 11 | 12 | {% raw %}# - restore_cache: 13 | # keys: 14 | # - v1-dependencies-{{ checksum "environment.yml" }} 15 | # - v1-dependencies-{% endraw %} 16 | 17 | - run: 18 | name: install dependencies 19 | command: | 20 | # conda env create -q || conda env update -q 21 | # source activate adj 22 | conda install -qy conda-build anaconda-client pytest pytest-cov 23 | conda config --set auto_update_conda no 24 | conda info -a 25 | conda build conda.recipe --no-test 26 | conda install --use-local {{ cookiecutter.package_name }} 27 | 28 | {% raw %}# - save_cache: 29 | # paths: 30 | # - /opt/conda 31 | # key: v1-dependencies-{{ checksum "environment.yml" }}{% endraw %} 32 | 33 | - run: 34 | name: run tests 35 | command: | 36 | # source activate adj 37 | pytest --color=yes -v --cov={{ cookiecutter.package_name }} tests 38 | conda install -c conda-forge codecov 39 | codecov 40 | 41 | - store_artifacts: 42 | path: test-reports 43 | destination: test-reports 44 | -------------------------------------------------------------------------------- /.github/workflows/issues.yml: -------------------------------------------------------------------------------- 1 | name: Automate Issues 2 | 3 | on: 4 | # NOTE: github.event is issue_comment payload: 5 | # https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#issue_comment 6 | issue_comment: 7 | types: [created] 8 | 9 | env: 10 | FEEDBACK_LBL: pending::feedback 11 | SUPPORT_LBL: pending::support 12 | 13 | jobs: 14 | # NOTE: will update label if anyone responds, not just the author/reporter 15 | # TODO: create conda-issue-sorting team and modify this to toggle label based on 16 | # whether a non-issue-sorting engineer commented 17 | pending_support: 18 | # if [pending::feedback] and anyone responds 19 | if: >- 20 | !github.event.repository.fork 21 | && !github.event.issue.pull_request 22 | && contains(github.event.issue.labels.*.name, 'pending::feedback') 23 | runs-on: ubuntu-latest 24 | steps: 25 | # remove [pending::feedback] 26 | - uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 # v1.3.0 27 | with: 28 | labels: ${{ env.FEEDBACK_LBL }} 29 | github_token: ${{ secrets.PROJECT_TOKEN }} 30 | # add [pending::support], if still open 31 | - uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf # v1.1.3 32 | if: github.event.issue.state == 'open' 33 | with: 34 | labels: ${{ env.SUPPORT_LBL }} 35 | github_token: ${{ secrets.PROJECT_TOKEN }} 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Conda 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2_documentation.yml: -------------------------------------------------------------------------------- 1 | # edit this in https://github.com/conda/infrastructure 2 | 3 | name: Documentation 4 | description: Create a documentation related issue. 5 | labels: 6 | - type::documentation 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | > [!NOTE] 12 | > Documentation requests that are incomplete or missing information may be closed as inactionable. 13 | 14 | Since there are already a lot of open issues, please also take a moment to search existing ones to see if your bug has already been reported. If you find something related, please upvote that issue and provide additional details as necessary. 15 | 16 | 💐 Thank you for helping to make conda better. We would be unable to improve conda without our community! 17 | - type: checkboxes 18 | id: checks 19 | attributes: 20 | label: Checklist 21 | description: Please confirm and check all of the following options. 22 | options: 23 | - label: I added a descriptive title 24 | required: true 25 | - label: I searched open reports and couldn't find a duplicate 26 | required: true 27 | - type: textarea 28 | id: what 29 | attributes: 30 | label: What happened? 31 | description: Mention here any typos, broken links, or missing, incomplete, or outdated information, etc. that you have noticed in the conda docs or CLI help. 32 | validations: 33 | required: true 34 | - type: textarea 35 | id: context 36 | attributes: 37 | label: Additional Context 38 | description: Include any additional information (or screenshots) that you think would be valuable. 39 | -------------------------------------------------------------------------------- /.github/template-files/config.yml: -------------------------------------------------------------------------------- 1 | conda/governance: 2 | # [required] community files 3 | - CODE_OF_CONDUCT.md 4 | 5 | conda/infrastructure: 6 | # [required] general workflows 7 | - .github/workflows/cla.yml 8 | - .github/workflows/update.yml 9 | 10 | # [optional] to include repo in https://github.com/orgs/conda/projects/2 11 | - .github/workflows/issues.yml 12 | - .github/workflows/labels.yml 13 | - .github/workflows/project.yml 14 | 15 | # [optional] stale bot workflows 16 | - .github/workflows/stale.yml 17 | - .github/workflows/lock.yml 18 | 19 | # [optional] general processes for the conda org 20 | - src: templates/HOW_WE_USE_GITHUB.md 21 | dst: HOW_WE_USE_GITHUB.md 22 | 23 | # [optional] standard issue templates 24 | - src: templates/issues/bug.yml 25 | dst: .github/ISSUE_TEMPLATE/0_bug.yml 26 | 27 | - src: templates/issues/feature.yml 28 | dst: .github/ISSUE_TEMPLATE/1_feature.yml 29 | 30 | - src: templates/issues/documentation.yml 31 | dst: .github/ISSUE_TEMPLATE/2_documentation.yml 32 | 33 | - src: templates/issues/epic.yml 34 | dst: .github/ISSUE_TEMPLATE/epic.yml 35 | 36 | # [optional] standard PR template 37 | # - src: templates/pull_requests/news_tests_docs.md 38 | # dst: .github/template-files/templates/pull_request_template_details.md 39 | - src: templates/pull_requests/base.md 40 | dst: .github/PULL_REQUEST_TEMPLATE.md 41 | 42 | # [optional] rever release files 43 | # - src: templates/releases/RELEASE.md 44 | # dst: RELEASE.md 45 | # with: 46 | # placeholder: YY.M 47 | # - src: templates/releases/rever.xsh 48 | # dst: rever.xsh 49 | # - src: templates/releases/TEMPLATE 50 | # dst: news/TEMPLATE 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | -------------------------------------------------------------------------------- /.github/workflows/labels.yml: -------------------------------------------------------------------------------- 1 | name: Sync Labels 2 | 3 | on: 4 | # NOTE: github.event is workflow_dispatch payload: 5 | # https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#workflow_dispatch 6 | workflow_dispatch: 7 | inputs: 8 | delete-unmapped: 9 | description: Delete labels not mapped in either global or local label configurations. 10 | default: false 11 | type: boolean 12 | 13 | dry-run: 14 | description: Run label synchronization workflow without making any changes. 15 | default: false 16 | type: boolean 17 | 18 | jobs: 19 | sync: 20 | if: '!github.event.repository.fork' 21 | runs-on: ubuntu-latest 22 | env: 23 | GLOBAL: https://raw.githubusercontent.com/conda/infra/main/.github/global.yml 24 | LOCAL: .github/labels.yml 25 | steps: 26 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 27 | 28 | - id: has_local 29 | uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0 30 | with: 31 | files: ${{ env.LOCAL }} 32 | 33 | - name: Global Only 34 | uses: EndBug/label-sync@52074158190acb45f3077f9099fea818aa43f97a # v2.3.3 35 | if: steps.has_local.outputs.files_exists == 'false' 36 | with: 37 | config-file: ${{ env.GLOBAL }} 38 | delete-other-labels: ${{ inputs.delete-unmapped }} 39 | dry-run: ${{ inputs.dry-run }} 40 | 41 | - name: Global & Local 42 | uses: EndBug/label-sync@52074158190acb45f3077f9099fea818aa43f97a # v2.3.3 43 | if: steps.has_local.outputs.files_exists == 'true' 44 | with: 45 | config-file: | 46 | ${{ env.GLOBAL }} 47 | ${{ env.LOCAL }} 48 | delete-other-labels: ${{ inputs.delete-unmapped }} 49 | dry-run: ${{ inputs.dry-run }} 50 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/0_bug.yml: -------------------------------------------------------------------------------- 1 | # edit this in https://github.com/conda/infrastructure 2 | 3 | name: Bug Report 4 | description: Create a bug report. 5 | labels: 6 | - type::bug 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Because processing new bug reports is time-consuming, we would like to ask you to fill out the following form to the best of your ability and as completely as possible. 12 | 13 | > [!NOTE] 14 | > Bug reports that are incomplete or missing information may be closed as inactionable. 15 | 16 | Since there are already a lot of open issues, please also take a moment to search existing ones to see if your bug has already been reported. If you find something related, please upvote that issue and provide additional details as necessary. 17 | 18 | 💐 Thank you for helping to make `conda/cookiecutter-conda-python` better. We would be unable to improve `conda/cookiecutter-conda-python` without our community! 19 | - type: checkboxes 20 | id: checks 21 | attributes: 22 | label: Checklist 23 | description: Please confirm and check all of the following options. 24 | options: 25 | - label: I added a descriptive title 26 | required: true 27 | - label: I searched open reports and couldn't find a duplicate 28 | required: true 29 | - type: textarea 30 | id: what 31 | attributes: 32 | label: What happened? 33 | description: What should have happened instead? Please provide as many details as possible. The more information provided, the more likely we are able to replicate your problem and offer a solution. 34 | validations: 35 | required: true 36 | 37 | - type: textarea 38 | id: context 39 | attributes: 40 | label: Additional Context 41 | description: Include any additional information (or screenshots) that you think would be valuable. 42 | -------------------------------------------------------------------------------- /.github/workflows/lock.yml: -------------------------------------------------------------------------------- 1 | name: Lock 2 | 3 | on: 4 | # NOTE: github.event is workflow_dispatch payload: 5 | # https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#workflow_dispatch 6 | workflow_dispatch: 7 | 8 | schedule: 9 | - cron: 0 6 * * * 10 | 11 | permissions: 12 | issues: write 13 | pull-requests: write 14 | 15 | jobs: 16 | lock: 17 | if: '!github.event.repository.fork' 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5.0.1 21 | with: 22 | # Number of days of inactivity before a closed issue is locked 23 | issue-inactive-days: 180 24 | # Do not lock issues created before a given timestamp, value must follow ISO 8601 25 | exclude-issue-created-before: '' 26 | # Do not lock issues with these labels, value must be a comma separated list of labels or '' 27 | exclude-any-issue-labels: '' 28 | # Labels to add before locking an issue, value must be a comma separated list of labels or '' 29 | add-issue-labels: locked 30 | # Reason for locking an issue, value must be one of resolved, off-topic, too heated, spam or '' 31 | issue-lock-reason: resolved 32 | # Number of days of inactivity before a closed pull request is locked 33 | pr-inactive-days: 365 34 | # Do not lock pull requests created before a given timestamp, value must follow ISO 8601 35 | exclude-pr-created-before: '' 36 | # Do not lock pull requests with these labels, value must be a comma separated list of labels or '' 37 | exclude-any-pr-labels: '' 38 | # Labels to add before locking a pull request, value must be a comma separated list of labels or '' 39 | add-pr-labels: locked 40 | # Reason for locking a pull request, value must be one of resolved, off-topic, too heated, spam or '' 41 | pr-lock-reason: resolved 42 | 43 | # Limit locking to issues, pull requests or discussions, value must be a comma separated list of issues, prs, discussions or '' 44 | process-only: issues, prs 45 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1_feature.yml: -------------------------------------------------------------------------------- 1 | # edit this in https://github.com/conda/infrastructure 2 | 3 | name: Feature Request 4 | description: Create a feature request. 5 | labels: 6 | - type::feature 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Because processing new feature requests is time-consuming, we would like to ask you to fill out the following form to the best of your ability and as completely as possible. 12 | 13 | > [!NOTE] 14 | > Feature requests that are incomplete or missing information may be closed as inactionable. 15 | 16 | Since there are already a lot of open issues, please also take a moment to search existing ones to see if your feature request has already been submitted. If you find something related, please upvote that issue and provide additional details as necessary. 17 | 18 | 💐 Thank you for helping to make `conda/cookiecutter-conda-python` better. We would be unable to improve `conda/cookiecutter-conda-python` without our community! 19 | - type: checkboxes 20 | id: checks 21 | attributes: 22 | label: Checklist 23 | description: Please confirm and check all of the following options. 24 | options: 25 | - label: I added a descriptive title 26 | required: true 27 | - label: I searched open requests and couldn't find a duplicate 28 | required: true 29 | - type: textarea 30 | id: idea 31 | attributes: 32 | label: What is the idea? 33 | description: Describe what the feature is and the desired state. 34 | validations: 35 | required: true 36 | - type: textarea 37 | id: why 38 | attributes: 39 | label: Why is this needed? 40 | description: Who would benefit from this feature? Why would this add value to them? What problem does this solve? 41 | - type: textarea 42 | id: what 43 | attributes: 44 | label: What should happen? 45 | description: What should be the user experience with the feature? Describe from a user perspective what they would do and see. 46 | - type: textarea 47 | id: context 48 | attributes: 49 | label: Additional Context 50 | description: Include any additional information that you think would be valuable. 51 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | global: 3 | # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the 4 | # /E:ON and /V:ON options are not enabled in the batch script interpreter 5 | # See: http://stackoverflow.com/a/13751649/163740 6 | CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\tools\\appveyor\\run_with_env.cmd" 7 | 8 | matrix: 9 | - PYTHON: "C:\\Miniconda36-x64" 10 | PYTHON_VERSION: "3.6" 11 | PYTHON_ARCH: "64" 12 | 13 | - PYTHON: "C:\\Miniconda-x64" 14 | PYTHON_VERSION: "2.7" 15 | PYTHON_ARCH: "64" 16 | 17 | init: 18 | - ECHO %PYTHON% %PYTHON_VERSION% %PYTHON_ARCH% %HOME% 19 | 20 | 21 | install: 22 | # If there is a newer build queued for the same PR, cancel this one. 23 | # The AppVeyor 'rollout builds' option is supposed to serve the same 24 | # purpose but it is problematic because it tends to cancel builds pushed 25 | # directly to master instead of just PR builds (or the converse). 26 | # credits: JuliaLang developers. 27 | - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` 28 | https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` 29 | Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` 30 | throw "There are newer queued builds for this pull request, failing early." } 31 | # these correspond to folder naming of miniconda installs on appveyor. See 32 | # https://www.appveyor.com/docs/installed-software#python 33 | - if "%PYTHON_VERSION%" == "3.6" set "BASE_PYTHON_VERSION=36" 34 | - if "%PYTHON_ARCH%" == "64" set "ARCH_LABEL=-x64" 35 | - call "C:\Miniconda%BASE_PYTHON_VERSION%%ARCH_LABEL%\Scripts\activate.bat" 36 | - conda config --set always_yes yes 37 | - conda update -q conda 38 | - conda config --set auto_update_conda no 39 | - conda update -q --all 40 | - conda install -q pytest pytest-cov conda-build anaconda-client 41 | - conda info 42 | # this is to ensure dependencies 43 | - conda build conda.recipe --no-test 44 | - conda install --use-local {{ cookiecutter.package_name }} 45 | 46 | 47 | # Not a .NET project, we build package in the install step instead 48 | build: false 49 | 50 | test_script: 51 | - py.test --color=yes -v --cov {{ cookiecutter.package_name }} --cov-report xml tests 52 | 53 | on_success: 54 | - conda install -c conda-forge codecov 55 | - codecov --env PYTHON_VERSION --file C:\projects\{{ cookiecutter.repo_name }}\coverage.xml 56 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/conda.recipe/meta.yaml: -------------------------------------------------------------------------------- 1 | {# raw is for ignoring templating with cookiecutter, leaving it for use with conda-build -#} 2 | {% raw -%} 3 | {% set pyproject = load_file_data('../pyproject.toml', from_recipe_dir=True) %} 4 | {% set version = VERSION %} 5 | {% set project = pyproject['project'] %} 6 | {%- endraw %} 7 | 8 | package: 9 | name: {{ cookiecutter.package_name.replace('_', '-') }} 10 | {% raw -%} 11 | version: {{ version }} 12 | {%- endraw %} 13 | 14 | source: 15 | path: .. 16 | 17 | build: 18 | # If the installation is complex, or different between Unix and Windows, use 19 | # separate bld.bat and build.sh files instead of this key. Add the line 20 | # "skip: True # [py<35]" (for example) to limit to Python 3.5 and newer, or 21 | # "skip: True # [not win]" to limit to Windows. 22 | {% raw -%} 23 | script: {{ PYTHON }} -m pip install --no-build-isolation --no-deps --ignore-installed -vv . 24 | {%- endraw %} 25 | {% if cookiecutter.noarch_python == 'y' -%} 26 | noarch: python{% endif %} 27 | number: 0 28 | {% if cookiecutter.include_cli == 'y' -%}{% raw -%}entry_points: 29 | {% for name, reference in project['scripts'].items() %} 30 | - {{ name }} = {{ reference }} 31 | {% endfor %}{%- endraw %}{% endif %} 32 | 33 | requirements: 34 | # if you need compilers, uncomment these 35 | # read more at https://docs.conda.io/projects/conda-build/en/latest/resources/compiler-tools.html 36 | # build: 37 | {% raw -%} 38 | # - {{ compilers('c') }} 39 | {%- endraw %} 40 | host: 41 | {% raw -%} 42 | - python {{ project['requires-python'] }} 43 | - pip 44 | {% for dep in pyproject['build-system']['requires'] %} 45 | - {{ dep.lower() }} 46 | {% endfor %} 47 | {%- endraw %} 48 | run: 49 | {% raw -%} 50 | - python {{ project['requires-python'] }} 51 | {% for dep in project['dependencies'] %} 52 | - {{ dep.lower() }} 53 | {% endfor %} 54 | {%- endraw %} 55 | 56 | test: 57 | imports: 58 | - {{ cookiecutter.package_name }} 59 | source_files: 60 | - tests 61 | requires: 62 | {% raw -%} 63 | {% for dep in project['optional-dependencies']['test'] %} 64 | - {{ dep.lower() }} 65 | {% endfor %} 66 | {%- endraw %} 67 | commands: 68 | - pytest 69 | {% if cookiecutter.include_cli == 'y' -%} 70 | {% raw -%} 71 | {% for name in project['scripts'] %} 72 | - {{ name }} 73 | {% endfor %}{%- endraw %}{% endif %} 74 | - python -c "from {{ cookiecutter.package_name }} import __version__; assert __version__ == \"{% raw %}{{ version }}{%- endraw %}\"" 75 | 76 | about: 77 | home: https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.repo_name }} 78 | summary: {{ cookiecutter.project_short_description }} 79 | {% raw -%} 80 | license: {{ pyproject.get('license') }} 81 | {%- endraw %} 82 | license_file: LICENSE 83 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | build-backend = "hatchling.build" 3 | requires = ["hatchling", "hatch-vcs>=0.3", "setuptools-scm>=7.1"] 4 | 5 | [project] 6 | authors = [ 7 | {name = "{{ cookiecutter.full_name.replace('\"', '\\\"') }}", email = "{{ cookiecutter.email }}"} 8 | ] 9 | classifiers = [ 10 | "Programming Language :: Python", 11 | "Programming Language :: Python :: 3 :: Only", 12 | "Programming Language :: Python :: 3.9", 13 | "Programming Language :: Python :: 3.10", 14 | "Programming Language :: Python :: 3.11", 15 | "Programming Language :: Python :: 3.12", 16 | "Programming Language :: Python :: Implementation :: CPython", 17 | "Topic :: Software Development :: Libraries :: Python Modules" 18 | ] 19 | dependencies = [ 20 | # package requirements go here 21 | ] 22 | description = "{{ cookiecutter.project_short_description }}" 23 | dynamic = ["version"] 24 | license = {text = "{{ cookiecutter.open_source_license }}"} 25 | name = "{{ cookiecutter.repo_name }}" 26 | readme = "README.rst" 27 | requires-python = ">=3.9" 28 | 29 | [project.optional-dependencies] 30 | test = [ 31 | "pytest", 32 | "pytest-cov", 33 | "mypy" 34 | ] 35 | 36 | {% if cookiecutter.include_cli == "y" -%} 37 | [project.scripts] 38 | {{ cookiecutter.repo_name }} = "{{ cookiecutter.package_name }}.cli:cli" 39 | {%- endif %} 40 | 41 | [project.urls] 42 | repository = "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.repo_name }}" 43 | 44 | [tool.coverage.report] 45 | exclude_lines = [ 46 | "pragma: no cover", 47 | # This covers both typing.TYPE_CHECKING and plain TYPE_CHECKING, with any amount of whitespace 48 | "if\\s+(typing\\.)?TYPE_CHECKING:", 49 | 'if __name__ == "__main__":' 50 | ] 51 | omit = [ 52 | "src/{{ cookiecutter.package_name }}/__main__.py", 53 | "src/{{ cookiecutter.package_name }}/_version.py", 54 | "tests/*" 55 | ] 56 | 57 | [tool.distutils.bdist_wheel] 58 | universal = true 59 | 60 | [tool.hatch.build.hooks.vcs] 61 | version-file = "src/{{ cookiecutter.package_name }}/_version.py" 62 | 63 | [tool.hatch.build.targets.sdist] 64 | include = [ 65 | "/src/{{ cookiecutter.package_name }}", 66 | "/pyproject.toml" 67 | ] 68 | 69 | [tool.hatch.version] 70 | source = "vcs" 71 | 72 | [tool.mypy] 73 | disallow_untyped_defs = true 74 | files = ["src/{{ cookiecutter.package_name }}/**/*.py"] 75 | python_version = "3.9" 76 | warn_no_return = true 77 | 78 | [tool.pytest.ini_options] 79 | addopts = [ 80 | "-vv", 81 | "--color=yes", 82 | "--cov-append", 83 | "--cov-branch", 84 | "--cov-report=term-missing", 85 | "--cov={{ cookiecutter.package_name }}", 86 | "--tb=native", 87 | "--strict-markers", 88 | "--durations=20" 89 | ] 90 | markers = [ 91 | "serial: execute test serially (to avoid race conditions)", 92 | "slow: tests can take a long time (deselect with '-m \"not slow\"')" 93 | ] 94 | norecursedirs = [".*", "*.egg*", "build", "dist", "conda.recipe", "examples", "env", "envs", "scripts"] 95 | -------------------------------------------------------------------------------- /tests/test_template.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import tomli 3 | 4 | 5 | @pytest.fixture 6 | def context(): 7 | """Test template creation with test parameters.""" 8 | return { 9 | "full_name": "test name", 10 | "email": "test@email.com", 11 | "github_username": "test_username", 12 | "repo_name": "test-repo", 13 | "package_name": "test_repo", 14 | "project_short_description": "Test description." 15 | } 16 | 17 | 18 | def test_template(cookies, context): 19 | """Test the template for proper creation. 20 | 21 | cookies is a fixture provided by the pytest-cookies 22 | plugin. Its bake() method creates a temporary directory 23 | and installs the cookiecutter template into that directory. 24 | """ 25 | result = cookies.bake(extra_context=context) 26 | 27 | assert result.exit_code == 0 28 | assert result.exception is None 29 | assert result.project.basename == "test-repo" 30 | assert result.project.isdir() 31 | assert result.project.join("src", context["package_name"]).isdir() 32 | assert result.project.join("src", context["package_name"], "__init__.py").exists() 33 | 34 | 35 | def test_has_license(cookies, context): 36 | context["open_source_license"] = "BSD" 37 | result = cookies.bake(extra_context=context) 38 | assert result.exit_code == 0 39 | assert result.exception is None 40 | assert result.project.join("LICENSE").check(file=1) 41 | 42 | 43 | def test_no_license(cookies, context): 44 | context["open_source_license"] = "Proprietary" 45 | result = cookies.bake(extra_context=context) 46 | assert result.exit_code == 0 47 | assert result.exception is None 48 | assert not result.project.join("LICENSE").check(file=1) 49 | 50 | 51 | def test_no_noarch(cookies, context): 52 | context["noarch_python"] = "n" 53 | result = cookies.bake(extra_context=context) 54 | assert result.exit_code == 0 55 | assert result.exception is None 56 | with result.project.join("conda.recipe", "meta.yaml").open() as f: 57 | recipe = f.read() 58 | assert "noarch: python" not in recipe 59 | 60 | 61 | def test_no_cli(cookies, context): 62 | context["include_cli"] = "n" 63 | result = cookies.bake(extra_context=context) 64 | assert result.exit_code == 0 65 | assert result.exception is None 66 | with result.project.join("conda.recipe", "meta.yaml").open() as f: 67 | recipe = f.read() 68 | assert "entry_points" not in recipe 69 | 70 | with result.project.join("pyproject.toml").open("rb") as f: 71 | pyproject = tomli.load(f) 72 | 73 | assert not pyproject.get("project", {}).get("scripts", []) 74 | assert not result.project.join("tests/test_cli.py").check(file=1) 75 | assert not result.project.join(context["repo_name"], "src", context["package_name"], "cli.py").check(file=1) 76 | assert not result.project.join(context["repo_name"], "src", context["package_name"], "__main__.py").check(file=1) 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cookiecutter-conda-python 2 | A [cookiecutter](https://www.github.com/audreyr/cookiecutter "cookiecutter") template for 3 | conda packages using Python 4 | 5 | ## Features 6 | 7 | - Modern build system using [pyproject.toml](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/) and [hatchling](https://pypi.org/project/hatchling/) build backend 8 | - Automatic versioning with [hatch-vcs](https://pypi.org/project/hatch-vcs/) (requires git annotated tags before it'll work) 9 | - Ready-made conda recipe found in conda.recipe/meta.yaml 10 | - It reads the pyproject.toml file for almost all metadata. You will likely not need to modify it 11 | - You will need to set the `VERSION` env var to the output of `hatch version` to build the package 12 | - [pre-commit](https://pre-commit.com/) config for automatic linting with every git commit 13 | - Pre-configured for Appveyor, Travis CI and Circle CI (you need to activate each of these individually) 14 | - Coverage report hosted on Codecov.io (activated after first successful CI run, which uploads results) 15 | - Code analysis with codacy, setup to exclude version file and tests (requires activation of project at Codacy) 16 | 17 | ## Installation 18 | 19 | Prior to installing cookiecutter-conda-python, the cookiecutter package must be installed in your environment. This is achieved via the following command:: 20 | 21 | conda install cookiecutter 22 | 23 | With cookiecutter installed, the cookiecutter-conda-python template can be installed with:: 24 | 25 | cookiecutter https://github.com/conda/cookiecutter-conda-python.git 26 | 27 | Once cookiecutter clones the template, you will be asked a series of questions related to your project:: 28 | 29 | [1/9] full_name (Full Name): (required) 30 | [2/9] email (Email Address): (required) 31 | [3/9] github_username (Destination github org or username): (required) 32 | [4/9] repo_name (repository-name): (required) 33 | [5/9] package_name (test_pkg): (optional, autogenerated from repository-name) 34 | [6/9] project_short_description (Short description): (optional) 35 | [7/9] noarch_python (y): (optional, default yes) 36 | [8/9] include_cli (y): (optional, default yes) 37 | [9/9] Select open_source_license 38 | 1 - MIT 39 | 2 - BSD 40 | 3 - ISC 41 | 4 - Apache 42 | 5 - GNUv3 43 | 6 - Proprietary 44 | Choose from [1/2/3/4/5/6] (1): (optional, default 1) 45 | 46 | ## Usage 47 | 48 | After answering the questions asked during installation, a conda Python package will be 49 | created in your current working directory. This package will contain a simple CLI script 50 | and the conda recipe necessary to build the application into a conda package. 51 | 52 | You will need to have conda-build, hatch, hatchling, and hatch-vcs to build:: 53 | 54 | conda install conda-build hatch hatchling hatch-vcs 55 | 56 | To build the conda package, be sure to set `VERSION` 57 | 58 | VERSION=`hatch version` conda build conda.recipe/ 59 | 60 | You'll still need to activate the web services you want to use - they won't be active automatically. 61 | 62 | - __Appveyor__: https://www.appveyor.com/docs/ 63 | - __Circle CI__: https://circleci.com/docs/2.0/#setting-up-your-build-on-circleci 64 | - __Travis CI__: https://docs.travis-ci.com/user/getting-started/#To-get-started-with-Travis-CI 65 | - __Codecov__: No configuration necessary - project will be created when first successful CI run completes and uploads coverage results 66 | - __Codacy__: https://support.codacy.com/hc/en-us/articles/207278449-Getting-started-with-Codacy 67 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/epic.yml: -------------------------------------------------------------------------------- 1 | # edit this in https://github.com/conda/infrastructure 2 | 3 | name: Epic 4 | description: A collection of related tickets. 5 | labels: 6 | - epic 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | This form is intended for grouping and collecting together related tickets to better gauge the scope of a problem/feature. 12 | 13 | If you are attempting to report a bug, propose a new feature, or some other code change please use one of the other forms available. 14 | 15 | > [!NOTE] 16 | > Epics that are incomplete or missing information may be closed as inactionable. 17 | 18 | Since there are already a lot of open issues, please also take a moment to search existing ones to see if a similar epic has already been opened. If you find something related, please upvote that issue and provide additional details as necessary. 19 | 20 | 💐 Thank you for helping to make `conda/cookiecutter-conda-python` better. We would be unable to improve `conda/cookiecutter-conda-python` without our community! 21 | 22 | - type: checkboxes 23 | id: checks 24 | attributes: 25 | label: Checklist 26 | description: Please confirm and check all of the following options. 27 | options: 28 | - label: I added a descriptive title 29 | required: true 30 | - label: I searched open issues and couldn't find a duplicate 31 | required: true 32 | 33 | - type: textarea 34 | id: what 35 | attributes: 36 | label: What? 37 | description: >- 38 | What feature or problem will be addressed in this epic? 39 | placeholder: Please describe here. 40 | validations: 41 | required: true 42 | 43 | - type: textarea 44 | id: why 45 | attributes: 46 | label: Why? 47 | description: >- 48 | Why is the reported issue(s) a problem, or why is the proposed feature needed? 49 | (Research and spike issues can be linked here.) 50 | value: | 51 | - [ ] 52 | placeholder: Please describe here and/or link to relevant supporting issues. 53 | validations: 54 | required: true 55 | 56 | - type: textarea 57 | id: user_impact 58 | attributes: 59 | label: User impact 60 | description: >- 61 | In what specific way(s) will users benefit from this change? (e.g. use cases or performance improvements) 62 | placeholder: Please describe here. 63 | validations: 64 | required: true 65 | 66 | - type: textarea 67 | id: goals 68 | attributes: 69 | label: Goals 70 | description: >- 71 | What goal(s) should this epic accomplish? 72 | value: | 73 | - [ ] 74 | validations: 75 | required: true 76 | 77 | - type: textarea 78 | id: tasks 79 | attributes: 80 | label: Tasks 81 | description: >- 82 | What needs to be done to implement this change? 83 | value: | 84 | - [ ] 85 | validations: 86 | required: false 87 | 88 | - type: textarea 89 | id: blocked_by 90 | attributes: 91 | label: 'This epic is blocked by:' 92 | description: >- 93 | Epics and issues that block this epic. 94 | value: | 95 | - [ ] 96 | validations: 97 | required: false 98 | 99 | - type: textarea 100 | id: blocks 101 | attributes: 102 | label: 'This epic blocks:' 103 | description: >- 104 | Epics and issues that are blocked by this epic. 105 | value: | 106 | - [ ] 107 | validations: 108 | required: false 109 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Stale 2 | 3 | on: 4 | # NOTE: github.event is workflow_dispatch payload: 5 | # https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#workflow_dispatch 6 | workflow_dispatch: 7 | inputs: 8 | dryrun: 9 | description: 'dryrun: Preview stale issues/prs without marking them (true|false)' 10 | required: true 11 | type: boolean 12 | default: true 13 | 14 | schedule: 15 | - cron: 0 4 * * * 16 | 17 | permissions: 18 | issues: write 19 | pull-requests: write 20 | 21 | jobs: 22 | stale: 23 | if: '!github.event.repository.fork' 24 | runs-on: ubuntu-latest 25 | strategy: 26 | matrix: 27 | include: 28 | - only-issue-labels: '' 29 | days-before-issue-stale: 365 30 | days-before-issue-close: 30 31 | # [type::support] issues have a more aggressive stale/close timeline 32 | - only-issue-labels: type::support 33 | days-before-issue-stale: 90 34 | days-before-issue-close: 21 35 | steps: 36 | - uses: conda/actions/read-yaml@eb545bb8ab48d499b31c057a6df3cf46753fdbcb # v25.3.1 37 | id: read_yaml 38 | with: 39 | path: https://raw.githubusercontent.com/conda/infra/main/.github/messages.yml 40 | 41 | - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 42 | id: stale 43 | with: 44 | # Only issues with these labels are checked whether they are stale 45 | only-issue-labels: ${{ matrix.only-issue-labels }} 46 | 47 | # Idle number of days before marking issues stale 48 | days-before-issue-stale: ${{ matrix.days-before-issue-stale }} 49 | # Idle number of days before closing stale issues/PRs 50 | days-before-issue-close: ${{ matrix.days-before-issue-close }} 51 | # Idle number of days before marking PRs stale 52 | days-before-pr-stale: 365 53 | # Idle number of days before closing stale PRs 54 | days-before-pr-close: 30 55 | 56 | # Comment on the staled issues 57 | stale-issue-message: ${{ fromJSON(steps.read_yaml.outputs.value)['stale-issue'] }} 58 | # Label to apply on staled issues 59 | stale-issue-label: stale 60 | # Label to apply on closed issues 61 | close-issue-label: stale::closed 62 | # Reason to use when closing issues 63 | close-issue-reason: not_planned 64 | 65 | # Comment on the staled PRs 66 | stale-pr-message: ${{ fromJSON(steps.read_yaml.outputs.value)['stale-pr'] }} 67 | # Label to apply on staled PRs 68 | stale-pr-label: stale 69 | # Label to apply on closed PRs 70 | close-pr-label: stale::closed 71 | 72 | # Remove stale label from issues/PRs on updates/comments 73 | remove-stale-when-updated: true 74 | # Add specified labels to issues/PRs when they become unstale 75 | labels-to-add-when-unstale: stale::recovered 76 | # Remove specified labels to issues/PRs when they become unstale 77 | labels-to-remove-when-unstale: stale,stale::closed 78 | 79 | # Max number of operations per run 80 | operations-per-run: ${{ secrets.STALE_OPERATIONS_PER_RUN || 100 }} 81 | # Dry-run 82 | debug-only: ${{ github.event.inputs.dryrun || false }} 83 | # Order to get issues/PRs 84 | ascending: true 85 | # Delete branch after closing a stale PR 86 | delete-branch: false 87 | 88 | # Issues with these labels will never be considered stale 89 | exempt-issue-labels: stale::recovered,epic 90 | # Issues with these labels will never be considered stale 91 | exempt-pr-labels: stale::recovered,epic 92 | # Exempt all issues/PRs with milestones from stale 93 | exempt-all-milestones: true 94 | # Assignees on issues/PRs exempted from stale 95 | exempt-assignees: mingwandroid 96 | 97 | - name: Print outputs 98 | run: echo ${{ join(steps.stale.outputs.*, ',') }} 99 | -------------------------------------------------------------------------------- /.github/workflows/update.yml: -------------------------------------------------------------------------------- 1 | name: Update Repository 2 | 3 | on: 4 | # every Sunday at 00:36 UTC 5 | # https://crontab.guru/#36_2_*_*_0 6 | schedule: 7 | - cron: 36 2 * * 0 8 | 9 | workflow_dispatch: 10 | 11 | issue_comment: 12 | types: 13 | - created 14 | 15 | jobs: 16 | update: 17 | if: >- 18 | !github.event.repository.fork 19 | && ( 20 | github.event_name == 'schedule' 21 | || github.event_name == 'workflow_dispatch' 22 | || ( 23 | github.event_name == 'issue_comment' 24 | && github.event.issue.pull_request 25 | && ( 26 | github.event.comment.body == '@conda-bot render' 27 | || github.event.comment.body == '@conda-bot recreate' 28 | ) 29 | ) 30 | ) 31 | runs-on: ubuntu-latest 32 | steps: 33 | - if: github.event_name == 'issue_comment' 34 | uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 35 | with: 36 | comment-id: ${{ github.event.comment.id }} 37 | reactions: eyes 38 | reactions-edit-mode: replace 39 | token: ${{ secrets.SYNC_TOKEN }} 40 | 41 | - if: github.event.comment.body == '@conda-bot render' 42 | name: Configure git origin 43 | run: | 44 | echo REPOSITORY=$(curl --silent ${{ github.event.issue.pull_request.url }} | jq --raw-output '.head.repo.full_name') >> $GITHUB_ENV 45 | echo REF=$(curl --silent ${{ github.event.issue.pull_request.url }} | jq --raw-output '.head.ref') >> $GITHUB_ENV 46 | 47 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 48 | with: 49 | repository: ${{ env.REPOSITORY || github.repository }} 50 | ref: ${{ env.REF || '' }} 51 | token: ${{ secrets.SYNC_TOKEN }} 52 | 53 | - name: Configure git user 54 | run: | 55 | git config --global user.name 'Conda Bot' 56 | git config --global user.email '18747875+conda-bot@users.noreply.github.com' 57 | 58 | - uses: conda/actions/combine-durations@eb545bb8ab48d499b31c057a6df3cf46753fdbcb # v25.3.1 59 | id: durations 60 | continue-on-error: true 61 | 62 | - uses: conda/actions/template-files@eb545bb8ab48d499b31c057a6df3cf46753fdbcb # v25.3.1 63 | id: templates 64 | continue-on-error: true 65 | 66 | - name: Commit changes 67 | # no-op if there are no updates 68 | continue-on-error: true 69 | run: | 70 | git add . 71 | git commit --message "🤖 updated file(s)" 72 | 73 | - if: github.event.comment.body != '@conda-bot render' 74 | name: Create fork 75 | # no-op if the repository is already forked 76 | run: echo FORK=$(gh repo fork --clone=false --default-branch-only 2>&1 | awk '{print $1}') >> $GITHUB_ENV 77 | env: 78 | GH_TOKEN: ${{ secrets.SYNC_TOKEN }} 79 | 80 | - if: github.event.comment.body != '@conda-bot render' 81 | id: create 82 | # no-op if no commits were made 83 | uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 84 | with: 85 | push-to-fork: ${{ env.FORK }} 86 | token: ${{ secrets.SYNC_TOKEN }} 87 | branch: update 88 | delete-branch: true 89 | title: 🤖 Update infrastructure file(s) 90 | body: | 91 | [update.yml]: ${{ github.server_url }}/${{ github.repository }}/blob/main/.github/workflows/update.yml 92 | 93 | Your friendly repository updater. 94 | 95 | ${{ steps.durations.outputs.summary }} 96 | 97 | ${{ steps.templates.outputs.summary }} 98 | 99 | This PR was triggered by @${{ github.triggering_actor }} via ${{ github.event_name }}. 100 | 101 |
102 | Commands 103 | 104 | Trigger actions by commenting on this PR: 105 | 106 | - `@conda-bot render` will run rendering workflows and commit and push any changes to this PR 107 | - `@conda-bot recreate` will recreate this PR, overwriting any edits that have been made to it 108 | 109 |
110 | 111 | ###### Auto-generated by the [`update.yml`][update.yml] workflow, see ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}. 112 | 113 | - if: github.event.comment.body == '@conda-bot render' 114 | id: update 115 | name: Push changes 116 | run: git push --force-with-lease 117 | 118 | - if: always() && github.event_name == 'issue_comment' 119 | uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 120 | with: 121 | comment-id: ${{ github.event.comment.id }} 122 | reactions: ${{ (steps.create.conclusion == 'success' || steps.update.conclusion == 'success') && 'hooray' || 'confused' }} 123 | reactions-edit-mode: replace 124 | token: ${{ secrets.SYNC_TOKEN }} 125 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/LICENSE: -------------------------------------------------------------------------------- 1 | {% if cookiecutter.open_source_license == 'MIT' -%} 2 | MIT License 3 | 4 | Copyright (c) {% now 'local', '%Y' %}, {{ cookiecutter.full_name }} 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | {% elif cookiecutter.open_source_license == 'BSD' %} 24 | 25 | BSD License 26 | 27 | Copyright (c) {% now 'local', '%Y' %}, {{ cookiecutter.full_name }} 28 | All rights reserved. 29 | 30 | Redistribution and use in source and binary forms, with or without modification, 31 | are permitted provided that the following conditions are met: 32 | 33 | * Redistributions of source code must retain the above copyright notice, this 34 | list of conditions and the following disclaimer. 35 | 36 | * Redistributions in binary form must reproduce the above copyright notice, this 37 | list of conditions and the following disclaimer in the documentation and/or 38 | other materials provided with the distribution. 39 | 40 | * Neither the name of the copyright holder nor the names of its 41 | contributors may be used to endorse or promote products derived from this 42 | software without specific prior written permission. 43 | 44 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 45 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 46 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 47 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 48 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 49 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 50 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 51 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 52 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 53 | OF THE POSSIBILITY OF SUCH DAMAGE. 54 | {% elif cookiecutter.open_source_license == 'ISC' -%} 55 | ISC License 56 | 57 | Copyright (c) {% now 'local', '%Y' %}, {{ cookiecutter.full_name }} 58 | 59 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 60 | 61 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 62 | {% elif cookiecutter.open_source_license == 'Apache' -%} 63 | Apache Software License 2.0 64 | 65 | Copyright (c) {% now 'local', '%Y' %}, {{ cookiecutter.full_name }} 66 | 67 | Licensed under the Apache License, Version 2.0 (the "License"); 68 | you may not use this file except in compliance with the License. 69 | You may obtain a copy of the License at 70 | 71 | http://www.apache.org/licenses/LICENSE-2.0 72 | 73 | Unless required by applicable law or agreed to in writing, software 74 | distributed under the License is distributed on an "AS IS" BASIS, 75 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 76 | See the License for the specific language governing permissions and 77 | limitations under the License. 78 | {% elif cookiecutter.open_source_license == 'GNUv3' -%} 79 | GNU GENERAL PUBLIC LICENSE 80 | Version 3, 29 June 2007 81 | 82 | {{ cookiecutter.project_short_description }} 83 | Copyright (C) {% now 'local', '%Y' %} {{ cookiecutter.full_name }} 84 | 85 | This program is free software: you can redistribute it and/or modify 86 | it under the terms of the GNU General Public License as published by 87 | the Free Software Foundation, either version 3 of the License, or 88 | (at your option) any later version. 89 | 90 | This program is distributed in the hope that it will be useful, 91 | but WITHOUT ANY WARRANTY; without even the implied warranty of 92 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 93 | GNU General Public License for more details. 94 | 95 | You should have received a copy of the GNU General Public License 96 | along with this program. If not, see . 97 | 98 | Also add information on how to contact you by electronic and paper mail. 99 | 100 | You should also get your employer (if you work as a programmer) or school, 101 | if any, to sign a "copyright disclaimer" for the program, if necessary. 102 | For more information on this, and how to apply and follow the GNU GPL, see 103 | . 104 | 105 | The GNU General Public License does not permit incorporating your program 106 | into proprietary programs. If your program is a subroutine library, you 107 | may consider it more useful to permit linking proprietary applications with 108 | the library. If this is what you want to do, use the GNU Lesser General 109 | Public License instead of this License. But first, please read 110 | . 111 | {% endif %} -------------------------------------------------------------------------------- /HOW_WE_USE_GITHUB.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [conda-org]: https://github.com/conda 5 | [sub-team]: https://github.com/conda-incubator/governance#sub-teams 6 | 7 | [project-planning]: https://github.com/orgs/conda/projects/2/views/11 8 | [project-sorting]: https://github.com/orgs/conda/projects/2/views/11 9 | [project-support]: https://github.com/orgs/conda/projects/2/views/12 10 | [project-backlog]: https://github.com/orgs/conda/projects/2/views/13 11 | [project-in-progress]: https://github.com/orgs/conda/projects/2/views/14 12 | 13 | [docs-toc]: https://github.blog/changelog/2021-04-13-table-of-contents-support-in-markdown-files/ 14 | [docs-actions]: https://docs.github.com/en/actions 15 | [docs-saved-reply]: https://docs.github.com/en/get-started/writing-on-github/working-with-saved-replies/creating-a-saved-reply 16 | [docs-commit-signing]: https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits 17 | 18 | [infrastructure]: https://github.com/conda/infrastructure 19 | [workflow-sync]: https://github.com/conda/infrastructure/blob/main/.github/workflows/sync.yml 20 | [workflow-update]: https://github.com/conda/cookiecutter-conda-python/blob/main/.github/workflows/update.yml 21 | [labels-global]: https://github.com/conda/infrastructure/blob/main/.github/global.yml 22 | 23 | 24 | [workflow-cla]: https://github.com/conda/cookiecutter-conda-python/blob/main/.github/workflows/cla.yml 25 | [workflow-issues]: https://github.com/conda/cookiecutter-conda-python/blob/main/.github/workflows/issues.yml 26 | [workflow-labels]: https://github.com/conda/cookiecutter-conda-python/blob/main/.github/workflows/labels.yml 27 | [workflow-lock]: https://github.com/conda/cookiecutter-conda-python/blob/main/.github/workflows/lock.yml 28 | [workflow-project]: https://github.com/conda/cookiecutter-conda-python/blob/main/.github/workflows/project.yml 29 | [workflow-stale]: https://github.com/conda/cookiecutter-conda-python/blob/main/.github/workflows/stale.yml 30 | [labels-local]: https://github.com/conda/cookiecutter-conda-python/blob/main/.github/labels.yml 31 | [labels-page]: https://github.com/conda/cookiecutter-conda-python/labels 32 | 33 | # How We Use GitHub 34 | 35 | This document seeks to outline how we as a community use GitHub Issues to track bugs and feature requests while still catering to development practices & project management (_e.g._, release cycles, feature planning, priority sorting, etc.). 36 | 37 | 38 | **Topics:** 39 | 40 | - [What is "Issue Sorting"?](#what-is-issue-sorting) 41 | - [Issue Sorting Procedures](#issue-sorting-procedures) 42 | - [Commit Signing](#commit-signing) 43 | - [Types of Issues](#types-of-issues) 44 | - [Standard Issue](#standard-issue) 45 | - [Epics](#epics) 46 | - [Spikes](#spikes) 47 | - [Working on Issues](#working-on-issues) 48 | 49 | > [!NOTE] 50 | > This document is written in the style of an FAQ. For easier navigation, use [GitHub's table of contents feature][docs-toc]. 51 | 52 | ## What is "Issue Sorting"? 53 | 54 | > [!NOTE] 55 | > "Issue sorting" is similar to that of "triaging", but we've chosen to use different terminology because "triaging" is a word related to very weighty topics (_e.g._, injuries and war) and we would like to be sensitive to those connotations. Additionally, we are taking a more "fuzzy" approach to sorting (_e.g._, severities may not be assigned, etc.). 56 | 57 | "Issue Sorting" refers to the process of assessing the priority of incoming issues. Below is a high-level diagram of the flow of issues: 58 | 59 | ```mermaid 60 | flowchart LR 61 | subgraph flow_sorting [Issue Sorting] 62 | board_sorting{{Sorting}} 63 | board_support{{Support}} 64 | 65 | board_sorting<-->board_support 66 | end 67 | 68 | subgraph flow_refinement [Refinement] 69 | board_backlog{{Backlog}} 70 | 71 | board_backlog-- refine -->board_backlog 72 | end 73 | 74 | subgraph flow_progress [In Progress] 75 | board_progress{{In Progress}} 76 | end 77 | 78 | state_new(New Issues) 79 | state_closed(Closed) 80 | 81 | state_new-->board_sorting 82 | board_sorting-- investigated -->board_backlog 83 | board_sorting-- duplicates, off-topic -->state_closed 84 | board_support-- resolved, unresponsive -->state_closed 85 | board_backlog-- pending work -->board_progress 86 | board_backlog-- resolved, irrelevant -->state_closed 87 | board_progress-- resolved -->state_closed 88 | ``` 89 | 90 | ### Why sort issues? 91 | 92 | At the most basic "bird's eye view" level, sorted issues will fall into the category of four main priority levels: 93 | 94 | - Do now 95 | - Do sometime 96 | - Provide user support 97 | - Never do (_i.e._, close) 98 | 99 | At its core, sorting enables new issues to be placed into these four categories, which helps to ensure that they will be processed at a velocity similar to or exceeding the rate at which new issues are coming in. One of the benefits of actively sorting issues is to avoid engineer burnout and to make necessary work sustainable; this is done by eliminating a never-ending backlog that has not been reviewed by any maintainers. 100 | 101 | There will always be broad-scope design and architecture implementations that the maintainers will be interested in pursuing; by actively organizing issues, the sorting engineers will be able to more easily track and tackle both specific and big-picture goals. 102 | 103 | ### Who does the sorting? 104 | 105 | Sorting engineers are a conda governance [sub-team][sub-team]; they are a group of community members who are responsible for making decisions regarding closing issues and setting feature work priorities, among other sorting-related tasks. 106 | 107 | ### How do items show up for sorting? 108 | 109 | New issues that are opened in any of the repositories in the [conda GitHub organization][conda-org] will show up in the "Sorting" tab of the [Planning project][project-planning]. There are two [GitHub Actions][docs-actions] workflows utilized for this purpose; [`.github/workflows/issues.yml`][workflow-issues] and [`.github/workflows/project.yml`][workflow-project]. 110 | 111 | The GitHub workflows in the [`conda/infrastructure`][infrastructure] repository are viewed as canonical; the [`.github/workflows/sync.yml` workflow][workflow-sync] pushes any modifications to other repositories from there and individual repositories can pull additional files using the [`.github/workflows/update.yml`][workflow-update] workflow. 112 | 113 | ### What is done about the issues in the "Sorting" tab? 114 | 115 | Issues in the ["Sorting" tab of the project board][project-sorting] are considered ready for the following procedures: 116 | 117 | - Mitigation via short-term workarounds and fixes 118 | - Redirection to the correct project 119 | - Determining if support can be provided for errors and questions 120 | - Closing out of any duplicate/off-topic issues 121 | 122 | The sorting engineers on rotation are not seeking to _resolve_ issues that arise. Instead, the goal is to understand the issue and to determine whether it is legitimate, and then to collect as much relevant information as possible so that the maintainers can make an informed decision about the appropriate resolution schedule. 123 | 124 | Issues will remain in the ["Sorting" tab][project-sorting] as long as the issue is in an investigatory phase (_e.g._, querying the user for more details, asking the user to attempt other workarounds, other debugging efforts, etc.) and are likely to remain in this state the longest, but should still be progressing over the course of 1-2 weeks. 125 | 126 | For more information on the sorting process, see [Issue Sorting Procedures](#issue-sorting-procedures). 127 | 128 | ### When do items move out of the "Sorting" tab? 129 | 130 | Items move out of the ["Sorting" tab][project-sorting] once the investigatory phase described in [What is done about the issues in the "Sorting" tab?](#what-is-done-about-the-issues-in-the-sorting-tab) has concluded and the sorting engineer has enough information to make a decision about the appropriate resolution schedule for the issue. The additional tabs in the project board that the issues can be moved to include the following: 131 | 132 | - **"Support"** - Any issue in the ["Support" tab of the Planning board][project-support] is a request for support and is not a feature request or a bug report. Add the https://github.com/conda/cookiecutter-conda-python/labels/type%3A%3Asupport label to move an issue to this tab. 133 | - **"Backlog"** - The issue has revealed a bug or feature request. We have collected enough details to understand the problem/request and to reproduce it on our own. These issues have been moved into the [Backlog tab of the Planning board][project-backlog] at the end of the sorting rotation during Refinement. Add the https://github.com/conda/cookiecutter-conda-python/labels/backlog label to move an issue to this tab. 134 | - **"Closed"** - The issue was closed due to being a duplicate, being redirected to a different project, was a user error, a question that has been resolved, etc. 135 | 136 | ### Where do work issues go after being sorted? 137 | 138 | Once issues are deemed ready to be worked on, they will be moved to the ["Backlog" tab of the Planning board][project-backlog]. Once actively in progress, the issues will be moved to the ["In Progress" tab of the Planning board][project-in-progress] and then closed out once the work is complete. 139 | 140 | ### What is the purpose of having a "Backlog"? 141 | 142 | Issues are "backlogged" when they have been sorted but not yet earmarked for an upcoming release. 143 | 144 | ### What automation procedures are currently in place? 145 | 146 | Global automation procedures synced out from the [`conda/infrastructure`][infrastructure] repo include: 147 | 148 | - [Marking of issues and pull requests as stale][workflow-stale], resulting in: 149 | - issues marked as https://github.com/conda/cookiecutter-conda-python/labels/type%3A%3Asupport being labeled stale after 21 days of inactivity and being closed after 7 further days of inactivity (that is, closed after 30 inactive days total) 150 | - all other inactive issues (not labeled as https://github.com/conda/cookiecutter-conda-python/labels/type%3A%3Asupport being labeled stale after 365 days of inactivity and being closed after 30 further days of inactivity (that is, closed after an approximate total of 1 year and 1 month of inactivity) 151 | - all inactive pull requests being labeled stale after 365 days of inactivity and being closed after 30 further days of inactivity (that is, closed after an approximate total of 1 year and 1 month of inactivity) 152 | - [Locking of closed issues and pull requests with no further activity][workflow-lock] after 365 days 153 | - [Adding new issues and pull requests to the respective project boards][workflow-project] 154 | - [Indicating an issue is ready for the sorting engineer's attention][workflow-issues] by toggling https://github.com/conda/cookiecutter-conda-python/labels/pending%3A%3Afeedback with https://github.com/conda/cookiecutter-conda-python/labels/pending%3A%3Asupport after a contributor leaves a comment 155 | - [Verifying that contributors have signed the CLA][workflow-cla] before allowing pull requests to be merged; if the contributor hasn't signed the CLA previously, merging is be blocked until a manual review can be done 156 | - [Syncing out templates, labels, workflows, and documentation][workflow-sync] from [`conda/infrastructure`][infrastructure] to the other repositories 157 | 158 | ## Issue Sorting Procedures 159 | 160 | ### How are issues sorted? 161 | 162 | Issues in the ["Sorting" tab of the Planning board][project-sorting] are reviewed by issue sorting engineers, who take rotational sorting shifts. In the process of sorting issues, engineers label the issues and move them to the other tabs of the project board for further action. 163 | 164 | Issues that require input from multiple members of the sorting team will be brought up during refinement meetings in order to understand how those particular issues fit into the short- and long-term roadmap. These meetings enable the sorting engineers to get together to collectively prioritize issues, earmark feature requests for specific future releases (versus a more open-ended backlog), tag issues as ideal for first-time contributors, as well as whether or not to close/reject specific feature requests. 165 | 166 | ### How does labeling work? 167 | 168 | Labeling is a very important means for sorting engineers to keep track of the current state of an issue with regards to the asynchronous nature of communicating with users. Utilizing the proper labels helps to identify the severity of the issue as well as to quickly understand the current state of a discussion. 169 | 170 | Each label has an associated description that clarifies how the label should be used. Hover on the label to see its description. Label colors are used to distinguish labels by category. 171 | 172 | Generally speaking, labels with the same category are considered mutually exclusive, but in some cases labels sharing the same category can occur concurrently, as they indicate qualifiers as opposed to types. For example, we may have the following types, https://github.com/conda/cookiecutter-conda-python/labels/type%3A%3Abug, https://github.com/conda/cookiecutter-conda-python/labels/type%3A%3Afeature, and https://github.com/conda/cookiecutter-conda-python/labels/type%3A%3Adocumentation, where for any one issue there would be _at most_ **one** of these to be defined (_i.e._ an issue should not be a bug _and_ a feature request at the same time). Alternatively, with issues involving specific operating systems (_i.e._, https://github.com/conda/cookiecutter-conda-python/labels/os%3A%3Alinux, https://github.com/conda/cookiecutter-conda-python/labels/os%3A%3Amacos, and https://github.com/conda/cookiecutter-conda-python/labels/os%3A%3Awindows), an issue could be labeled with one or more, depending on the system(s) the issue occurs on. 173 | 174 | Please note that there are also automation policies in place that are affected by labeling. For example, if an issue is labeled as https://github.com/conda/cookiecutter-conda-python/labels/type%3A%3Asupport, that issue will be marked https://github.com/conda/cookiecutter-conda-python/labels/stale after 21 days of inactivity and auto-closed after seven more days without activity (30 inactive days total), which is earlier than issues without this label. See [What automation procedures are currently in place?](#what-automation-procedures-are-currently-in-place) for more details. 175 | 176 | ### What labels are required for each issue? 177 | 178 | At minimum, both `type` and `source` labels should be specified on each issue before moving it from the "Sorting" tab to the "Backlog" tab. All issues that are bugs should also be tagged with a `severity` label. 179 | 180 | The `type` labels are exclusive of each other: each sorted issue should have exactly one `type` label. These labels give high-level information on the issue's classification (_e.g._, bug, feature, tech debt, etc.) 181 | 182 | The `source` labels are exclusive of each other: each sorted issue should have exactly one `source` label. These labels give information on the sub-group to which the issue's author belongs (_e.g._, a partner, a frequent contributor, the wider community, etc.). Through these labels, maintainers gain insight into how well we're meeting the needs of various groups. 183 | 184 | The `severity` labels are exclusive of each other and, while required for the https://github.com/conda/cookiecutter-conda-python/labels/type%3A%bug label, they can also be applied to other types to indicate demand or need. These labels help us to prioritize our work. Severity is not the only factor for work prioritization, but it is an important consideration. 185 | 186 | Please review the descriptions of the `type`, `source`, and `severity` labels on the [labels page][labels-page] prior to use. 187 | 188 | ### How are new labels defined? 189 | 190 | Labels are defined using a scoped syntax with an optional high-level category (_e.g._, `source`, `tag`, `type`, etc.) and a specific topic, much like the following: 191 | 192 | - `[topic]` 193 | - `[category::topic]` 194 | - `[category::topic-phrase]` 195 | 196 | This syntax helps with issue sorting enforcement, as it helps to ensure that sorted issues are, at minimum, categorized by type and source. 197 | 198 | There are a number of labels that have been defined for the different repositories. In order to create a streamlined sorting process, label terminologies are standardized using similar (if not the same) labels. 199 | 200 | ### How are new labels added? 201 | 202 | New **global** labels (_i.e._, labels that apply equally to all repositories within the conda GitHub organization) are added to [`conda/infrastructure`][infrastructure]'s [`.github/global.yml` file][labels-global]; new **local** labels (_i.e._, labels specific to particular repositories) are added to each repository's [`.github/labels.yml` file][labels-local]. All new labels should follow the labeling syntax described in ["How are new labels defined?"](#how-are-new-labels-defined). Global labels are combined with any local labels and these aggregated labels are used by the [`.github/workflows/labels.yml` workflow][workflow-labels] to synchronize the labels available for the repository. 203 | 204 | ### Are there any templates to use as responses for commonly-seen issues? 205 | 206 | Some of the same types of issues appear regularly (_e.g._, issues that are duplicates of others, issues that should be filed in the Anaconda issue tracker, errors that are due to a user's specific setup/environment, etc.). 207 | 208 | Below are some boilerplate responses for the most commonly-seen issues to be sorted: 209 | 210 |
211 | Duplicate Issue 212 | 213 | 214 |
215 | 
216 | This is a duplicate of [link to primary issue]; please feel free to continue the discussion there.
217 | 
218 | 219 | 220 | 221 | > **Warning** 222 | > Apply the https://github.com/conda/cookiecutter-conda-python/labels/duplicate label to the issue being closed and https://github.com/conda/cookiecutter-conda-python/labels/duplicate%3A%3Aprimary to the original issue. 223 | 224 |
225 | 226 |
227 | Anaconda Products 228 | 229 | 230 |
231 | Thank you for filing this issue! Unfortunately, this is off-topic for this repo because it is related to an Anaconda product.
232 | If you are encountering issues with Anaconda products or services, you have several options for receiving community
233 | support:
234 | 
235 | - [Anaconda community forums](https://community.anaconda.cloud)
236 | - [Anaconda issue tracker on GitHub](https://github.com/ContinuumIO/anaconda-issues/issues)
237 | 
238 | 239 | 240 | 241 | > **Warning** 242 | > Apply the https://github.com/conda/cookiecutter-conda-python/labels/off-topic label to these issues before closing them out. 243 | 244 |
245 | 246 |
247 | General Off Topic 248 | 249 |
250 | Unfortunately, this issue is outside the scope of support we offer via GitHub or is not directly related to this project.
251 | Community support can be found elsewhere, though, and we encourage you to explore the following options:
252 | 
253 | - [Conda discourse forum](https://conda.discourse.group/)
254 | - [Community chat channels](https://conda.org/community#chat)
255 | - [Stack Overflow posts tagged "conda"](https://stackoverflow.com/questions/tagged/conda)
256 | 
257 | 258 | 259 | 260 | > **Warning** 261 | > Apply the https://github.com/conda/cookiecutter-conda-python/labels/off-topic label to these issues before closing them out. 262 | 263 |
264 | 265 | 266 | In order to not have to manually type or copy/paste the above repeatedly, note that it's possible to add text for the most commonly-used responses via [GitHub's "Add Saved Reply" option][docs-saved-reply]. 267 | 268 | ## Commit Signing 269 | 270 | For all maintainers, we require commit signing and strongly recommend it for all others wishing to contribute. More information about how to set this up within GitHub can be found here: 271 | 272 | - [GitHub's signing commits docs][docs-commit-signing] 273 | 274 | ## Types of Issues 275 | 276 | ### Standard Issue 277 | 278 | TODO 279 | 280 | ### Epics 281 | 282 | TODO 283 | 284 | ### Spikes 285 | 286 | #### What is a spike? 287 | 288 | "Spike" is a term that is borrowed from extreme programming and agile development. They are used when the **outcome of an issue is unknown or even optional**. For example, when first coming across a problem that has not been solved before, a project may choose to either research the problem or create a prototype in order to better understand it. 289 | 290 | Additionally, spikes represent work that **may or may not actually be completed or implemented**. An example of this are prototypes created to explore possible solutions. Not all prototypes are implemented and the purpose of creating a prototype is often to explore the problem space more. For research-oriented tasks, the end result of this research may be that a feature request simply is not viable at the moment and would result in putting a stop to that work. 291 | 292 | Finally, spikes are usually **timeboxed**. However, given the open source/volunteer nature of our contributions, we do not enforce this for our contributors. When a timebox is set, this means that we are limiting how long we want someone to work on said spike. We do this to prevent contributors from falling into a rabbit hole they may never return from. Instead, we set a time limit to perform work on the spike and then have the assignee report back. If the tasks defined in the spike have not yet been completed, a decision is made on whether it makes sense to perform further work on the spike. 293 | 294 | #### When do I create a spike? 295 | 296 | A spike should be created when we do not have enough information to move forward with solving a problem. That simply means that, whenever we are dealing with unknowns or processes the project team has never encountered before, it may be useful for us to create a spike. 297 | 298 | In day-to-day work, this kind of situation may appear when new bug reports or feature requests come in that deal with problems or technologies that the project team is unfamiliar with. All issues that the project team has sufficient knowledge of should instead proceed as regular issues. 299 | 300 | #### When do I not create a spike? 301 | 302 | Below are some common scenarios where creating a spike is not appropriate: 303 | 304 | - Writing a technical specification for a feature we know how to implement 305 | - Design work that would go into drafting how an API is going to look and function 306 | - Any work that must be completed or is not optional 307 | 308 | ## Working on Issues 309 | 310 | ### How do I assign myself to an issue I am actively reviewing? 311 | 312 | If you do **not** have permissions, please indicate that you are working on an issue by leaving a comment. Someone who has permissions will assign you to the issue. If two weeks have passed without a pull request or an additional comment requesting information, you may be removed from the issue and the issue reassigned. 313 | 314 | If you are assigned to an issue but will not be able to continue work on it, please comment to indicate that you will no longer be working on it and press `unassign me` next to your username in the `Assignees` section of the issue page (top right). 315 | 316 | If you **do** have permissions, please assign yourself to the issue by pressing `assign myself` under the `Assignees` section of the issue page (top right). 317 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Conda Organization Code of Conduct 2 | 3 | # The Short Version 4 | 5 | Be kind to others. Do not insult or put down others. Behave professionally. Remember that harassment and sexist, racist, or exclusionary jokes are not appropriate for the conda Organization. 6 | 7 | All communication should be appropriate for a professional audience including people of many different backgrounds. Sexual language and imagery is not appropriate. 8 | 9 | The conda Organization is dedicated to providing a harassment-free community for everyone, regardless of gender, sexual orientation, gender identity and expression, disability, physical appearance, body size, race, or religion. We do not tolerate harassment of community members in any form. 10 | 11 | Thank you for helping make this a welcoming, friendly community for all. 12 | 13 | ## Report an Incident 14 | 15 | * Report a code of conduct incident [using a form](https://form.jotform.com/221527028480048). 16 | * Report a code of conduct incident via email: [conduct@conda.org](mailto:conduct@conda.org). 17 | * Contact [an individual committee member](#committee-membership) or [CoC event representative](#coc-representatives) to report an incident in confidence. 18 | 19 |   20 | 21 | And now the longer version... 22 | 23 | # Conda Organization Diversity Statement 24 | 25 | The conda Organization welcomes and encourages participation in our community by people of all backgrounds and identities. We are committed to promoting and sustaining a culture that values mutual respect, tolerance, and learning, and we work together as a community to help each other live out these values. 26 | 27 | We have created this diversity statement because we believe that a diverse community is stronger, more vibrant, and produces better software and better science. A diverse community where people treat each other with respect has more potential contributors, more sources for ideas, and fewer shared assumptions that might hinder development or research. 28 | 29 | Although we have phrased the formal diversity statement generically to make it all-inclusive, we recognize that there are specific identities that are impacted by systemic discrimination and marginalization. We welcome all people to participate in the conda Organization community regardless of their identity or background. 30 | 31 | # Conda Organization Code of Conduct: Introduction & Scope 32 | 33 | This code of conduct should be honored by everyone who participates in the conda Organization community. It should be honored in any conda Organization-related activities, by anyone claiming affiliation with the conda Organization, and especially when someone is representing the conda Organization in any role (including as an event volunteer or speaker). 34 | 35 | This code of conduct applies to all spaces managed by the conda Organization, including all public and private mailing lists, issue trackers, wikis, forums, and any other communication channel used by our community. The code of conduct equally applies at conda Organization events and governs standards of behavior for attendees, speakers, volunteers, booth staff, and event sponsors. 36 | 37 | This code is not exhaustive or complete. It serves to distill our understanding of a collaborative, inclusive community culture. Please try to follow this code in spirit as much as in letter, to create a friendly and productive environment that enriches the conda Organization community. 38 | 39 | The conda Organization Code of Conduct follows below. 40 | 41 | # Standards for Behavior 42 | 43 | The conda Organization is a worldwide community. All communication should be appropriate for a professional audience including people of many different backgrounds. 44 | 45 | **Please always be kind and courteous. There's never a need to be mean or rude or disrespectful.** Thank you for helping make this a welcoming, friendly community for all. 46 | 47 | We strive to: 48 | 49 | **Be empathetic, welcoming, friendly, and patient.** We remember that the conda Organization is crafted by human beings who deserve to be treated with kindness and empathy. We work together to resolve conflict and assume good intentions. We may all experience some frustration from time to time, but we do not allow frustration to turn into a personal attack. A community where people feel uncomfortable or threatened is not a productive one. 50 | 51 | **Be collaborative.** Our work depends on the participation of many people, and in turn others depend on our work. Open source communities depend on effective and friendly collaboration to achieve their goals. 52 | 53 | **Be inquisitive.** Nobody knows everything! Asking questions early avoids many problems later, so we encourage questions, although we may direct them to the appropriate forum. We will try hard to be responsive and helpful. 54 | 55 | **Be careful in the words that we choose.** We are careful and respectful in our communication and we take responsibility for our own speech. Be kind to others. Do not insult or put down other members of the community. 56 | 57 | ## Unacceptable Behavior 58 | 59 | We are committed to making participation in this community a harassment-free experience. 60 | 61 | We will not accept harassment or other exclusionary behaviors, such as: 62 | 63 | - The use of sexualized language or imagery 64 | - Excessive profanity (please avoid curse words; people differ greatly in their sensitivity to swearing) 65 | - Posting sexually explicit or violent material 66 | - Violent or intimidating threats or language directed against another person 67 | - Inappropriate physical contact and/or unwelcome sexual attention or sexual comments 68 | - Sexist, racist, or otherwise discriminatory jokes and language 69 | - Trolling or insulting and derogatory comments 70 | - Written or verbal comments which have the effect of excluding people on the basis of membership in a specific group, including level of experience, gender, gender identity and expression, sexual orientation, disability, neurotype, personal appearance, body size, race, ethnicity, age, religion, or nationality 71 | - Public or private harassment 72 | - Sharing private content, such as emails sent privately or non-publicly, or direct message history, without the sender's consent 73 | - Continuing to initiate interaction (such as photography, recording, messaging, or conversation) with someone after being asked to stop 74 | - Sustained disruption of talks, events, or communications, such as heckling of a speaker 75 | - Publishing (or threatening to post) other people's personally identifying information ("doxing"), such as physical or electronic addresses, without explicit permission 76 | - Other unethical or unprofessional conduct 77 | - Advocating for, or encouraging, any of the above behaviors 78 | 79 | The conda Organization prioritizes marginalized people’s safety over privileged people’s comfort. The conda CoC Committee reserves the right not to act on complaints including, but not limited to: 80 | 81 | * ‘Reverse’ -isms, including ‘reverse racism,’ ‘reverse sexism,’ and ‘cisphobia’. 82 | * Reasonable communication of boundaries, such as “leave me alone,” “go away,” or “I’m not discussing this with you.” 83 | * Communicating in a ‘tone’ you don’t find congenial. 84 | * Criticizing racist, sexist, cissexist, or otherwise oppressive behavior or assumptions. 85 | 86 | ## Behavior Outside of conda Organization Spaces 87 | 88 | The CoC Committee does not influence behavior and membership in spaces outside the conda Organization. However, if you are being harassed by a member of the conda community outside our spaces, you may still report it to the CoC Committee. We will take all good-faith reports of harassment by conda community members seriously. This includes harassment outside our spaces and harassment that took place at any point in time. 89 | 90 | The CoC Committee reserves the right to exclude people from conda Organization spaces based on their past behavior, including behavior outside conda Organization spaces and behavior towards people who are not in the conda community. 91 | 92 | # Confidentiality and Public Statements to the Community 93 | 94 | The CoC Committee will keep the identity of the reporter confidential. 95 | 96 | Whenever possible, CoC cases will be reported to the community. The level of detail in reports will vary from case to case. Reports will describe at least the type of infraction that was reported, and the Committee's decision and any action taken. In most cases, the report will not include personally identifiable information. 97 | 98 | # Live Events 99 | 100 | > **If you feel your safety is in jeopardy or the situation is an emergency, we urge you to contact local law enforcement before making a report to the event's Code of Conduct committee members, [representatives](#coc-representatives), or other staff.** (In the U.S., call 911.) 101 | 102 | Live events present particular challenges: 103 | 104 | **Code of conduct reports, and consequences that stem from them, merit a thoughtful and deliberative process. Decisions and consequences matter for the reporter, the reported, and for the community at large. However, many reports, especially at live events, require rapid action to quickly address the behavior being reported.** 105 | 106 | To better support situations where immediate action may be required, these guidelines are used *during* live events: 107 | 108 | * All conda Organization events will have specific, named Code of Conduct contacts for the events. 109 | * The names and contact mechanisms for the Code of Conduct representatives will be clearly and frequently communicated to event participants. 110 | 111 | ## CoC Representatives 112 | 113 | Every conda Organization associated event will have named CoC Committee members or *CoC representatives* that are the first point of contact for that event. Who these people are will be clearly and frequently communicated to event participants. CoC approved representatives are used when there are no committee members participating in the event. 114 | 115 | ## Live Events: Reporting and Actions 116 | At conda Organization events, Code of Conduct committee members or representatives will attempt to gather and write down [information](#what-to-include-in-a-report) from anyone making a verbal report at a live event. Recording the details in writing is exceedingly important in order for us to effectively respond to reports. If event staff write down a report taken verbally, then the person making the report will be asked to review the written report for accuracy. 117 | 118 | For reports made during live events, or in any situation where urgent action is needed: 119 | 120 | * Any two (or more) event organizers, event staff, CoC Committee members or CoC representatives can decide if immediate action is to be taken and what that action is. In exceptionally dangerous situations, this decision can be made by a single person. 121 | * These rapid decisions can be reconsidered during the event as more information becomes available. 122 | * The scope of any rapid decision is limited to the current event / situation. 123 | * The report, any related information, and any decisions and consequences will be reported to the full Code of Conduct Committee as soon as possible. 124 | 125 | The full Code of Conduct Committee will then consider the report using the full timeline and processes defined below. The Committee may decide to apply consequences in other spaces beyond the space where the behavior was reported. 126 | 127 | Potential *immediate* consequences for violating the conda Organization Code of Conduct at a live event include, but are not limited to: 128 | 129 | - Warning the person to cease their behavior and that any further reports will result in sanctions 130 | - Requiring that the person avoid any interaction with, and physical proximity to, the person they are harassing for the remainder of the event 131 | - Ending a talk that violates the policy early 132 | - Not publishing the video or slides of a talk that violated the policy 133 | - Not allowing a speaker who violated the policy to give (further) talks at the event now or in the future 134 | - Immediately ending any event volunteer responsibilities and privileges the reported person holds 135 | - Expelling the person from the event without a refund 136 | - Requiring that the person immediately leave the event and not return 137 | - Any other response that the CoC members, representatives, or event staff deem necessary and appropriate to the situation 138 | 139 | # Reporting Guidelines 140 | 141 | If you believe someone is violating the code of conduct, please report this in a timely manner. Code of conduct violations reduce the value of the community for everyone. The conda Code of Conduct (CoC) Committee and the conda Organization take reports of misconduct very seriously and are committed to preserving and maintaining the welcoming nature of our community. 142 | 143 | > [!NOTE] 144 | > You are also encouraged to reach out to the conda Code of Conduct (CoC) Committee if you want clarification on something, if you notice some borderline behavior, or just have a concern. Send us a note at [conduct@conda.org](mailto:conduct@conda.org). 145 | 146 | All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The conda CoC Committee commits to maintaining confidentiality with regard to the reporter of an incident. 147 | 148 | For possibly unintentional breaches of the code of conduct, you may want to respond to the person and point out this code of conduct (either in public or in private, whatever is most appropriate). If you would prefer not to do that, please report the issue to the conda CoC Committee directly. 149 | 150 | Take care of each other. Alert someone if you notice a dangerous situation, someone in distress, or violations of this code of conduct, even if they seem inconsequential. 151 | 152 | ## How to Submit a Report 153 | 154 | The CoC Committee is committed to promptly addressing any reported issues. If you have experienced or witnessed behavior that violates the conda Organization Code of Conduct, please let us know. 155 | 156 | You can report an incident 157 | 158 | * via the **[Incident Reporting Form](https://form.jotform.com/221527028480048)** 159 | * via email: [conduct@conda.org](mailto:conduct@conda.org) 160 | * contact [an individual committee member](#committee-membership) or [CoC event representative](#coc-representatives) to report an incident in confidence. 161 | 162 | Reports submitted via the form or committee email address are sent to the [full conda Code of Conduct Committee](#committee-membership). 163 | 164 | ## What to Include in a Report 165 | 166 | Our ability to address any code of conduct breaches in a timely and effective manner is impacted by the amount of information you can provide, so, we ask you to include as much of the following information as you can**: 167 | 168 | - **Your contact info** (so we can get in touch with you if we need to follow up). This will be kept confidential. You can also file a report [anonymously](#anonymous-reporting). 169 | - The **approximate time and location of the incident** (please be as specific as possible). 170 | - **Identifying information** (e.g. name, nickname, screen name, physical description) of the individual whose behavior is being reported. 171 | - **Description of the behavior** (if reporting harassing language, please be specific about the words used), **your account of what happened**, and any available **supporting records** (e.g. email, GitHub issue, screenshots, etc.). 172 | - **Description of the circumstances/context** surrounding the incident. 173 | - Let us know **if the incident is ongoing**, and/or if this is part of an ongoing pattern of behavior. 174 | - Names and contact info, if possible, of **anyone else who witnessed** or was involved in this incident. (Did anyone else observe the incident?) 175 | - **Any other relevant information** you believe we should have. 176 | 177 | ## Anonymous Reporting 178 | 179 | The reporting form supports anonymous incident reporting. Anonymous reporting works best when the behavior happened in a public space and was witnessed by many. If an incident is reported anonymously and was not witnessed by others, then the committee may be limited in what actions it can take and what it can report to the larger community. Nevertheless, the CoC Committee is still interested in receiving these reports. They are helpful when determining what we need to address as a community, and when looking for evidence of repeated behavior. 180 | 181 | ## Conflicts of Interest 182 | 183 | Committee members are expected to recuse themselves if they have a conflict of interest, and are required to recuse themselves if they are the accused or the target of the reported behavior. In addition, the CoC Committee can [vote](#voting-and-decision-making) to remove a committee member from a case, if the committee feels that the member has a conflict of interest. This [vote](#voting-and-decision-making) requires a simple majority. 184 | 185 | If you are concerned about making a report that will be read by all committee members, you are strongly encouraged to contact [individual committee members](#committee-membership) directly. 186 | 187 | # Enforcement: What Happens After a Report is Filed? 188 | 189 | ## Acknowledgment and Responding to Immediate Needs 190 | 191 | CoC Committee members and/or event staff will attempt to ensure your safety and help with any immediate needs. The CoC Committee will make every effort to **acknowledge receipt within 24 hours** (and we'll aim for much more quickly than that). 192 | 193 | ## Reviewing the Report 194 | 195 | The CoC Committee will make all efforts to **review the incident within three days** and determine: 196 | 197 | - Whether this is an ongoing situation, or if there is a threat to anyone's physical safety 198 | - What happened 199 | - Whether this event constitutes a code of conduct violation 200 | - Who the bad actor was, if any 201 | 202 | ## Contacting the Person Reported 203 | 204 | After the CoC Committee has had time to review and discuss the report, someone will attempt to contact the person who is the subject of the report to inform them of what has been reported about them. We will then ask that person for their account of what happened. 205 | 206 | ## Response and Potential Consequences 207 | 208 | Once the CoC Committee has completed our investigation of the report, we will make a decision as to how to respond. The person making a report will not normally be consulted as to the proposed resolution of the issue, except insofar as we need to understand how to help them feel safe. 209 | 210 | Potential consequences for violating the conda Organization code of conduct include: 211 | 212 | - Nothing (if we determine that no violation occurred) 213 | - Private feedback or reprimand from the CoC Committee to the individual(s) involved 214 | - Warning the person to cease their behavior and that any further reports will result in sanctions 215 | - A public announcement that an incident occurred 216 | - Mediation (only if both reporter and reportee agree) 217 | - An imposed vacation (e.g. asking someone to "take a week off" from a mailing list) 218 | - A permanent or temporary ban from some or all the conda Organization spaces (mailing lists, GitHub repos, in-person events, etc.) 219 | - Assistance to the complainant with a report to other bodies, for example, institutional offices or appropriate law enforcement agencies 220 | - Removing a person from the conda Organization membership or other formal affiliation 221 | - Publishing an account of the harassment and calling for the resignation of the alleged harasser from their responsibilities (may be called for if the person is an event leader, or refuses to stand aside from the conflict of interest, or similar) 222 | - Any other response that the CoC Committee deems necessary and appropriate to the situation 223 | 224 | No one espousing views or values contrary to the standards of our code of conduct will be permitted to hold any position representing the conda Organization, including volunteer positions. The CoC Committee has the right and responsibility to remove, edit, or reject comments, commits, code, website edits, issues, and other contributions that are not aligned with this code of conduct. 225 | 226 | We aim to **respond within one week** to the original reporter with either a resolution or an explanation of why the situation is not yet resolved. 227 | 228 | We will contact the person who is the subject of the report to let them know what actions will be taken as a result of the report, if any. 229 | 230 | Our policy is to make sure that everyone aware of the initial incident is also made aware that official action has been taken, while still respecting the privacy of individuals. In addition, we will also usually [notify the community](#confidentiality-and-public-statements-to-the-community) that an incident has been reported, what type of incident it was, and what the response was, again respecting the privacy of individuals. 231 | 232 | ## Appealing a Decision 233 | 234 | To appeal a decision of the CoC Committee, contact the [Committee Co-Chairs](#committee-membership), with your appeal. Please include as much detail as possible about why you are appealing the decision. The Co-Chairs will review the appeal, possibly consulting with the full Committee, and then issue a decision. 235 | 236 | # Timeline Summary: 237 | 238 | | Time | Event | Details | 239 | | ---- | ---- | ---- | 240 | | Within 24 Hours | Acknowledge | The CoC Committee will make every effort to **acknowledge receipt of a report within 24 hours**. | 241 | | Within 3 Days | Review | The CoC Committee aims to **review the incident within three days**. | 242 | | Within 1 Week | Resolve | We will **respond within one week** to the original reporter with either a resolution or an explanation of why the situation is not yet resolved. | 243 | 244 | # Voting and Decision Making 245 | 246 | Committee votes and decisions require both a minimum quorum size for the vote to be counted, and then a minimum percentage of cast affirmative votes to pass. 247 | 248 | Except where otherwise noted, votes require a quorum and a simple majority to pass: 249 | 250 | * Minimum Quorum: 251 | * More than 50% of eligible committee members must vote. 252 | * Eligibile members do not include those excluded because of [conflicts of interest](#conflicts-of-interest). 253 | * Affirmative vote threshold: 254 | * More than 50% of the votes cast need to be affirmative to take action. 255 | 256 | # Committee Membership 257 | 258 | You can reach the entire CoC Committee by emailing [conduct@conda.org](mailto:conduct@conda.org). 259 | 260 | | Name | Employer / Funding | Steering Council Member | Current Term Ends | 261 | | ---- | ---- | ---- | --- | 262 | | [Eric Dill](https://github.com/ericdill) | [Anaconda](https://anaconda.com/) | | 2026-07-01 | 263 | | [Dasha Gurova](https://github.com/dashagurova) | [Anaconda](https://anaconda.com/) | | 2026-07-01 | 264 | | [Bianca Henderson](https://github.com/beeankha) | [Red Hat](https://redhat.com/) | | 2026-07-01 | 265 | | [Katherine Kinnaman](https://github.com/kathatherine) | [Anaconda](https://anadonda.com/) | | 2026-07-01 | 266 | | [Mahe Iram Khan](https://github.com/ForgottenProgramme) | [Anaconda](https://anaconda.com/) | | 2025-07-01 | 267 | | [Ken Odegard](https://github.com/kenodegard) | [Anaconda](https://anaconda.com/) | | 2025-07-01 | 268 | | [Crystal Soja](https://github.com/csoja), Co-Chair | [Anaconda](https://anaconda.com/) | | 2025-07-01 | 269 | | [Jaime Rodríguez-Guerra](https://github.com/jaimergp), Co-Chair | [Quansight](https://quansight.com/) | yes | 2025-07-01 | 270 | 271 | # Terms and New Members 272 | 273 | * Committee members are appointed for two year terms. Committee members can choose to renew their memberships. 274 | * Committee members can resign before their term ends. 275 | * Committee members can also be removed by a [simple majority vote](#voting-and-decision-making) from their fellow committee members. 276 | * New committee members are added by a simple majority vote as well. 277 | 278 | # Eligibility 279 | 280 | Anyone from the community who is interested and able to do CoC Committee work is eligible to be nominated for the committee. New committee members can be nominated by any community member, including nominating themselves. 281 | 282 | ## Shared Funding 283 | 284 | Unlike the Steering Council, we are not limiting the number of Committee members who share a common source of funding. However, if a report involves someone who shares funding with CoC Committee members, then the remainder of the committee may vote to exclude some or all Committee members with that same funding, even if that excludes a majority of the CoC Committee. This should be done only if the separately funded Committee members feel that the common funding is interfering with decision making. 285 | 286 | Note: This requires tracking the funding sources of CoC Committee members. 287 | 288 | ## Overlap with Steering Council Membership 289 | 290 | Committee members can also be on the conda Organization Steering Council. However, Steering Council members have to make up less than 50% of the Code of Conduct Committee. 291 | 292 | # Updating this Code of Conduct 293 | 294 | The conda Organization's Code of Conduct can be updated by a [simple majority vote](#voting-and-decision-making) of the CoC Committee. 295 | 296 | 297 | # License 298 | 299 | This code of conduct is based on the [NumFOCUS code of conduct template](https://github.com/numfocus/numfocus/blob/8759e21481552f213489e3718979ccecf68e9ead/manual/numfocus-coc.md) as it existed on 2022/03/08 (which is the 2019/11/20 version). Several added sections are based on the [Galaxy Community Code of Conduct](https://galaxyproject.org/community/coc/). 300 | 301 | The NumFOCUS code of conduct template was itself adapted from numerous sources, including the [*Geek Feminism wiki, created by the Ada Initiative and other volunteers, which is under a Creative Commons Zero license*](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy), the [*Contributor Covenant version 1.2.0*](http://contributor-covenant.org/version/1/2/0/), the [*Bokeh Code of Conduct*](https://github.com/bokeh/bokeh/blob/master/CODE_OF_CONDUCT.md), the [*SciPy Code of Conduct*](https://github.com/jupyter/governance/blob/master/conduct/enforcement.md), the [*Carpentries Code of Conduct*](https://docs.carpentries.org/topic_folders/policies/code-of-conduct.html#enforcement-manual), and the [*NeurIPS Code of Conduct*](https://neurips.cc/public/CodeOfConduct). 302 | 303 | **The conda Organization Code of Conduct is licensed under the [Creative Commons Attribution 3.0 Unported License](https://creativecommons.org/licenses/by/3.0/).** 304 | --------------------------------------------------------------------------------