From 72ce8750452c48af4c5744af486e5a46a2855832 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 25 Aug 2024 00:22:53 +0000 Subject: [PATCH] Updated examples from cookiecutter-mdakit at 99b1fb9 --- .codecov.yml | 16 + .gitattributes | 1 + .github/ISSUE_TEMPLATE/bug_report.md | 34 + .github/ISSUE_TEMPLATE/feature_request.md | 20 + .github/PULL_REQUEST_TEMPLATE.md | 17 + .github/workflows/gh-ci.yaml | 163 +++++ .gitignore | 109 ++++ .pre-commit-config.yaml | 21 + .pylintrc | 612 ++++++++++++++++++ AUTHORS.md | 23 + CHANGELOG.md | 37 ++ CODE_OF_CONDUCT.md | 136 ++++ CONTRIBUTING.md | 29 + LICENSE | 339 ++++++++++ MANIFEST.in | 6 + README.md | 100 +++ cookieKit/__init__.py | 9 + cookieKit/analysis/__init__.py | 0 cookieKit/analysis/myanalysisclass.py | 115 ++++ cookieKit/data/README.md | 17 + cookieKit/data/__init__.py | 0 cookieKit/data/files.py | 19 + cookieKit/data/mda.txt | 45 ++ cookieKit/tests/__init__.py | 0 cookieKit/tests/analysis/__init__.py | 0 .../tests/analysis/test_myanalysisclass.py | 63 ++ cookieKit/tests/conftest.py | 20 + cookieKit/tests/test_cookieKit.py | 19 + cookieKit/tests/utils.py | 77 +++ devtools/conda-envs/test_env.yaml | 18 + docs/Makefile | 20 + docs/README.md | 24 + docs/make.bat | 36 ++ docs/requirements.yaml | 13 + docs/source/_static/README.md | 29 + .../logo/mdakits-empty-favicon-template.svg | 57 ++ .../logo/mdakits-empty-logo-template.svg | 65 ++ .../_static/logo/mdakits-placeholder-logo.png | Bin 0 -> 50632 bytes docs/source/_templates/README.md | 14 + docs/source/api.rst | 8 + docs/source/conf.py | 197 ++++++ docs/source/getting_started.rst | 4 + docs/source/index.rst | 23 + pyproject.toml | 92 +++ readthedocs.yaml | 16 + 45 files changed, 2663 insertions(+) create mode 100644 .codecov.yml create mode 100644 .gitattributes create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/gh-ci.yaml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 .pylintrc create mode 100644 AUTHORS.md create mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 README.md create mode 100644 cookieKit/__init__.py create mode 100644 cookieKit/analysis/__init__.py create mode 100644 cookieKit/analysis/myanalysisclass.py create mode 100644 cookieKit/data/README.md create mode 100644 cookieKit/data/__init__.py create mode 100644 cookieKit/data/files.py create mode 100644 cookieKit/data/mda.txt create mode 100644 cookieKit/tests/__init__.py create mode 100644 cookieKit/tests/analysis/__init__.py create mode 100644 cookieKit/tests/analysis/test_myanalysisclass.py create mode 100644 cookieKit/tests/conftest.py create mode 100644 cookieKit/tests/test_cookieKit.py create mode 100644 cookieKit/tests/utils.py create mode 100644 devtools/conda-envs/test_env.yaml create mode 100644 docs/Makefile create mode 100644 docs/README.md create mode 100644 docs/make.bat create mode 100644 docs/requirements.yaml create mode 100644 docs/source/_static/README.md create mode 100644 docs/source/_static/logo/mdakits-empty-favicon-template.svg create mode 100644 docs/source/_static/logo/mdakits-empty-logo-template.svg create mode 100644 docs/source/_static/logo/mdakits-placeholder-logo.png create mode 100644 docs/source/_templates/README.md create mode 100644 docs/source/api.rst create mode 100644 docs/source/conf.py create mode 100644 docs/source/getting_started.rst create mode 100644 docs/source/index.rst create mode 100644 pyproject.toml create mode 100644 readthedocs.yaml diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 0000000..e0d8e5d --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,16 @@ +# Codecov configuration to make it a bit less noisy +coverage: + status: + patch: false + project: + default: + threshold: 50% +comment: + layout: "header" + require_changes: false + branches: null + behavior: default + flags: null + paths: null +ignore: + - "mdakit-Cookie/_version.py" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..eb4cfa9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +mdakit-Cookie/_version.py export-subst diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..abcd97a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,34 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +## Expected behavior ## + + + + +## Actual behavior ## + + + + +## Code to reproduce the behavior ## + + + +``` python +import mdakit-Cookie + +... + +``` + +## Current environment ## + +- Which version are you using? (run `python -c "import mdakit-Cookie; print(mdakit-Cookie.__version__)"`) +- Which version of Python (`python -V`)? +- Which operating system? +- What is the output of `pip list`? +- If you use conda, what is the output of `conda list`? \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..0be4ea9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +## Is your feature request related to a problem? ## + + + +## Describe the solution you'd like ## + + + +## Describe alternatives you've considered ## + + + +## Additional context ## + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..90d6c3f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,17 @@ + + + +Fixes # + +Changes made in this Pull Request: + + - + - + + +PR Checklist +------------ + - [ ] Tests? + - [ ] Docs? + - [ ] CHANGELOG updated? + - [ ] Issue raised/referenced? diff --git a/.github/workflows/gh-ci.yaml b/.github/workflows/gh-ci.yaml new file mode 100644 index 0000000..3066fb2 --- /dev/null +++ b/.github/workflows/gh-ci.yaml @@ -0,0 +1,163 @@ +name: GH Actions CI +on: + push: + branches: + - "**" # main -- replaced main to allow CI to run in example cookie repo + pull_request: + branches: + - "**" # main -- replaced main to allow CI to run in example cookie repo + schedule: + # Weekly tests at midnight on Sundays run on main by default: + # Scheduled workflows run on the latest commit on the default or base branch. + # (from https://help.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule) + - cron: "0 0 * * 0" + +concurrency: + # Specific group naming so CI is only cancelled + # within same PR or on merge to main + group: ${{ github.ref }}-${{ github.head_ref }}-${{ github.workflow }} + cancel-in-progress: true + +defaults: + run: + shell: bash -l {0} + +jobs: + main-tests: + if: "github.repository == 'other/mdakit-Cookie'" + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macOS-latest, windows-latest] + mdanalysis-version: ["latest", "develop"] + python-version: ["3.10", "3.11", "3.12"] + exclude: + # Entries here exclude particular combinations of the matrix + # Edit or remove as particular combinations come into or out of date + # Below we exclude runs with the latest release and Python 3.12 + - mdanalysis-version: "latest" + python-version: "3.12" + + steps: + - uses: actions/checkout@v4 + + - name: Build information + run: | + uname -a + df -h + ulimit -a + + + # More info on options: https://github.com/conda-incubator/setup-miniconda + - name: Install conda dependencies + uses: conda-incubator/setup-miniconda@v3 + with: + python-version: ${{ matrix.python-version }} + environment-file: devtools/conda-envs/test_env.yaml + add-pip-as-python-dependency: true + + channels: defaults + + activate-environment: mdakit-Cookie-test + auto-update-conda: true + auto-activate-base: false + show-channel-urls: true + + + - name: Install MDAnalysis version + uses: MDAnalysis/install-mdanalysis@main + with: + version: ${{ matrix.mdanalysis-version }} + install-tests: false + installer: pip + shell: bash -l {0} + + - name: Install package + run: | + python --version + python -m pip install . --no-deps + + - name: Python information + run: | + which python + which pip + pip list + + conda info + conda list + + + - name: Run tests + run: | + pytest -n 2 -v --cov=cookieKit --cov-report=xml --color=yes cookieKit/tests/ + + - name: codecov + if: github.repository == 'other/mdakit-Cookie' && github.event_name != 'schedule' + uses: codecov/codecov-action@v4 + with: + file: coverage.xml + name: codecov-${{ matrix.os }}-py${{ matrix.python-version }} + verbose: True + # to upload coverage reports, set a secret called CODECOV_TOKEN + # in the repository settings + # (Obtain this from the Codecov website after setting up the repository there) + token: ${{ secrets.CODECOV_TOKEN }} + # To fail the CI if there's an error, keep this set to true + # If repository forks need to run CI, you may need to set this to false + # Forks can't access the CODECOV_TOKEN secret, + # and a failed upload registers as an error + fail_ci_if_error: true + + + pylint_check: + if: "github.repository == 'other/mdakit-Cookie'" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install Pylint + run: | + which pip + which python + pip install pylint mdanalysis + + - name: Run Pylint + env: + PYLINTRC: .pylintrc + run: | + pylint mdakit-Cookie + + + pypi_check: + if: "github.repository == 'other/mdakit-Cookie'" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install dependencies + run: | + pip install pipx twine + + - name: Build package + run: | + python -m pipx run build --sdist + + - name: Check package build + run: | + DISTRIBUTION=$(ls -t1 dist/mdakit_cookie-*.tar.gz | head -n 1) + test -n "${DISTRIBUTION}" || { echo "no distribution dist/mdakit-Cookie-*.tar.gz found"; exit 1; } + echo "twine check $DISTRIBUTION" + twine check $DISTRIBUTION diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21e8110 --- /dev/null +++ b/.gitignore @@ -0,0 +1,109 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +.pytest_cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# VS Code +.vscode/ + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.DS_Store + +# poetry +poetry.lock diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..062c53f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,21 @@ + +# To install the git pre-commit hook run: +# pre-commit install +# To update the pre-commit hooks run: +# pre-commit install-hooks +exclude: '^(\.tox|ci/templates|\.bumpversion\.cfg)(/|$)' +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: master + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: debug-statements + - repo: https://github.com/timothycrosley/isort + rev: master + hooks: + - id: isort + - repo: https://gitlab.com/pycqa/flake8 + rev: master + hooks: + - id: flake8 diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..6b984a7 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,612 @@ +# -*- Mode: conf; tab-width: 4; indent-tabs-mode:nil; coding:utf-8 -*- +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore= + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Pickle collected data for later comparisons. +persistent=no + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Use multiple processes to speed up Pylint. +jobs=1 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + +# Allow optimization of some AST trees. This will activate a peephole AST +# optimizer, which will apply various small optimizations. For instance, it can +# be used to obtain the result of joining multiple strings with the addition +# operator. Joining a lot of strings can lead to a maximum recursion error in +# Pylint and this flag can prevent that. It has one side effect, the resulting +# AST will be different than the one from reality. This option is deprecated +# and it will be removed in Pylint 2.0. +optimize-ast=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +disable=all + +enable=abstract-class-instantiated, + access-member-before-definition, + anomalous-unicode-escape-in-string, + apply-builtin, + assert-on-tuple, + assigning-non-slot, + assignment-from-no-return, + backtick, + bad-except-order, + bad-exception-context, + bad-format-character, + bad-format-string, + bad-format-string-key, + bad-open-mode, + bad-reversed-sequence, + bad-staticmethod-argument, + bad-str-strip-call, + binary-op-exception, + boolean-datetime + buffer-builtin, + catching-non-exception, + cmp-builtin, + cmp-method, + coerce-builtin, + coerce-method, + confusing-with-statement, + continue-in-finally, + delslice-method, + deprecated-method, + deprecated-module, + dict-iter-method, + dict-view-method, + duplicate-argument-name, + duplicate-bases, + duplicate-except, + duplicate-key, + eval-used, + exec-used, + execfile-builtin, + file-builtin, + format-combined-specification, + format-needs-mapping, + getslice-method, + global-at-module-level, + global-statement, + global-variable-not-assigned, + global-variable-undefined, + hex-method, + import-star-module-level, + inconsistent-mro, + inherit-non-class, + init-is-generator, + input-builtin, + intern-builtin, + invalid-all-object, + invalid-encoded-data, + invalid-format-index, + invalid-slots, + invalid-slots-object, + invalid-star-assignment-target, + logging-format-truncated, + logging-not-lazy, + logging-too-few-args, + logging-too-many-args, + logging-unsupported-format, + long-suffix, + lost-exception, + lowercase-l-suffix, + method-hidden, + misplaced-bare-raise, + misplaced-future, + missing-format-argument-key, + missing-format-attribute, + missing-format-string-key, + missing-kwoa, + missing-super-argument, + mixed-format-string, + mixed-indentation, + no-init, + no-method-argument, + non-iterator-returned, + non-parent-init-called, + nonexistent-operator, + nonlocal-and-global, + nonlocal-without-binding, + nonstandard-exception, + not-a-mapping, + not-an-iterable, + not-async-context-manager, + not-context-manager, + not-in-loop, + notimplemented-raised, + oct-method, + old-ne-operator, + old-octal-literal, + old-raise-syntax, + parameter-unpacking, + raising-non-exception, + raising-string, + raw_input-builtin, + redefine-in-handler, + redundant-keyword-arg, + redundant-unittest-assert, + reload-builtin, + repeated-keyword, + return-arg-in-generator, + return-in-init, + return-outside-function, + setslice-method, + signature-differs, + slots-on-old-class, + standarderror-builtin, + star-needs-assignment-target, + super-on-old-class, + too-few-format-args, + too-few-public-methods, + too-many-function-attributes, + too-many-star-expressions, + truncated-format-string, + unexpected-keyword-arg, + unichr-builtin, + unicode-builtin, + unnecessary-pass, + unpacking-in-except, + unreachable, + unsubscriptable-object, + unsupported-binary-operation, + unsupported-membership-test, + unused-format-string-argument, + unused-format-string-key, + useless-else-on-loop, + using-cmp-argument, + using-constant-test, + yield-inside-async-function, + yield-outside-function, + old-division, + relative-import, + no-absolute-import, + print-statement, + xrange-builtin, + zip-builtin-not-iterating, + map-builtin-not-iterating, + +# Things we'd like to try. +# Procedure: +# 1. Enable a bunch. +# 2. See if there's spurious ones; if so disable. +# 3. Record above. +# 4. Remove from this list. + # abstract-method, + # anomalous-backslash-in-string, + # arguments-differ, + # assignment-from-none, + # attribute-defined-outside-init, + # bad-builtin, + # bad-indentation, + # bad-super-call, + # bare-except, + # basestring-builtin, + # broad-except, + # cell-var-from-loop, + # dangerous-default-value, + # deprecated-lambda, + # expression-not-assigned, + # filter-builtin-not-iterating, + # fixme, + # function-redefined, + # import-error, + # indexing-exception, + # invalid-name, + # invalid-sequence-index, + # invalid-slice-index, + # logging-format-interpolation, + # long-builtin, + # metaclass-assignment, + # missing-docstring, + # next-method-called, + # no-member, + # no-self-argument, + # no-value-for-parameter, + # nonzero-method, + # not-callable, + # pointless-statement, + # pointless-string-statement, + # property-on-old-class, + # protected-access, + # redefined-builtin, + # redefined-outer-name, + # reduce-builtin, + # reimported, + # round-builtin, + # super-init-not-called, + # too-many-arguments, + # too-many-format-args, + # too-many-function-args, + # too-many-locals, + # undefined-all-variable, + # undefined-loop-variable, + # unexpected-special-method-signature, + # unnecessary-lambda, + # unnecessary-semicolon, + # unpacking-non-sequence, + # unused-argument, + # unused-import, + # unused-variable, + # unused-wildcard-import, + # used-before-assignment, + # wildcard-import, + # wrong-import-order, + # invalid-unary-operand-type, + # raising-bad-type, + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=parseable + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". This option is deprecated +# and it will be removed in Pylint 2.0. +files-output=no + +# Tells whether to display a full report or only the messages +reports=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_$|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules= + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma,dict-separator + +# Maximum number of lines in a module +max-module-lines=2000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[BASIC] + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,input + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_,x + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty + +# Regular expression matching correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for function names +function-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for variable names +variable-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for attribute names +attr-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for argument names +argument-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for method names +method-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + + +[ELIF] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=10 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=30 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=0 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=builtins.Exception diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 0000000..c438481 --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,23 @@ +# Authors + +TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs was created by Test User name in 2024. + + +All contributing authors are listed in this file below. +The repository history at https://github.com/other/mdakit-Cookie +and the CHANGELOG show individual code contributions. + +## Chronological list of authors + + + +**2024** +- Test User name <@test-user-account> \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5041f92 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,37 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + + +## [Unreleased] + +### Authors + + +### Added + + +### Fixed + + +### Changed + + +### Deprecated + + +### Removed + diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..b2fa070 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,136 @@ +# Code of conduct + +The TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs *Code of Conduct* sets the rules for the behavior of +every member in the TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs community so that everyone can +experience a welcoming, supportive, and productive environment that is +free from harassment. + + +**Table of Contents** + +- [Code of conduct](#code-of-conduct) + - [Code of Conduct and Community Guidelines](#code-of-conduct-and-community-guidelines) + - [Scope](#scope) + - [Enforcement](#enforcement) + - [Acknowledgment](#acknowledgment) + + +## Code of Conduct and Community Guidelines + +TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs is part of an engaged and respectful community made up of people from all +over the world. Your involvement helps us to further our mission and to create +an open platform that serves a broad range of communities, from research and +education to industry and beyond. This diversity is one of our biggest +strengths, but it can also lead to communication issues and conflicts. +Therefore, we have a few ground rules we ask that our community members adhere +to. + +Fundamentally, we are committed to providing a productive, +harassment-free environment for everyone. Rather than considering this +code an exhaustive list of things that you can’t do, take it in the +spirit it is intended - a guide to make it easier to enrich all of us +and the communities in which we participate. + +Importantly: as a member of our community, you are also a steward of these +values. Not all problems need to be resolved via formal processes, and often a +quick, friendly but clear word on an online forum or in person can help resolve +a misunderstanding and de-escalate things. + +By embracing the following principles, guidelines and actions to follow or +avoid, you will help us make TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs a welcoming and productive community. + +1. **Be friendly and patient**. + +2. **Be welcoming**. We strive to be a community that welcomes and supports + people of all backgrounds and identities. This includes, but is not limited + to, members of any race, ethnicity, culture, national origin, color, + immigration status, social and economic class, educational level, sex, sexual + orientation, gender identity and expression, age, physical appearance, family + status, political belief, technological or professional choices, academic + discipline, religion, mental ability, and physical ability. + +3. **Be considerate**. Your work will be used by other people, and you in turn + will depend on the work of others. Any decision you take will affect users + and colleagues, and you should take those consequences into account when + making decisions. Remember that we're a world-wide community. You may be + communicating with someone with a different primary language or cultural + background. + +4. **Be respectful**. Not all of us will agree all the time, but disagreement is + no excuse for poor behavior or poor manners. We might all experience some + frustration now and then, but we cannot allow that frustration to turn into a + personal attack. It’s important to remember that a community where people + feel uncomfortable or threatened is not a productive one. + +5. **Be careful in the words that you choose**. Be kind to others. Do not insult + or put down other community members. Harassment and other exclusionary + behavior are not acceptable. This includes, but is not limited to: + * threats or violent language directed against another person + * discriminatory jokes and language + * posting sexually explicit or violent material + * posting (or threatening to post) other people's personally identifying + information ("doxing") + * personal insults, especially those using racist or sexist terms + * unwelcome sexual attention + * advocating for, or encouraging, any of the above behavior + * repeated harassment of others. In general, if someone asks you to stop, + then stop + +6. **Moderate your expectations**. Many in our community volunteer their time. + They are probably not purposefully ignoring issues, refusing to engage in + discussion, avoiding features, etc. but often just unavailable. + +7. **When we disagree, try to understand why**. Disagreements, both social and + technical, happen all the time and TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs is no exception. It is important + that we resolve disagreements and differing views constructively. Remember + that we’re different. The strength of TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs comes from its varied community + that includes people from a wide range of backgrounds. Different people have + different perspectives on issues. Being unable to understand why someone + holds a viewpoint doesn’t mean they’re wrong. Don’t forget that it is human + to err and blaming each other doesn’t get us anywhere. Instead, focus on + helping to resolve issues and learning from mistakes. + +8. **A simple apology can go a long way**. It can often de-escalate a situation, + and telling someone that you are sorry is act of empathy that doesn’t + automatically imply an admission of guilt. + + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an +appointed representative at an online or offline event. Representation of a +project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at 'test_email@test.com'. The project team will +review and investigate all complaints, and will respond in a way that it deems +appropriate to the circumstances. The project team is obligated to maintain +confidentiality with regard to the reporter of an incident. Further details of +specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + + +## Acknowledgment + +Original text was adapted from +the +[*Speak Up!*](http://web.archive.org/web/20141109123859/http://speakup.io/coc.html), +[*Django*](https://www.djangoproject.com/conduct), +[*Contributor Covenant*](http://contributor-covenant.org/), +[*Jupyter*](https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md), +[*MolSSI*](https://github.com/MolSSI/cookiecutter-cms/blob/master/%7B%7Bcookiecutter.repo_name%7D%7D/CODE_OF_CONDUCT.md), +and [*MDAnalysis*](https://github.com/MDAnalysis/mdanalysis/blob/develop/CODE_OF_CONDUCT.md) projects, +modified by TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs. +We are grateful to those projects for contributing these +materials under open licensing terms for us to easily reuse. + +All content on this page is licensed under a [*Creative Commons +Attribution*](http://creativecommons.org/licenses/by/3.0/) license. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..9cbfb4d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,29 @@ +# How to contribute + +We welcome all contributions to TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs! + +Contributions can take many forms, such as: + +* sharing bug reports or feature requests through the [Issue Tracker](https://github.com/other/mdakit-Cookie/issues) +* asking or answering questions, or otherwise joining in on discussions +* adding bug fixes, new features, or otherwise improving the code +* adding or improving documentation + +The second two options both involve making a [pull request](https://github.com/other/mdakit-Cookie/pulls) . + +There are many existing guides on how to make a contribution to an open +source project on GitHub. In short, the steps are to: + + * Ensure that you have a [GitHub account](https://github.com/signup/free) + * [Fork](https://help.github.com/articles/fork-a-repo/) the repository into your own account + * On your local machine, [clone](https://help.github.com/articles/cloning-a-repository/) your fork + * Create a development environment from source, following the Installation from source instructions + * Create a new branch off the `main` branch with a meaningful name (e.g. ``git checkout -b fix-issue-39``) + * Add your modifications to the code or documentation + * Add tests if modifying the code + * Commit and push changes to GitHub, and open a pull request + +Guides such as the [MDAnalysis User Guide](https://userguide.mdanalysis.org/stable/contributing.html) +have been written in much more detail to go through these steps more thoroughly. +We strongly encourage you to check those for help, and we welcome any questions. +Thank you for your contribution! \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..f0a508c --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,6 @@ +include LICENSE +include MANIFEST.in +include AUTHORS.md CHANGELOG.md CODE_OF_CONDUCT.md README.md + +graft cookieKit +global-exclude *.py[cod] __pycache__ *.so \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..99ab4bb --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs +============================== +[//]: # (Badges) + +| **Latest release** | [![Last release tag][badge_release]][url_latest_release] ![GitHub commits since latest release (by date) for a branch][badge_commits_since] [![Documentation Status][badge_docs]][url_docs]| +| :----------------- | :------- | +| **Status** | [![GH Actions Status][badge_actions]][url_actions] [![codecov][badge_codecov]][url_codecov] | +| **Community** | [![License: GPL v2][badge_license]][url_license] [![Powered by MDAnalysis][badge_mda]][url_mda]| + +[badge_actions]: https://github.com/other/mdakit-Cookie/actions/workflows/gh-ci.yaml/badge.svg +[badge_codecov]: https://codecov.io/gh/other/mdakit-Cookie/branch/main/graph/badge.svg +[badge_commits_since]: https://img.shields.io/github/commits-since/other/mdakit-Cookie/latest +[badge_docs]: https://readthedocs.org/projects/mdakit-Cookie/badge/?version=latest +[badge_license]: https://img.shields.io/badge/License-GPLv2-blue.svg +[badge_mda]: https://img.shields.io/badge/powered%20by-MDAnalysis-orange.svg?logoWidth=16&logo=data:image/x-icon;base64,AAABAAEAEBAAAAEAIAAoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJD+XwCY/fEAkf3uAJf97wGT/a+HfHaoiIWE7n9/f+6Hh4fvgICAjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACT/yYAlP//AJ///wCg//8JjvOchXly1oaGhv+Ghob/j4+P/39/f3IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJH8aQCY/8wAkv2kfY+elJ6al/yVlZX7iIiI8H9/f7h/f38UAAAAAAAAAAAAAAAAAAAAAAAAAAB/f38egYF/noqAebF8gYaagnx3oFpUUtZpaWr/WFhY8zo6OmT///8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAn46Ojv+Hh4b/jouJ/4iGhfcAAADnAAAA/wAAAP8AAADIAAAAAwCj/zIAnf2VAJD/PAAAAAAAAAAAAAAAAICAgNGHh4f/gICA/4SEhP+Xl5f/AwMD/wAAAP8AAAD/AAAA/wAAAB8Aov9/ALr//wCS/Z0AAAAAAAAAAAAAAACBgYGOjo6O/4mJif+Pj4//iYmJ/wAAAOAAAAD+AAAA/wAAAP8AAABhAP7+FgCi/38Axf4fAAAAAAAAAAAAAAAAiIiID4GBgYKCgoKogoB+fYSEgZhgYGDZXl5e/m9vb/9ISEjpEBAQxw8AAFQAAAAAAAAANQAAADcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjo6Mb5iYmP+cnJz/jY2N95CQkO4pKSn/AAAA7gAAAP0AAAD7AAAAhgAAAAEAAAAAAAAAAACL/gsAkv2uAJX/QQAAAAB9fX3egoKC/4CAgP+NjY3/c3Nz+wAAAP8AAAD/AAAA/wAAAPUAAAAcAAAAAAAAAAAAnP4NAJL9rgCR/0YAAAAAfX19w4ODg/98fHz/i4uL/4qKivwAAAD/AAAA/wAAAP8AAAD1AAAAGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALGxsVyqqqr/mpqa/6mpqf9KSUn/AAAA5QAAAPkAAAD5AAAAhQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADkUFBSuZ2dn/3V1df8uLi7bAAAATgBGfyQAAAA2AAAAMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0AAADoAAAA/wAAAP8AAAD/AAAAWgC3/2AAnv3eAJ/+dgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9AAAA/wAAAP8AAAD/AAAA/wAKDzEAnP3WAKn//wCS/OgAf/8MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIQAAANwAAADtAAAA7QAAAMAAABUMAJn9gwCe/e0Aj/2LAP//AQAAAAAAAAAA +[badge_release]: https://img.shields.io/github/release-pre/other/mdakit-Cookie.svg +[url_actions]: https://github.com/other/mdakit-Cookie/actions?query=branch%3Amain+workflow%3Agh-ci +[url_codecov]: https://codecov.io/gh/other/mdakit-Cookie/branch/main +[url_docs]: https://mdakit-Cookie.readthedocs.io/en/latest/?badge=latest +[url_latest_release]: https://github.com/other/mdakit-Cookie/releases +[url_license]: https://www.gnu.org/licenses/gpl-2.0 +[url_mda]: https://www.mdanalysis.org + +Test MDAKit Project with dependencies using anaconda and ReadTheDocs + +TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs is bound by a [Code of Conduct](https://github.com/other/mdakit-Cookie/blob/main/CODE_OF_CONDUCT.md). + +### Installation + +To build TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs from source, +we highly recommend using virtual environments. +If possible, we strongly recommend that you use +[Anaconda](https://docs.conda.io/en/latest/) as your package manager. +Below we provide instructions both for `conda` and +for `pip`. + +#### With conda + +Ensure that you have [conda](https://docs.conda.io/projects/conda/en/latest/user-guide/install/index.html) installed. + +Create a virtual environment and activate it: + +``` +conda create --name mdakit-Cookie +conda activate mdakit-Cookie +``` + +Install the development and documentation dependencies: + +``` +conda env update --name mdakit-Cookie --file devtools/conda-envs/test_env.yaml +conda env update --name mdakit-Cookie --file docs/requirements.yaml +``` + +Build this package from source: + +``` +pip install -e . +``` + +If you want to update your dependencies (which can be risky!), run: + +``` +conda update --all +``` + +And when you are finished, you can exit the virtual environment with: + +``` +conda deactivate +``` + +#### With pip + +To build the package from source, run: + +``` +pip install . +``` + +If you want to create a development environment, install +the dependencies required for tests and docs with: + +``` +pip install ".[test,doc]" +``` + +### Copyright + +The TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs source code is hosted at https://github.com/other/mdakit-Cookie +and is available under the GNU General Public License, version 2 (see the file [LICENSE](https://github.com/other/mdakit-Cookie/blob/main/LICENSE)). + +Copyright (c) 2024, Test User name + + +#### Acknowledgements + +Project based on the +[MDAnalysis Cookiecutter](https://github.com/MDAnalysis/cookiecutter-mda) version 0.1. +Please cite [MDAnalysis](https://github.com/MDAnalysis/mdanalysis#citation) when using TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs in published work. diff --git a/cookieKit/__init__.py b/cookieKit/__init__.py new file mode 100644 index 0000000..98d54bf --- /dev/null +++ b/cookieKit/__init__.py @@ -0,0 +1,9 @@ +""" +TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs +Test MDAKit Project with dependencies using anaconda and ReadTheDocs +""" + +# Add imports here +from importlib.metadata import version + +__version__ = version("mdakit-Cookie") diff --git a/cookieKit/analysis/__init__.py b/cookieKit/analysis/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cookieKit/analysis/myanalysisclass.py b/cookieKit/analysis/myanalysisclass.py new file mode 100644 index 0000000..58172a2 --- /dev/null +++ b/cookieKit/analysis/myanalysisclass.py @@ -0,0 +1,115 @@ +""" +MyAnalysisClass --- :mod:`cookieKit.analysis.MyAnalysisClass` +=========================================================== + +This module contains the :class:`MyAnalysisClass` class. + +""" +from typing import Union, TYPE_CHECKING + +from MDAnalysis.analysis.base import AnalysisBase +import numpy as np + +if TYPE_CHECKING: + from MDAnalysis.core.universe import Universe, AtomGroup + + +class MyAnalysisClass(AnalysisBase): + """MyAnalysisClass class. + + This class is used to perform analysis on a trajectory. + + Parameters + ---------- + universe_or_atomgroup: :class:`~MDAnalysis.core.universe.Universe` or :class:`~MDAnalysis.core.groups.AtomGroup` + Universe or group of atoms to apply this analysis to. + If a trajectory is associated with the atoms, + then the computation iterates over the trajectory. + select: str + Selection string for atoms to extract from the input Universe or + AtomGroup + + Attributes + ---------- + universe: :class:`~MDAnalysis.core.universe.Universe` + The universe to which this analysis is applied + atomgroup: :class:`~MDAnalysis.core.groups.AtomGroup` + The atoms to which this analysis is applied + results: :class:`~MDAnalysis.analysis.base.Results` + results of calculation are stored here, after calling + :meth:`MyAnalysisClass.run` + start: Optional[int] + The first frame of the trajectory used to compute the analysis + stop: Optional[int] + The frame to stop at for the analysis + step: Optional[int] + Number of frames to skip between each analyzed frame + n_frames: int + Number of frames analysed in the trajectory + times: numpy.ndarray + array of Timestep times. Only exists after calling + :meth:`MyAnalysisClass.run` + frames: numpy.ndarray + array of Timestep frame indices. Only exists after calling + :meth:`MyAnalysisClass.run` + """ + + def __init__( + self, + universe_or_atomgroup: Union["Universe", "AtomGroup"], + select: str = "all", + # TODO: add your own parameters here + **kwargs + ): + # the below line must be kept to initialize the AnalysisBase class! + super().__init__(universe_or_atomgroup.trajectory, **kwargs) + # after this you will be able to access `self.results` + # `self.results` is a dictionary-like object + # that can should used to store and retrieve results + # See more at the MDAnalysis documentation: + # https://docs.mdanalysis.org/stable/documentation_pages/analysis/base.html?highlight=results#MDAnalysis.analysis.base.Results + + self.universe = universe_or_atomgroup.universe + self.atomgroup = universe_or_atomgroup.select_atoms(select) + + def _prepare(self): + """Set things up before the analysis loop begins""" + # This is an optional method that runs before + # _single_frame loops over the trajectory. + # It is useful for setting up results arrays + # For example, below we create an array to store + # the number of atoms with negative coordinates + # in each frame. + self.results.is_negative = np.zeros( + (self.n_frames, self.atomgroup.n_atoms), + dtype=bool, + ) + + def _single_frame(self): + """Calculate data from a single frame of trajectory""" + # This runs once for each frame of the trajectory + # It can contain the main analysis method, or just collect data + # so that analysis can be done over the aggregate data + # in _conclude. + + # The trajectory positions update automatically + negative = self.atomgroup.positions < 0 + # You can access the frame number using self._frame_index + self.results.is_negative[self._frame_index] = negative.any(axis=1) + + def _conclude(self): + """Calculate the final results of the analysis""" + # This is an optional method that runs after + # _single_frame loops over the trajectory. + # It is useful for calculating the final results + # of the analysis. + # For example, below we determine the + # which atoms always have negative coordinates. + self.results.always_negative = self.results.is_negative.all(axis=0) + always_negative_atoms = self.atomgroup[self.results.always_negative] + self.results.always_negative_atoms = always_negative_atoms + self.results.always_negative_atom_names = always_negative_atoms.names + + # results don't have to be arrays -- they can be any value, e.g. floats + self.results.n_negative_atoms = self.results.is_negative.sum(axis=1) + self.results.mean_negative_atoms = self.results.n_negative_atoms.mean() diff --git a/cookieKit/data/README.md b/cookieKit/data/README.md new file mode 100644 index 0000000..550587e --- /dev/null +++ b/cookieKit/data/README.md @@ -0,0 +1,17 @@ +# Sample Package Data + +This directory contains sample additional data you may want to include with your package. +This is a place where non-code related additional information (such as data files, molecular structures, etc.) can +go that you want to ship alongside your code. + +Please note that it is not recommended to place large files in your git directory. If your project requires files larger +than a few megabytes in size it is recommended to host these files elsewhere. This is especially true for binary files +as the `git` structure is unable to correctly take updates to these files and will store a complete copy of every version +in your `git` history which can quickly add up. As a note most `git` hosting services like GitHub have a 1 GB per repository +cap. + +## Including package data + +Modify your package's `setup.py` file and the `setup()` command. Include the +[`package_data`](http://setuptools.readthedocs.io/en/latest/setuptools.html#basic-use) keyword and point it at the +correct files. \ No newline at end of file diff --git a/cookieKit/data/__init__.py b/cookieKit/data/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cookieKit/data/files.py b/cookieKit/data/files.py new file mode 100644 index 0000000..c9c5f03 --- /dev/null +++ b/cookieKit/data/files.py @@ -0,0 +1,19 @@ +""" +Location of data files +====================== + +Use as :: + + from cookieKit.data.files import * + +""" + +__all__ = [ + "MDANALYSIS_LOGO", # example file of MDAnalysis logo +] + +import importlib.resources + +data_directory = importlib.resources.files("cookieKit") / "data" + +MDANALYSIS_LOGO = data_directory / "mda.txt" diff --git a/cookieKit/data/mda.txt b/cookieKit/data/mda.txt new file mode 100644 index 0000000..7893f85 --- /dev/null +++ b/cookieKit/data/mda.txt @@ -0,0 +1,45 @@ + + ▄▄████████▄▄ + ,▓███████████████▄ ____ + ▄███████████████████ ╔D╠╠╠╠╠╠╬φ_ + ▐█████████████████████ ╔╠╠╠╠╠╠╠╠╠╠╠╠▒ + ██████████████████████▌ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠H + ███████████████████████ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠H + ╙██████████████████████ ╠╠╠╠╠╠╠╠╠╠╠╠╠╩ + ╙██████████████████████ ╙╠╠╠╠╠╠╠╠╠╝^ + '██████████████████████_ `'^╙╙^` + `▀███████████▀▀▀███████▄ + `` _╓╗φ@@@φ╗╖,╙▀████▄▄╓,,,▄▄▄▓█████▓▄_ + ,φ▓╬╬╬╬╬╬╬╬╬╬╬╬▒,╙█████████████████████▓_ + Æ╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▌ ▀██████████████████████ + _,,_ ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓ ╚██████████████████████ + ╔╠╠╠╠╠╬_ [╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬L ██████████████████████▌ + ╠╠╠╠╠╠╠H ╟╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▒ ███████████████████████ + `╚╠╠╠╠╙ ╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬L ██████████████████████▌ + [╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╩ ███████████████████████ + é╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╜ ██████████████████████▀ + _╗▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╝╙,▓████████████████████▀" + _╓╗╗╗╗╗╖,__ __╓φ▓╬╬╝╜"▄▄▄▄▄▄▄▄▄╠╙╙^""▄▄▓████▀" └╙╙▀▀▀"" + ╔Æ╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╜╓▓█████████████████████▀ + ╗╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╩ ██████████████████████▀ + ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▌ ██████████████████████Ñ ╔@DD╠DK╓ + [╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╟██████████████████████ ╒╠╠╠╠╠╠╠╠╠╠ + ╢╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ██████████████████████▌ ╚╠╠╠╠╠╠╠╠╠╠H + ╚╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╟█████████████████████` '╠╠╠╠╠╠╠╠╠╠ + ╫╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▒ ████████████████████▌ `╚╠╠╠╠╠╝╙ + ╚╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬W ██████████████████▀ + ╙╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓╖╙▀█████████████▀ + "╙╨╝╝╝╨╙^`` `"╙╝╬╬▓W╓╙▀▀▀▀▀▀▀▀"_,,,__ + _╓╦φφφφ╦,_ '╝╬╬╬╬▓▒▒▒▒▓╬╬╬╬╬╬╬╬╬▓╗_ + ,φ╠╠╠╠╠╠╠╠╠╠╠D╦_ `╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓, + ╔╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╦ ╟╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▄ + j╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠H ╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬L + ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓ + ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ║╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▌ + ²╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ + '╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╩ `╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓ + '╚╠╠╠╠╠╠╠╠╠╝╙ ╙╣╬╬╬╬╬╬╬╬╬╬╬╬╬╝^ + ````` `╙╨╝╝╝╝╝╨╙` + +--- +asciiart.club diff --git a/cookieKit/tests/__init__.py b/cookieKit/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cookieKit/tests/analysis/__init__.py b/cookieKit/tests/analysis/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cookieKit/tests/analysis/test_myanalysisclass.py b/cookieKit/tests/analysis/test_myanalysisclass.py new file mode 100644 index 0000000..abaad56 --- /dev/null +++ b/cookieKit/tests/analysis/test_myanalysisclass.py @@ -0,0 +1,63 @@ +import pytest +from numpy.testing import assert_allclose + +from cookieKit.analysis.myanalysisclass import MyAnalysisClass +from cookieKit.tests.utils import make_Universe + + +class TestMyAnalysisClass: + + # fixtures are helpful functions that set up a test + # See more at https://docs.pytest.org/en/stable/how-to/fixtures.html + @pytest.fixture + def universe(self): + u = make_Universe( + extras=("names", "resnames",), + n_frames=3, + ) + # create toy data to test assumptions + for ts in u.trajectory: + ts.positions[:ts.frame] *= -1 + return u + + @pytest.fixture + def analysis(self, universe): + return MyAnalysisClass(universe) + + @pytest.mark.parametrize( + "select, n_atoms", # argument names + [ # argument values in a tuple, in order + ("all", 125), + ("index 0:9", 10), + ("segindex 3:4", 50), + ] + ) + def test_atom_selection(self, universe, select, n_atoms): + # `universe` here is the fixture defined above + analysis = MyAnalysisClass( + universe, select=select) + assert analysis.atomgroup.n_atoms == n_atoms + + @pytest.mark.parametrize( + "stop, expected_mean", + [ + (1, 0), + (2, 0.5), + (3, 1) + ] + ) + def test_mean_negative_atoms(self, analysis, stop, expected_mean): + # assert we haven't run yet and the result doesn't exist yet + assert "mean_negative_atoms" not in analysis.results + analysis.run(stop=stop) + assert analysis.n_frames == stop + + # when comparing floating point values, it's best to use assert_allclose + # to allow for floating point precision differences + assert_allclose( + analysis.results.mean_negative_atoms, # computed data + expected_mean, # reference / desired data + rtol=1e-07, # relative tolerance + atol=0, # absolute tolerance + err_msg="mean_negative_atoms is not correct", + ) diff --git a/cookieKit/tests/conftest.py b/cookieKit/tests/conftest.py new file mode 100644 index 0000000..bf65e39 --- /dev/null +++ b/cookieKit/tests/conftest.py @@ -0,0 +1,20 @@ +""" +Global pytest fixtures +""" + +# Use this file if you need to share any fixtures +# across multiple modules +# More information at +# https://docs.pytest.org/en/stable/how-to/fixtures.html#scope-sharing-fixtures-across-classes-modules-packages-or-session + +import pytest + +from cookieKit.data.files import MDANALYSIS_LOGO + + +@pytest.fixture +def mdanalysis_logo_text() -> str: + """Example fixture demonstrating how data files can be accessed""" + with open(MDANALYSIS_LOGO, "r", encoding="utf8") as f: + logo_text = f.read() + return logo_text diff --git a/cookieKit/tests/test_cookieKit.py b/cookieKit/tests/test_cookieKit.py new file mode 100644 index 0000000..bbd80a9 --- /dev/null +++ b/cookieKit/tests/test_cookieKit.py @@ -0,0 +1,19 @@ +""" +Unit and regression test for the cookieKit package. +""" + +# Import package, test suite, and other packages as needed +import cookieKit +import pytest +import sys + + +def test_cookieKit_imported(): + """Sample test, will always pass so long as import statement worked""" + assert "cookieKit" in sys.modules + + +def test_mdanalysis_logo_length(mdanalysis_logo_text): + """Example test using a fixture defined in conftest.py""" + logo_lines = mdanalysis_logo_text.split("\n") + assert len(logo_lines) == 46, "Logo file does not have 46 lines!" diff --git a/cookieKit/tests/utils.py b/cookieKit/tests/utils.py new file mode 100644 index 0000000..63a2e16 --- /dev/null +++ b/cookieKit/tests/utils.py @@ -0,0 +1,77 @@ +from typing import Tuple + +import MDAnalysis as mda +from MDAnalysis.coordinates.memory import MemoryReader +import numpy as np + + +def make_Universe( + extras: Tuple[str] = tuple(), + size: Tuple[int, int, int] = (125, 25, 5), + n_frames: int = 0, + velocities: bool = False, + forces: bool = False +) -> mda.Universe: + """Make a dummy reference Universe + + Allows the construction of arbitrary-sized Universes. Suitable for + the generation of structures for output. + + Preferable for testing core components because: + * minimises dependencies within the package + * very fast compared to a "real" Universe + + Parameters + ---------- + extras : tuple of strings, optional + extra attributes to add to Universe: + u = make_Universe(('masses', 'charges')) + Creates a lightweight Universe with only masses and charges. + size : tuple of int, optional + number of elements of the Universe (n_atoms, n_residues, n_segments) + n_frames : int + If positive, create a fake Reader object attached to Universe + velocities : bool, optional + if the fake Reader provides velocities + force : bool, optional + if the fake Reader provides forces + + Returns + ------- + MDAnalysis.core.universe.Universe object + + """ + + n_atoms, n_residues, n_segments = size + trajectory = n_frames > 0 + u = mda.Universe.empty( + # topology things + n_atoms=n_atoms, + n_residues=n_residues, + n_segments=n_segments, + atom_resindex=np.repeat( + np.arange(n_residues), n_atoms // n_residues), + residue_segindex=np.repeat( + np.arange(n_segments), n_residues // n_segments), + # trajectory things + trajectory=trajectory, + velocities=velocities, + forces=forces, + ) + if extras is None: + extras = [] + for ex in extras: + u.add_TopologyAttr(ex) + + if trajectory: + pos = np.arange(3 * n_atoms * n_frames).reshape(n_frames, n_atoms, 3) + vel = pos + 100 if velocities else None + fcs = pos + 10000 if forces else None + reader = MemoryReader( + pos, + velocities=vel, + forces=fcs, + ) + u.trajectory = reader + + return u diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml new file mode 100644 index 0000000..b91b979 --- /dev/null +++ b/devtools/conda-envs/test_env.yaml @@ -0,0 +1,18 @@ +name: mdakit-Cookie-test +channels: + - defaults +dependencies: + # Base depends + - python + - pip + + # Testing + - pytest + - pytest-cov + - pytest-xdist + + # Pip-only installs + - pip: + - codecov + - MDAnalysis + diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..b9df5b1 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = mdakit-Cookie +SOURCEDIR = source +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..2c4887f --- /dev/null +++ b/docs/README.md @@ -0,0 +1,24 @@ +# Compiling TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs's Documentation + +The docs for this project are built with [Sphinx](http://www.sphinx-doc.org/en/master/). +To compile the docs, first ensure that Sphinx and the ReadTheDocs theme are installed. + + +```bash +conda install sphinx sphinx_rtd_theme +``` + + +Once installed, you can use the `Makefile` in this directory to compile static HTML pages by +```bash +make html +``` + +The compiled docs will be in the `_build` directory and can be viewed by opening `index.html` (which may itself +be inside a directory called `html/` depending on what version of Sphinx is installed). + + +A configuration file for [Read The Docs](https://readthedocs.org/) (readthedocs.yaml) is included in the top level of the repository. To use Read the Docs to host your documentation, go to https://readthedocs.org/ and connect this repository. You may need to change your default branch to `main` under Advanced Settings for the project. + +If you would like to use Read The Docs with `autodoc` (included automatically) and your package has dependencies, you will need to include those dependencies in your documentation yaml file (`docs/requirements.yaml`). + diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..48948e3 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build +set SPHINXPROJ=mdakit-Cookie + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/docs/requirements.yaml b/docs/requirements.yaml new file mode 100644 index 0000000..133da0f --- /dev/null +++ b/docs/requirements.yaml @@ -0,0 +1,13 @@ +name: mdakit-Cookie-docs +channels: + + - defaults + +dependencies: + # Base depends + - python + - pip + + - mdanalysis-sphinx-theme >=1.0.1 + # Pip-only installs + #- pip: diff --git a/docs/source/_static/README.md b/docs/source/_static/README.md new file mode 100644 index 0000000..da94cbc --- /dev/null +++ b/docs/source/_static/README.md @@ -0,0 +1,29 @@ +# Static Doc Directory + +Add any paths that contain custom static files (such as style sheets) here, +relative to the `conf.py` file's directory. +They are copied after the builtin static files, +so a file named "default.css" will overwrite the builtin "default.css". + +The path to this folder is set in the Sphinx `conf.py` file in the line: +```python +html_static_path = ['_static'] +``` + +## Examples of file to add to this directory +* Custom Cascading Style Sheets +* Custom JavaScript code +* Static logo images + + +### Logos + +Several template and placeholder logo documents are +already provided in this repo. +We encourage you to replace them with your own custom logos! +You can either use an entirely new image, or edit our +template documents (for example, by placing your own logo +within the gears). + +All "Empty gear" and placeholder documents in the ``logo/`` directory are provided +under a [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/) license under the [terms of our license document](https://github.com/MDAnalysis/branding/blob/main/logos/LICENSE). diff --git a/docs/source/_static/logo/mdakits-empty-favicon-template.svg b/docs/source/_static/logo/mdakits-empty-favicon-template.svg new file mode 100644 index 0000000..333dede --- /dev/null +++ b/docs/source/_static/logo/mdakits-empty-favicon-template.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + diff --git a/docs/source/_static/logo/mdakits-empty-logo-template.svg b/docs/source/_static/logo/mdakits-empty-logo-template.svg new file mode 100644 index 0000000..279ba87 --- /dev/null +++ b/docs/source/_static/logo/mdakits-empty-logo-template.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + diff --git a/docs/source/_static/logo/mdakits-placeholder-logo.png b/docs/source/_static/logo/mdakits-placeholder-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..427c3b4fb92d6ee2cc420da882ec243855e9ac21 GIT binary patch literal 50632 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 x-8%jE?_3Zef{^-PmaNDB|3Ck~E{)+$_ViE2!g< literal 0 HcmV?d00001 diff --git a/docs/source/_templates/README.md b/docs/source/_templates/README.md new file mode 100644 index 0000000..e8e210a --- /dev/null +++ b/docs/source/_templates/README.md @@ -0,0 +1,14 @@ +# Templates Doc Directory + +Add any paths that contain templates here, relative to +the `conf.py` file's directory. +They are copied after the builtin template files, +so a file named "page.html" will overwrite the builtin "page.html". + +The path to this folder is set in the Sphinx `conf.py` file in the line: +```python +templates_path = ['_templates'] +``` + +## Examples of file to add to this directory +* HTML extensions of stock pages like `page.html` or `layout.html` diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 0000000..7dcb257 --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,8 @@ +API Documentation +================= + +.. autosummary:: + :toctree: autosummary + :recursive: + + cookieKit diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..830f086 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,197 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/stable/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. + +# In case the project was not installed +import os +import sys +sys.path.insert(0, os.path.abspath("../..")) +import cookieKit # noqa + + + +# -- Project information ----------------------------------------------------- + +project = "TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs" +copyright = ( + "2024, Test User name. " + "Project structure based on the " + "MDAnalysis Cookiecutter version 0.1" +) +author = "Test User name" + +# The short X.Y version +version = "" +# The full version, including alpha/beta/rc tags +release = "" + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +needs_sphinx = "6.2.1" + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named "sphinx.ext.*") or your custom +# ones. +extensions = [ + "sphinx.ext.autosummary", + "sphinx.ext.autodoc", + "sphinx.ext.mathjax", + "sphinx.ext.viewcode", + "sphinx.ext.napoleon", + "sphinx.ext.intersphinx", + "sphinx.ext.extlinks", + "mdanalysis_sphinx_theme", +] + +autosummary_generate = True +# This skips generating an autodoc of the test module +# when using the autosummary directive that is included +# by default in api.rst +autodoc_mock_imports = [ + 'cookieKit.tests' +] +napoleon_google_docstring = False +napoleon_use_param = False +napoleon_use_ivar = True + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = [".rst", ".md"] +source_suffix = ".rst" + +# The master toctree document. +master_doc = "index" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = "en" + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path . +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "default" + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "mdanalysis_sphinx_theme" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +html_theme_options = { + + "mda_official": False, + +} + +# Set your logo and favicon here -- replace the placeholders! +# An SVG with empty gears is provided for editing +html_logo = "_static/logo/mdakits-placeholder-logo.png" +html_favicon = "_static/logo/mdakits-empty-favicon-template.svg" + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``["localtoc.html", "relations.html", "sourcelink.html", +# "searchbox.html"]``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = "mdakit-Cookiedoc" + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ("letterpaper" or "a4paper"). + # + # "papersize": "letterpaper", + + # The font size ("10pt", "11pt" or "12pt"). + # + # "pointsize": "10pt", + + # Additional stuff for the LaTeX preamble. + # + # "preamble": "", + + # Latex figure (float) alignment + # + # "figure_align": "htbp", +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, "mdakit-Cookie.tex", "TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs Documentation", + "mdakit-Cookie", "manual"), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, "mdakit-Cookie", "TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs Documentation", + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, "mdakit-Cookie", "TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs Documentation", + author, "mdakit-Cookie", "Test MDAKit Project with dependencies using anaconda and ReadTheDocs", + "Miscellaneous"), +] + + +# -- Extension configuration ------------------------------------------------- +intersphinx_mapping = { + "python": ("https://docs.python.org/3/", None), + "mdanalysis": ("https://docs.mdanalysis.org/stable/", None), +} diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst new file mode 100644 index 0000000..526c5f1 --- /dev/null +++ b/docs/source/getting_started.rst @@ -0,0 +1,4 @@ +Getting Started +=============== + +This page details how to get started with TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs. diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..aeead5e --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,23 @@ +.. mdakit-Cookie documentation master file, created by + sphinx-quickstart on Thu Mar 15 13:55:56 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to TestMDAKit_with_host_other_anaconda-deps_and_ReadTheDocs's documentation! +========================================================= + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + getting_started + api + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..0c59e37 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,92 @@ +[build-system] +requires = [ + "setuptools >=61.2", + "versioningit", +] +build-backend = "setuptools.build_meta" + +[project] +name = "mdakit-Cookie" +description = "Test MDAKit Project with dependencies using anaconda and ReadTheDocs" +license = {file = "LICENSE" } +authors = [ + {name = "Test User name", email = "test_email@test.com"}, +] +maintainers = [ + {name = "Test User name", email = "test_email@test.com"}, +] +readme = "README.md" +requires-python = ">=3.9" +dependencies = [ + "MDAnalysis>=2.0.0", +] +keywords = [ + "molecular simulations", +] +dynamic = [ + "version", +] + +[project.optional-dependencies] +test = [ + "pytest>=6.0", + "pytest-xdist>=2.5", + "pytest-cov>=3.0", +] +doc = [ + "sphinx", + "sphinx_rtd_theme", +] + +# [project.urls] +# source = "https://github.com/other/mdakit-Cookie" +# documentation = "https://mdakit-Cookie.readthedocs.io" + +[tool.setuptools.packages.find] +include = ["cookieKit"] + +[tool.pytest.ini_options] +minversion = "6.0" +testpaths = [ + "cookieKit/tests", +] + +[tool.black] +line-length = 80 + +[tool.versioningit] +default-version = "1+unknown" + +[tool.versioningit.vcs] +method = "git" +# the below line expects tags to look like '1.0.2'. +# if prefixing with a v, e.g. 'v1.0.2', change it to ["v*"] +match = ["*"] + +[tool.versioningit.format] +distance = "{base_version}+{distance}.{vcs}{rev}" +dirty = "{base_version}+{distance}.{vcs}{rev}.dirty" +distance-dirty = "{base_version}+{distance}.{vcs}{rev}.dirty" + +[tool.coverage.run] +omit = [ + # Omit the tests + "*/tests/*", +] + +[tool.coverage.report] +exclude_also = [ + "if TYPE_CHECKING:", +] + +[tool.isort] +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +use_parentheses = true +line_length = 80 + +[tool.yapf] +COLUMN_LIMIT = 80 +INDENT_WIDTH = 4 +USE_TABS = false diff --git a/readthedocs.yaml b/readthedocs.yaml new file mode 100644 index 0000000..cab6477 --- /dev/null +++ b/readthedocs.yaml @@ -0,0 +1,16 @@ +# readthedocs.yaml + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "mambaforge-4.10" + +python: + install: + - method: pip + path: . + +conda: + environment: docs/requirements.yaml