Chore: Initial commit 16/71216/1
authorMatthew Watkins <mwatkins@linuxfoundation.org>
Wed, 8 Feb 2023 14:28:45 +0000 (14:28 +0000)
committerMatthew Watkins <mwatkins@linuxfoundation.org>
Wed, 8 Feb 2023 14:55:04 +0000 (14:55 +0000)
Signed-off-by: Matthew Watkins <mwatkins@linuxfoundation.org>
Change-Id: I27814ec48804fcb3ec0a618f9b2ed6f2cdc12ceb

31 files changed:
.coveragerc [new file with mode: 0644]
.editorconfig [new file with mode: 0644]
.gitignore [new file with mode: 0644]
.gitlint [new file with mode: 0644]
.gitreview [new file with mode: 0644]
.isort.cfg [new file with mode: 0644]
.pre-commit-config.yaml [new file with mode: 0644]
.readthedocs.yml [new file with mode: 0644]
AUTHORS.rst [new file with mode: 0644]
CHANGELOG.rst [new file with mode: 0644]
CONTRIBUTING.rst [new file with mode: 0644]
LICENSE.txt [new file with mode: 0644]
README.rst [new file with mode: 0644]
docs/Makefile [new file with mode: 0644]
docs/_static/.gitignore [new file with mode: 0644]
docs/authors.rst [new file with mode: 0644]
docs/changelog.rst [new file with mode: 0644]
docs/conf.py [new file with mode: 0644]
docs/contributing.rst [new file with mode: 0644]
docs/index.rst [new file with mode: 0644]
docs/license.rst [new file with mode: 0644]
docs/readme.rst [new file with mode: 0644]
docs/requirements.txt [new file with mode: 0644]
pyproject.toml [new file with mode: 0644]
setup.cfg [new file with mode: 0644]
setup.py [new file with mode: 0644]
src/python_one_password/__init__.py [new file with mode: 0644]
src/python_one_password/skeleton.py [new file with mode: 0644]
tests/conftest.py [new file with mode: 0644]
tests/test_skeleton.py [new file with mode: 0644]
tox.ini [new file with mode: 0644]

diff --git a/.coveragerc b/.coveragerc
new file mode 100644 (file)
index 0000000..1bf175a
--- /dev/null
@@ -0,0 +1,28 @@
+# .coveragerc to control coverage.py
+[run]
+branch = True
+source = python_one_password
+# omit = bad_file.py
+
+[paths]
+source =
+    src/
+    */site-packages/
+
+[report]
+# Regexes for lines to exclude from consideration
+exclude_lines =
+    # Have to re-enable the standard pragma
+    pragma: no cover
+
+    # Don't complain about missing debug-only code:
+    def __repr__
+    if self\.debug
+
+    # Don't complain if tests don't hit defensive assertion code:
+    raise AssertionError
+    raise NotImplementedError
+
+    # Don't complain if non-runnable code isn't run:
+    if 0:
+    if __name__ == .__main__.:
diff --git a/.editorconfig b/.editorconfig
new file mode 100644 (file)
index 0000000..0d865ee
--- /dev/null
@@ -0,0 +1,28 @@
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = space
+
+[*.json]
+indent_size = 2
+
+[*.rst]
+indent_size = 4
+
+[*.markdown]
+indent_size = 4
+max_line_length = 80
+
+[*.py]
+indent_size = 4
+max_line_legth = 120
+
+[*.sh]
+indent_size = 4
+max_line_length = 80
+
+[*.yaml]
+indent_size = 4
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..e9e1e9b
--- /dev/null
@@ -0,0 +1,54 @@
+# Temporary and binary files
+*~
+*.py[cod]
+*.so
+*.cfg
+!.isort.cfg
+!setup.cfg
+*.orig
+*.log
+*.pot
+__pycache__/*
+.cache/*
+.*.swp
+*/.ipynb_checkpoints/*
+.DS_Store
+
+# Project files
+.ropeproject
+.project
+.pydevproject
+.settings
+.idea
+.vscode
+tags
+
+# Package files
+*.egg
+*.eggs/
+.installed.cfg
+*.egg-info
+
+# Unittest and coverage
+htmlcov/*
+.coverage
+.coverage.*
+.tox
+junit*.xml
+coverage.xml
+.pytest_cache/
+
+# Build and docs folder/files
+build/*
+dist/*
+sdist/*
+docs/api/*
+docs/_rst/*
+docs/_build/*
+cover/*
+MANIFEST
+
+# Per-project virtualenvs
+.venv*/
+.conda*/
+.python-version
diff --git a/.gitlint b/.gitlint
new file mode 100644 (file)
index 0000000..463ce1f
--- /dev/null
+++ b/.gitlint
@@ -0,0 +1,100 @@
+# All these sections are optional, edit this file as you like.
+[general]
+# Ignore certain rules, you can reference them by their id or by their full
+# name
+# ignore=title-trailing-punctuation, T3
+
+# verbosity should be a value between 1 and 3, the command line -v flags take
+# precedence over this
+# verbosity = 2
+
+# By default gitlint will ignore merge commits. Set to 'false' to disable.
+# ignore-merge-commits=true
+
+# By default gitlint will ignore fixup commits. Set to 'false' to disable.
+# ignore-fixup-commits=true
+
+# By default gitlint will ignore squash commits. Set to 'false' to disable.
+# ignore-squash-commits=true
+
+# Enable debug mode (prints more output). Disabled by default.
+# debug=true
+
+# Set the extra-path where gitlint will search for user defined rules
+# See http://jorisroovers.github.io/gitlint/user_defined_rules for details
+# extra-path=examples/
+
+contrib=contrib-title-conventional-commits,contrib-body-requires-signed-off-by
+
+# [title-max-length]
+# line-length=80
+
+# [title-must-not-contain-word]
+# Comma-separated list of words that should not occur in the title. Matching is
+# case insensitive. It's fine if the keyword occurs as part of a larger word
+# (so "WIPING" will not cause a violation, but "WIP: my title" will.
+# words=wip
+
+# [title-match-regex]
+# python like regex (https://docs.python.org/2/library/re.html) that the
+# commit-msg title must be matched to.
+# Note that the regex can contradict with other rules if not used correctly
+# (e.g. title-must-not-contain-word).
+# regex=^US[0-9]*
+
+# [B1]
+# B1 = body-max-line-length
+# line-length=120
+
+# [body-min-length]
+# min-length=5
+
+# [body-is-missing]
+# Whether to ignore this rule on merge commits (which typically only have a title)
+# default = True
+# ignore-merge-commits=false
+
+# [body-changed-file-mention]
+# List of files that need to be explicitly mentioned in the body when they are
+# changed This is useful for when developers often erroneously edit certain
+# files or git submodules.  By specifying this rule, developers can only change
+# the file when they explicitly reference it in the commit message.
+# files=gitlint/rules.py,README.md
+
+# [author-valid-email]
+# python like regex (https://docs.python.org/2/library/re.html) that the
+# commit author email address should be matched to
+# For example, use the following regex if you only want to allow email
+# addresses from foo.com
+# regex=[^@]+@foo.com
+
+# [ignore-by-title]
+# Ignore certain rules for commits of which the title matches a regex
+# E.g. Match commit titles that start with "Release"
+# regex=^Release(.*)
+#
+# Ignore certain rules, you can reference them by their id or by their full name
+# Use 'all' to ignore all rules
+# ignore=T1,body-min-length
+
+# [ignore-by-body]
+# Ignore certain rules for commits of which the body has a line that matches a
+# regex
+# E.g. Match bodies that have a line that contain "release"
+# regex=(.*)release(.*)
+#
+# Ignore certain rules, you can reference them by their id or by their full name
+# Use 'all' to ignore all rules
+# ignore=T1,body-min-length
+
+# Enable Conventional Commit subject line enforcement
+# https://www.conventionalcommits.org/en/v1.0.0/
+#
+# Since we want all subjects to be well formed, enforce the topics
+# to the following (fairly standard) topics and require them to be Mixed Case
+[contrib-title-conventional-commits]
+types=Fix,Feat,Chore,Docs,Style,Refactor,Perf,Test,Revert,CI,Build
+
+# Require RELENG issues in commit messages
+#[body-match-regex]
+#regex=(.*)Issue:\s+(?<!IT)RELENG-\d+(.*)
diff --git a/.gitreview b/.gitreview
new file mode 100644 (file)
index 0000000..b9b7947
--- /dev/null
@@ -0,0 +1,5 @@
+[gerrit]
+host=gerrit.linuxfoundation.org
+port=29418
+project=releng/python-one-password.git
+defaultbranch=main
diff --git a/.isort.cfg b/.isort.cfg
new file mode 100644 (file)
index 0000000..d38ad9d
--- /dev/null
@@ -0,0 +1,3 @@
+[settings]
+profile = black
+known_first_party = python_one_password
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644 (file)
index 0000000..2c368e7
--- /dev/null
@@ -0,0 +1,74 @@
+---
+exclude: '^docs/conf.py'
+
+repos:
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v4.4.0
+    hooks:
+      - id: trailing-whitespace
+      - id: check-added-large-files
+      - id: check-ast
+      - id: check-json
+      - id: check-merge-conflict
+      - id: check-xml
+      - id: check-yaml
+      - id: debug-statements
+      - id: end-of-file-fixer
+      - id: requirements-txt-fixer
+      - id: mixed-line-ending
+        args: ['--fix=lf']  # replace 'auto' with 'lf' to enforce Linux/Mac line endings or 'crlf' for Windows
+
+  - repo: https://github.com/jorisroovers/gitlint
+    rev: v0.17.0
+    hooks:
+      - id: gitlint
+
+## If you want to automatically "modernize" your Python code:
+# - repo: https://github.com/asottile/pyupgrade
+#   rev: v3.3.1
+#   hooks:
+#   - id: pyupgrade
+#     args: ['--py37-plus']
+
+## If you want to avoid flake8 errors due to unused vars or imports:
+# - repo: https://github.com/PyCQA/autoflake
+#   rev: v2.0.0
+#   hooks:
+#   - id: autoflake
+#     args: [
+#       --in-place,
+#       --remove-all-unused-imports,
+#       --remove-unused-variables,
+#     ]
+
+  - repo: https://github.com/PyCQA/isort
+    rev: 5.12.0
+    hooks:
+      - id: isort
+
+  - repo: https://github.com/psf/black
+    rev: 23.1.0
+    hooks:
+      - id: black
+        language_version: python3
+
+## If like to embrace black styles even in the docs:
+# - repo: https://github.com/asottile/blacken-docs
+#   rev: v1.13.0
+#   hooks:
+#   - id: blacken-docs
+#     additional_dependencies: [black]
+
+  - repo: https://github.com/PyCQA/flake8
+    rev: 6.0.0
+    hooks:
+      - id: flake8
+        args: ["--max-line-length=120"]
+      ## You can add flake8 plugins via `additional_dependencies`:
+      #  additional_dependencies: [flake8-bugbear]
+
+## Check for misspells in documentation files:
+# - repo: https://github.com/codespell-project/codespell
+#   rev: v2.2.2
+#   hooks:
+#   - id: codespell
diff --git a/.readthedocs.yml b/.readthedocs.yml
new file mode 100644 (file)
index 0000000..a2bcab3
--- /dev/null
@@ -0,0 +1,27 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Build documentation in the docs/ directory with Sphinx
+sphinx:
+  configuration: docs/conf.py
+
+# Build documentation with MkDocs
+#mkdocs:
+#  configuration: mkdocs.yml
+
+# Optionally build your docs in additional formats such as PDF
+formats:
+  - pdf
+
+build:
+  os: ubuntu-22.04
+  tools:
+    python: "3.11"
+
+python:
+  install:
+    - requirements: docs/requirements.txt
+    - {path: ., method: pip}
diff --git a/AUTHORS.rst b/AUTHORS.rst
new file mode 100644 (file)
index 0000000..9517329
--- /dev/null
@@ -0,0 +1,5 @@
+============
+Contributors
+============
+
+* Matthew Watkins <mwatkins@linuxfoundation.org>
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
new file mode 100644 (file)
index 0000000..226e6f5
--- /dev/null
@@ -0,0 +1,10 @@
+=========
+Changelog
+=========
+
+Version 0.1
+===========
+
+- Feature A added
+- FIX: nasty bug #1729 fixed
+- add your changes here!
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
new file mode 100644 (file)
index 0000000..e593f99
--- /dev/null
@@ -0,0 +1,353 @@
+.. todo:: THIS IS SUPPOSED TO BE AN EXAMPLE. MODIFY IT ACCORDING TO YOUR NEEDS!
+
+   The document assumes you are using a source repository service that promotes a
+   contribution model similar to `GitHub's fork and pull request workflow`_.
+   While this is true for the majority of services (like GitHub, GitLab,
+   BitBucket), it might not be the case for private repositories (e.g., when
+   using Gerrit).
+
+   Also notice that the code examples might refer to GitHub URLs or the text
+   might use GitHub specific terminology (e.g., *Pull Request* instead of *Merge
+   Request*).
+
+   Please make sure to check the document having these assumptions in mind
+   and update things accordingly.
+
+.. todo:: Provide the correct links/replacements at the bottom of the document.
+
+.. todo:: You might want to have a look on `PyScaffold's contributor's guide`_,
+
+   especially if your project is open source. The text should be very similar to
+   this template, but there are a few extra contents that you might decide to
+   also include, like mentioning labels of your issue tracker or automated
+   releases.
+
+
+============
+Contributing
+============
+
+Welcome to ``python-one-password`` contributor's guide.
+
+This document focuses on getting any potential contributor familiarized
+with the development processes, but `other kinds of contributions`_ are also
+appreciated.
+
+If you are new to using git_ or have never collaborated in a project previously,
+please have a look at `contribution-guide.org`_. Other resources are also
+listed in the excellent `guide created by FreeCodeCamp`_ [#contrib1]_.
+
+Please notice, all users and contributors are expected to be **open,
+considerate, reasonable, and respectful**. When in doubt, `Python Software
+Foundation's Code of Conduct`_ is a good reference in terms of behavior
+guidelines.
+
+
+Issue Reports
+=============
+
+If you experience bugs or general issues with ``python-one-password``, please have a look
+on the `issue tracker`_. If you don't see anything useful there, please feel
+free to fire an issue report.
+
+.. tip::
+   Please don't forget to include the closed issues in your search.
+   Sometimes a solution was already reported, and the problem is considered
+   **solved**.
+
+New issue reports should include information about your programming environment
+(e.g., operating system, Python version) and steps to reproduce the problem.
+Please try also to simplify the reproduction steps to a very minimal example
+that still illustrates the problem you are facing. By removing other factors,
+you help us to identify the root cause of the issue.
+
+
+Documentation Improvements
+==========================
+
+You can help improve ``python-one-password`` docs by making them more readable and coherent, or
+by adding missing information and correcting mistakes.
+
+``python-one-password`` documentation uses Sphinx_ as its main documentation compiler.
+This means that the docs are kept in the same repository as the project code, and
+that any documentation update is done in the same way was a code contribution.
+
+.. todo:: Don't forget to mention which markup language you are using.
+
+    e.g.,  reStructuredText_ or CommonMark_ with MyST_ extensions.
+
+.. todo:: If your project is hosted on GitHub, you can also mention the following tip:
+
+   .. tip::
+      Please notice that the `GitHub web interface`_ provides a quick way of
+      propose changes in ``python-one-password``'s files. While this mechanism can
+      be tricky for normal code contributions, it works perfectly fine for
+      contributing to the docs, and can be quite handy.
+
+      If you are interested in trying this method out, please navigate to
+      the ``docs`` folder in the source repository_, find which file you
+      would like to propose changes and click in the little pencil icon at the
+      top, to open `GitHub's code editor`_. Once you finish editing the file,
+      please write a message in the form at the bottom of the page describing
+      which changes have you made and what are the motivations behind them and
+      submit your proposal.
+
+When working on documentation changes in your local machine, you can
+compile them using |tox|_::
+
+    tox -e docs
+
+and use Python's built-in web server for a preview in your web browser
+(``http://localhost:8000``)::
+
+    python3 -m http.server --directory 'docs/_build/html'
+
+
+Code Contributions
+==================
+
+.. todo:: Please include a reference or explanation about the internals of the project.
+
+   An architecture description, design principles or at least a summary of the
+   main concepts will make it easy for potential contributors to get started
+   quickly.
+
+Submit an issue
+---------------
+
+Before you work on any non-trivial code contribution it's best to first create
+a report in the `issue tracker`_ to start a discussion on the subject.
+This often provides additional considerations and avoids unnecessary work.
+
+Create an environment
+---------------------
+
+Before you start coding, we recommend creating an isolated `virtual
+environment`_ to avoid any problems with your installed Python packages.
+This can easily be done via either |virtualenv|_::
+
+    virtualenv <PATH TO VENV>
+    source <PATH TO VENV>/bin/activate
+
+or Miniconda_::
+
+    conda create -n python-one-password python=3 six virtualenv pytest pytest-cov
+    conda activate python-one-password
+
+Clone the repository
+--------------------
+
+#. Create an user account on |the repository service| if you do not already have one.
+#. Fork the project repository_: click on the *Fork* button near the top of the
+   page. This creates a copy of the code under your account on |the repository service|.
+#. Clone this copy to your local disk::
+
+    git clone git@github.com:YourLogin/python-one-password.git
+    cd python-one-password
+
+#. You should run::
+
+    pip install -U pip setuptools -e .
+
+   to be able to import the package under development in the Python REPL.
+
+   .. todo:: if you are not using pre-commit, please remove the following item:
+
+#. Install |pre-commit|_::
+
+    pip install pre-commit
+    pre-commit install
+
+   ``python-one-password`` comes with a lot of hooks configured to automatically help the
+   developer to check the code being written.
+
+Implement your changes
+----------------------
+
+#. Create a branch to hold your changes::
+
+    git checkout -b my-feature
+
+   and start making changes. Never work on the main branch!
+
+#. Start your work on this branch. Don't forget to add docstrings_ to new
+   functions, modules and classes, especially if they are part of public APIs.
+
+#. Add yourself to the list of contributors in ``AUTHORS.rst``.
+
+#. When you’re done editing, do::
+
+    git add <MODIFIED FILES>
+    git commit
+
+   to record your changes in git_.
+
+   .. todo:: if you are not using pre-commit, please remove the following item:
+
+   Please make sure to see the validation messages from |pre-commit|_ and fix
+   any eventual issues.
+   This should automatically use flake8_/black_ to check/fix the code style
+   in a way that is compatible with the project.
+
+   .. important:: Don't forget to add unit tests and documentation in case your
+      contribution adds an additional feature and is not just a bugfix.
+
+      Moreover, writing a `descriptive commit message`_ is highly recommended.
+      In case of doubt, you can check the commit history with::
+
+         git log --graph --decorate --pretty=oneline --abbrev-commit --all
+
+      to look for recurring communication patterns.
+
+#. Please check that your changes don't break any unit tests with::
+
+    tox
+
+   (after having installed |tox|_ with ``pip install tox`` or ``pipx``).
+
+   You can also use |tox|_ to run several other pre-configured tasks in the
+   repository. Try ``tox -av`` to see a list of the available checks.
+
+Submit your contribution
+------------------------
+
+#. If everything works fine, push your local branch to |the repository service| with::
+
+    git push -u origin my-feature
+
+#. Go to the web page of your fork and click |contribute button|
+   to send your changes for review.
+
+   .. todo:: if you are using GitHub, you can uncomment the following paragraph
+
+      Find more detailed information in `creating a PR`_. You might also want to open
+      the PR as a draft first and mark it as ready for review after the feedbacks
+      from the continuous integration (CI) system or any required fixes.
+
+
+Troubleshooting
+---------------
+
+The following tips can be used when facing problems to build or test the
+package:
+
+#. Make sure to fetch all the tags from the upstream repository_.
+   The command ``git describe --abbrev=0 --tags`` should return the version you
+   are expecting. If you are trying to run CI scripts in a fork repository,
+   make sure to push all the tags.
+   You can also try to remove all the egg files or the complete egg folder, i.e.,
+   ``.eggs``, as well as the ``*.egg-info`` folders in the ``src`` folder or
+   potentially in the root of your project.
+
+#. Sometimes |tox|_ misses out when new dependencies are added, especially to
+   ``setup.cfg`` and ``docs/requirements.txt``. If you find any problems with
+   missing dependencies when running a command with |tox|_, try to recreate the
+   ``tox`` environment using the ``-r`` flag. For example, instead of::
+
+    tox -e docs
+
+   Try running::
+
+    tox -r -e docs
+
+#. Make sure to have a reliable |tox|_ installation that uses the correct
+   Python version (e.g., 3.7+). When in doubt you can run::
+
+    tox --version
+    # OR
+    which tox
+
+   If you have trouble and are seeing weird errors upon running |tox|_, you can
+   also try to create a dedicated `virtual environment`_ with a |tox|_ binary
+   freshly installed. For example::
+
+    virtualenv .venv
+    source .venv/bin/activate
+    .venv/bin/pip install tox
+    .venv/bin/tox -e all
+
+#. `Pytest can drop you`_ in an interactive session in the case an error occurs.
+   In order to do that you need to pass a ``--pdb`` option (for example by
+   running ``tox -- -k <NAME OF THE FALLING TEST> --pdb``).
+   You can also setup breakpoints manually instead of using the ``--pdb`` option.
+
+
+Maintainer tasks
+================
+
+Releases
+--------
+
+.. todo:: This section assumes you are using PyPI to publicly release your package.
+
+   If instead you are using a different/private package index, please update
+   the instructions accordingly.
+
+If you are part of the group of maintainers and have correct user permissions
+on PyPI_, the following steps can be used to release a new version for
+``python-one-password``:
+
+#. Make sure all unit tests are successful.
+#. Tag the current commit on the main branch with a release tag, e.g., ``v1.2.3``.
+#. Push the new tag to the upstream repository_, e.g., ``git push upstream v1.2.3``
+#. Clean up the ``dist`` and ``build`` folders with ``tox -e clean``
+   (or ``rm -rf dist build``)
+   to avoid confusion with old builds and Sphinx docs.
+#. Run ``tox -e build`` and check that the files in ``dist`` have
+   the correct version (no ``.dirty`` or git_ hash) according to the git_ tag.
+   Also check the sizes of the distributions, if they are too big (e.g., >
+   500KB), unwanted clutter may have been accidentally included.
+#. Run ``tox -e publish -- --repository pypi`` and check that everything was
+   uploaded to PyPI_ correctly.
+
+
+
+.. [#contrib1] Even though, these resources focus on open source projects and
+   communities, the general ideas behind collaborating with other developers
+   to collectively create software are general and can be applied to all sorts
+   of environments, including private companies and proprietary code bases.
+
+
+.. <-- start -->
+.. todo:: Please review and change the following definitions:
+
+.. |the repository service| replace:: GitHub
+.. |contribute button| replace:: "Create pull request"
+
+.. _repository: https://github.com/<USERNAME>/python-one-password
+.. _issue tracker: https://github.com/<USERNAME>/python-one-password/issues
+.. <-- end -->
+
+
+.. |virtualenv| replace:: ``virtualenv``
+.. |pre-commit| replace:: ``pre-commit``
+.. |tox| replace:: ``tox``
+
+
+.. _black: https://pypi.org/project/black/
+.. _CommonMark: https://commonmark.org/
+.. _contribution-guide.org: https://www.contribution-guide.org/
+.. _creating a PR: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request
+.. _descriptive commit message: https://chris.beams.io/posts/git-commit
+.. _docstrings: https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html
+.. _first-contributions tutorial: https://github.com/firstcontributions/first-contributions
+.. _flake8: https://flake8.pycqa.org/en/stable/
+.. _git: https://git-scm.com
+.. _GitHub's fork and pull request workflow: https://guides.github.com/activities/forking/
+.. _guide created by FreeCodeCamp: https://github.com/FreeCodeCamp/how-to-contribute-to-open-source
+.. _Miniconda: https://docs.conda.io/en/latest/miniconda.html
+.. _MyST: https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html
+.. _other kinds of contributions: https://opensource.guide/how-to-contribute
+.. _pre-commit: https://pre-commit.com/
+.. _PyPI: https://pypi.org/
+.. _PyScaffold's contributor's guide: https://pyscaffold.org/en/stable/contributing.html
+.. _Pytest can drop you: https://docs.pytest.org/en/stable/how-to/failures.html#using-python-library-pdb-with-pytest
+.. _Python Software Foundation's Code of Conduct: https://www.python.org/psf/conduct/
+.. _reStructuredText: https://www.sphinx-doc.org/en/master/usage/restructuredtext/
+.. _Sphinx: https://www.sphinx-doc.org/en/master/
+.. _tox: https://tox.wiki/en/stable/
+.. _virtual environment: https://realpython.com/python-virtual-environments-a-primer/
+.. _virtualenv: https://virtualenv.pypa.io/en/stable/
+
+.. _GitHub web interface: https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files
+.. _GitHub's code editor: https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644 (file)
index 0000000..8dada3e
--- /dev/null
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/README.rst b/README.rst
new file mode 100644 (file)
index 0000000..e3f4343
--- /dev/null
@@ -0,0 +1,67 @@
+.. These are examples of badges you might want to add to your README:
+   please update the URLs accordingly
+
+    .. image:: https://api.cirrus-ci.com/github/<USER>/python-one-password.svg?branch=main
+        :alt: Built Status
+        :target: https://cirrus-ci.com/github/<USER>/python-one-password
+    .. image:: https://readthedocs.org/projects/python-one-password/badge/?version=latest
+        :alt: ReadTheDocs
+        :target: https://python-one-password.readthedocs.io/en/stable/
+    .. image:: https://img.shields.io/coveralls/github/<USER>/python-one-password/main.svg
+        :alt: Coveralls
+        :target: https://coveralls.io/r/<USER>/python-one-password
+    .. image:: https://img.shields.io/pypi/v/python-one-password.svg
+        :alt: PyPI-Server
+        :target: https://pypi.org/project/python-one-password/
+    .. image:: https://img.shields.io/conda/vn/conda-forge/python-one-password.svg
+        :alt: Conda-Forge
+        :target: https://anaconda.org/conda-forge/python-one-password
+    .. image:: https://pepy.tech/badge/python-one-password/month
+        :alt: Monthly Downloads
+        :target: https://pepy.tech/project/python-one-password
+    .. image:: https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Twitter
+        :alt: Twitter
+        :target: https://twitter.com/python-one-password
+
+.. image:: https://img.shields.io/badge/-PyScaffold-005CA0?logo=pyscaffold
+    :alt: Project generated with PyScaffold
+    :target: https://pyscaffold.org/
+
+|
+
+===================
+python-one-password
+===================
+
+
+    Tag editor for 1Password
+
+
+A longer description of your project goes here...
+
+
+.. _pyscaffold-notes:
+
+Making Changes & Contributing
+=============================
+
+This project uses `pre-commit`_, please make sure to install it before making any
+changes::
+
+    pip install pre-commit
+    cd python-one-password
+    pre-commit install
+
+It is a good idea to update the hooks to the latest version::
+
+    pre-commit autoupdate
+
+Don't forget to tell your contributors to also install and use pre-commit.
+
+.. _pre-commit: https://pre-commit.com/
+
+Note
+====
+
+This project has been set up using PyScaffold 4.4. For details and usage
+information on PyScaffold see https://pyscaffold.org/.
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644 (file)
index 0000000..31655dd
--- /dev/null
@@ -0,0 +1,29 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS    ?=
+SPHINXBUILD   ?= sphinx-build
+SOURCEDIR     = .
+BUILDDIR      = _build
+AUTODOCDIR    = api
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $?), 1)
+$(error "The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from https://sphinx-doc.org/")
+endif
+
+.PHONY: help clean Makefile
+
+# Put it first so that "make" without argument is like "make help".
+help:
+       @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+clean:
+       rm -rf $(BUILDDIR)/* $(AUTODOCDIR)
+
+# 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)
diff --git a/docs/_static/.gitignore b/docs/_static/.gitignore
new file mode 100644 (file)
index 0000000..3c96363
--- /dev/null
@@ -0,0 +1 @@
+# Empty directory
diff --git a/docs/authors.rst b/docs/authors.rst
new file mode 100644 (file)
index 0000000..cd8e091
--- /dev/null
@@ -0,0 +1,2 @@
+.. _authors:
+.. include:: ../AUTHORS.rst
diff --git a/docs/changelog.rst b/docs/changelog.rst
new file mode 100644 (file)
index 0000000..871950d
--- /dev/null
@@ -0,0 +1,2 @@
+.. _changes:
+.. include:: ../CHANGELOG.rst
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644 (file)
index 0000000..2fcf40b
--- /dev/null
@@ -0,0 +1,286 @@
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# This file only contains a selection of the most common options. For a full
+# list see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import os
+import sys
+import shutil
+
+# -- Path setup --------------------------------------------------------------
+
+__location__ = os.path.dirname(__file__)
+
+# 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.
+sys.path.insert(0, os.path.join(__location__, "../src"))
+
+# -- Run sphinx-apidoc -------------------------------------------------------
+# This hack is necessary since RTD does not issue `sphinx-apidoc` before running
+# `sphinx-build -b html . _build/html`. See Issue:
+# https://github.com/readthedocs/readthedocs.org/issues/1139
+# DON'T FORGET: Check the box "Install your project inside a virtualenv using
+# setup.py install" in the RTD Advanced Settings.
+# Additionally it helps us to avoid running apidoc manually
+
+try:  # for Sphinx >= 1.7
+    from sphinx.ext import apidoc
+except ImportError:
+    from sphinx import apidoc
+
+output_dir = os.path.join(__location__, "api")
+module_dir = os.path.join(__location__, "../src/python_one_password")
+try:
+    shutil.rmtree(output_dir)
+except FileNotFoundError:
+    pass
+
+try:
+    import sphinx
+
+    cmd_line = f"sphinx-apidoc --implicit-namespaces -f -o {output_dir} {module_dir}"
+
+    args = cmd_line.split(" ")
+    if tuple(sphinx.__version__.split(".")) >= ("1", "7"):
+        # This is a rudimentary parse_version to avoid external dependencies
+        args = args[1:]
+
+    apidoc.main(args)
+except Exception as e:
+    print("Running `sphinx-apidoc` failed!\n{}".format(e))
+
+# -- General configuration ---------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+# needs_sphinx = '1.0'
+
+# 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.autodoc",
+    "sphinx.ext.intersphinx",
+    "sphinx.ext.todo",
+    "sphinx.ext.autosummary",
+    "sphinx.ext.viewcode",
+    "sphinx.ext.coverage",
+    "sphinx.ext.doctest",
+    "sphinx.ext.ifconfig",
+    "sphinx.ext.mathjax",
+    "sphinx.ext.napoleon",
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ["_templates"]
+
+# The suffix of source filenames.
+source_suffix = ".rst"
+
+# The encoding of source files.
+# source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = "index"
+
+# General information about the project.
+project = "python-one-password"
+copyright = "2023, Matthew Watkins"
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# version: The short X.Y version.
+# release: The full version, including alpha/beta/rc tags.
+# If you don’t need the separation provided between version and release,
+# just set them both to the same value.
+try:
+    from python_one_password import __version__ as version
+except ImportError:
+    version = ""
+
+if not version or version.lower() == "unknown":
+    version = os.getenv("READTHEDOCS_VERSION", "unknown")  # automatically set by RTD
+
+release = version
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+# language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+# today = ''
+# Else, today_fmt is used as the format for a strftime call.
+# today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".venv"]
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+# default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+# add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+# add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+# show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = "sphinx"
+
+# A list of ignored prefixes for module index sorting.
+# modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+# keep_warnings = False
+
+# If this is True, todo emits a warning for each TODO entries. The default is False.
+todo_emit_warnings = True
+
+
+# -- 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 = "alabaster"
+
+# 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 = {
+    "sidebar_width": "300px",
+    "page_width": "1200px"
+}
+
+# Add any paths that contain custom themes here, relative to this directory.
+# html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+# html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+# html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+# html_logo = ""
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+# html_favicon = None
+
+# 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"]
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+# html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+# html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+# html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+# html_additional_pages = {}
+
+# If false, no module index is generated.
+# html_domain_indices = True
+
+# If false, no index is generated.
+# html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+# html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+# html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+# html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+# html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+# html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+# html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = "python-one-password-doc"
+
+
+# -- 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": "",
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+    ("index", "user_guide.tex", "python-one-password Documentation", "Matthew Watkins", "manual")
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+# latex_logo = ""
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+# latex_use_parts = False
+
+# If true, show page references after internal links.
+# latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+# latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+# latex_appendices = []
+
+# If false, no module index is generated.
+# latex_domain_indices = True
+
+# -- External mapping --------------------------------------------------------
+python_version = ".".join(map(str, sys.version_info[0:2]))
+intersphinx_mapping = {
+    "sphinx": ("https://www.sphinx-doc.org/en/master", None),
+    "python": ("https://docs.python.org/" + python_version, None),
+    "matplotlib": ("https://matplotlib.org", None),
+    "numpy": ("https://numpy.org/doc/stable", None),
+    "sklearn": ("https://scikit-learn.org/stable", None),
+    "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None),
+    "scipy": ("https://docs.scipy.org/doc/scipy/reference", None),
+    "setuptools": ("https://setuptools.pypa.io/en/stable/", None),
+    "pyscaffold": ("https://pyscaffold.org/en/stable", None),
+}
+
+print(f"loading configurations for {project} {version} ...", file=sys.stderr)
diff --git a/docs/contributing.rst b/docs/contributing.rst
new file mode 100644 (file)
index 0000000..e582053
--- /dev/null
@@ -0,0 +1 @@
+.. include:: ../CONTRIBUTING.rst
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644 (file)
index 0000000..bbf7b11
--- /dev/null
@@ -0,0 +1,61 @@
+===================
+python-one-password
+===================
+
+This is the documentation of **python-one-password**.
+
+.. note::
+
+    This is the main page of your project's `Sphinx`_ documentation.
+    It is formatted in `reStructuredText`_. Add additional pages
+    by creating rst-files in ``docs`` and adding them to the `toctree`_ below.
+    Use then `references`_ in order to link them from this page, e.g.
+    :ref:`authors` and :ref:`changes`.
+
+    It is also possible to refer to the documentation of other Python packages
+    with the `Python domain syntax`_. By default you can reference the
+    documentation of `Sphinx`_, `Python`_, `NumPy`_, `SciPy`_, `matplotlib`_,
+    `Pandas`_, `Scikit-Learn`_. You can add more by extending the
+    ``intersphinx_mapping`` in your Sphinx's ``conf.py``.
+
+    The pretty useful extension `autodoc`_ is activated by default and lets
+    you include documentation from docstrings. Docstrings can be written in
+    `Google style`_ (recommended!), `NumPy style`_ and `classical style`_.
+
+
+Contents
+========
+
+.. toctree::
+   :maxdepth: 2
+
+   Overview <readme>
+   Contributions & Help <contributing>
+   License <license>
+   Authors <authors>
+   Changelog <changelog>
+   Module Reference <api/modules>
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+.. _toctree: https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html
+.. _reStructuredText: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html
+.. _references: https://www.sphinx-doc.org/en/stable/markup/inline.html
+.. _Python domain syntax: https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#the-python-domain
+.. _Sphinx: https://www.sphinx-doc.org/
+.. _Python: https://docs.python.org/
+.. _Numpy: https://numpy.org/doc/stable
+.. _SciPy: https://docs.scipy.org/doc/scipy/reference/
+.. _matplotlib: https://matplotlib.org/contents.html#
+.. _Pandas: https://pandas.pydata.org/pandas-docs/stable
+.. _Scikit-Learn: https://scikit-learn.org/stable
+.. _autodoc: https://www.sphinx-doc.org/en/master/ext/autodoc.html
+.. _Google style: https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings
+.. _NumPy style: https://numpydoc.readthedocs.io/en/latest/format.html
+.. _classical style: https://www.sphinx-doc.org/en/master/domains.html#info-field-lists
diff --git a/docs/license.rst b/docs/license.rst
new file mode 100644 (file)
index 0000000..3989c51
--- /dev/null
@@ -0,0 +1,7 @@
+.. _license:
+
+=======
+License
+=======
+
+.. include:: ../LICENSE.txt
diff --git a/docs/readme.rst b/docs/readme.rst
new file mode 100644 (file)
index 0000000..81995ef
--- /dev/null
@@ -0,0 +1,2 @@
+.. _readme:
+.. include:: ../README.rst
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644 (file)
index 0000000..2ddf98a
--- /dev/null
@@ -0,0 +1,5 @@
+# Requirements file for ReadTheDocs, check .readthedocs.yml.
+# To build the module reference correctly, make sure every external package
+# under `install_requires` in `setup.cfg` is also listed here!
+sphinx>=3.2.1
+# sphinx_rtd_theme
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644 (file)
index 0000000..89a5bed
--- /dev/null
@@ -0,0 +1,9 @@
+[build-system]
+# AVOID CHANGING REQUIRES: IT WILL BE UPDATED BY PYSCAFFOLD!
+requires = ["setuptools>=46.1.0", "setuptools_scm[toml]>=5"]
+build-backend = "setuptools.build_meta"
+
+[tool.setuptools_scm]
+# For smarter version schemes and other configuration options,
+# check out https://github.com/pypa/setuptools_scm
+version_scheme = "no-guess-dev"
diff --git a/setup.cfg b/setup.cfg
new file mode 100644 (file)
index 0000000..c7cf2ed
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,125 @@
+# This file is used to configure your project.
+# Read more about the various options under:
+# https://setuptools.pypa.io/en/latest/userguide/declarative_config.html
+# https://setuptools.pypa.io/en/latest/references/keywords.html
+
+[metadata]
+name = python-one-password
+description = Tag editor for 1Password
+author = Matthew Watkins
+author_email = mwatkins@linuxfoundation.org
+license = Apache-2.0
+license_files = LICENSE.txt
+long_description = file: README.rst
+long_description_content_type = text/x-rst; charset=UTF-8
+url = https://gerrit.linuxfoundation.org/infra/releng/python-one-password
+# Add here related links, for example:
+project_urls =
+    Documentation = https://pyscaffold.org/
+#    Source = https://github.com/pyscaffold/pyscaffold/
+#    Changelog = https://pyscaffold.org/en/latest/changelog.html
+#    Tracker = https://github.com/pyscaffold/pyscaffold/issues
+#    Conda-Forge = https://anaconda.org/conda-forge/pyscaffold
+#    Download = https://pypi.org/project/PyScaffold/#files
+#    Twitter = https://twitter.com/PyScaffold
+
+# Change if running only on Windows, Mac or Linux (comma-separated)
+platforms = any
+
+# Add here all kinds of additional classifiers as defined under
+# https://pypi.org/classifiers/
+classifiers =
+    Development Status :: 4 - Beta
+    Programming Language :: Python
+
+
+[options]
+zip_safe = False
+packages = find_namespace:
+include_package_data = True
+package_dir =
+    =src
+
+# Require a min/specific Python version (comma-separated conditions)
+# python_requires = >=3.8
+
+# Add here dependencies of your project (line-separated), e.g. requests>=2.2,<3.0.
+# Version specifiers like >=2.2,<3.0 avoid problems due to API changes in
+# new major versions. This works if the required packages follow Semantic Versioning.
+# For more information, check out https://semver.org/.
+install_requires =
+    importlib-metadata; python_version<"3.8"
+
+
+[options.packages.find]
+where = src
+exclude =
+    tests
+
+[options.extras_require]
+# Add here additional requirements for extra features, to install with:
+# `pip install python-one-password[PDF]` like:
+# PDF = ReportLab; RXP
+
+# Add here test requirements (semicolon/line-separated)
+testing =
+    setuptools
+    pytest
+    pytest-cov
+
+[options.entry_points]
+# Add here console scripts like:
+# console_scripts =
+#     script_name = python_one_password.module:function
+# For example:
+# console_scripts =
+#     fibonacci = python_one_password.skeleton:run
+# And any other entry points, for example:
+# pyscaffold.cli =
+#     awesome = pyscaffoldext.awesome.extension:AwesomeExtension
+
+[tool:pytest]
+# Specify command line options as you would do when invoking pytest directly.
+# e.g. --cov-report html (or xml) for html/xml output or --junitxml junit.xml
+# in order to write a coverage file that can be read by Jenkins.
+# CAUTION: --cov flags may prohibit setting breakpoints while debugging.
+#          Comment those flags to avoid this pytest issue.
+addopts =
+    --cov python_one_password --cov-report term-missing
+    --verbose
+norecursedirs =
+    dist
+    build
+    .tox
+testpaths = tests
+# Use pytest markers to select/deselect specific tests
+# markers =
+#     slow: mark tests as slow (deselect with '-m "not slow"')
+#     system: mark end-to-end system tests
+
+[devpi:upload]
+# Options for the devpi: PyPI server and packaging tool
+# VCS export must be deactivated since we are using setuptools-scm
+no_vcs = 1
+formats = bdist_wheel
+
+[flake8]
+# Some sane defaults for the code style checker flake8
+max_line_length = 88
+extend_ignore = E203, W503
+# ^  Black-compatible
+#    E203 and W503 have edge cases handled by black
+exclude =
+    .tox
+    build
+    dist
+    .eggs
+    docs/conf.py
+
+[pyscaffold]
+# PyScaffold's parameters when the project was created.
+# This will be used when updating. Do not change!
+version = 4.4
+package = python_one_password
+extensions =
+    pre_commit
diff --git a/setup.py b/setup.py
new file mode 100644 (file)
index 0000000..2f67f3f
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,21 @@
+"""
+    Setup file for python-one-password.
+    Use setup.cfg to configure your project.
+
+    This file was generated with PyScaffold 4.4.
+    PyScaffold helps you to put up the scaffold of your new Python project.
+    Learn more under: https://pyscaffold.org/
+"""
+from setuptools import setup
+
+if __name__ == "__main__":
+    try:
+        setup(use_scm_version={"version_scheme": "no-guess-dev"})
+    except:  # noqa
+        print(
+            "\n\nAn error occurred while building the project, "
+            "please ensure you have the most updated version of setuptools, "
+            "setuptools_scm and wheel with:\n"
+            "   pip install -U setuptools setuptools_scm wheel\n\n"
+        )
+        raise
diff --git a/src/python_one_password/__init__.py b/src/python_one_password/__init__.py
new file mode 100644 (file)
index 0000000..c5c960d
--- /dev/null
@@ -0,0 +1,16 @@
+import sys
+
+if sys.version_info[:2] >= (3, 8):
+    # TODO: Import directly (no need for conditional) when `python_requires = >= 3.8`
+    from importlib.metadata import PackageNotFoundError, version  # pragma: no cover
+else:
+    from importlib_metadata import PackageNotFoundError, version  # pragma: no cover
+
+try:
+    # Change here if project is renamed and does not equal the package name
+    dist_name = "python-one-password"
+    __version__ = version(dist_name)
+except PackageNotFoundError:  # pragma: no cover
+    __version__ = "unknown"
+finally:
+    del version, PackageNotFoundError
diff --git a/src/python_one_password/skeleton.py b/src/python_one_password/skeleton.py
new file mode 100644 (file)
index 0000000..5d28aa3
--- /dev/null
@@ -0,0 +1,149 @@
+"""
+This is a skeleton file that can serve as a starting point for a Python
+console script. To run this script uncomment the following lines in the
+``[options.entry_points]`` section in ``setup.cfg``::
+
+    console_scripts =
+         fibonacci = python_one_password.skeleton:run
+
+Then run ``pip install .`` (or ``pip install -e .`` for editable mode)
+which will install the command ``fibonacci`` inside your current environment.
+
+Besides console scripts, the header (i.e. until ``_logger``...) of this file can
+also be used as template for Python modules.
+
+Note:
+    This file can be renamed depending on your needs or safely removed if not needed.
+
+References:
+    - https://setuptools.pypa.io/en/latest/userguide/entry_point.html
+    - https://pip.pypa.io/en/stable/reference/pip_install
+"""
+
+import argparse
+import logging
+import sys
+
+from python_one_password import __version__
+
+__author__ = "Matthew Watkins"
+__copyright__ = "Matthew Watkins"
+__license__ = "Apache-2.0"
+
+_logger = logging.getLogger(__name__)
+
+
+# ---- Python API ----
+# The functions defined in this section can be imported by users in their
+# Python scripts/interactive interpreter, e.g. via
+# `from python_one_password.skeleton import fib`,
+# when using this Python module as a library.
+
+
+def fib(n):
+    """Fibonacci example function
+
+    Args:
+      n (int): integer
+
+    Returns:
+      int: n-th Fibonacci number
+    """
+    assert n > 0
+    a, b = 1, 1
+    for _i in range(n - 1):
+        a, b = b, a + b
+    return a
+
+
+# ---- CLI ----
+# The functions defined in this section are wrappers around the main Python
+# API allowing them to be called directly from the terminal as a CLI
+# executable/script.
+
+
+def parse_args(args):
+    """Parse command line parameters
+
+    Args:
+      args (List[str]): command line parameters as list of strings
+          (for example  ``["--help"]``).
+
+    Returns:
+      :obj:`argparse.Namespace`: command line parameters namespace
+    """
+    parser = argparse.ArgumentParser(description="Just a Fibonacci demonstration")
+    parser.add_argument(
+        "--version",
+        action="version",
+        version=f"python-one-password {__version__}",
+    )
+    parser.add_argument(dest="n", help="n-th Fibonacci number", type=int, metavar="INT")
+    parser.add_argument(
+        "-v",
+        "--verbose",
+        dest="loglevel",
+        help="set loglevel to INFO",
+        action="store_const",
+        const=logging.INFO,
+    )
+    parser.add_argument(
+        "-vv",
+        "--very-verbose",
+        dest="loglevel",
+        help="set loglevel to DEBUG",
+        action="store_const",
+        const=logging.DEBUG,
+    )
+    return parser.parse_args(args)
+
+
+def setup_logging(loglevel):
+    """Setup basic logging
+
+    Args:
+      loglevel (int): minimum loglevel for emitting messages
+    """
+    logformat = "[%(asctime)s] %(levelname)s:%(name)s:%(message)s"
+    logging.basicConfig(
+        level=loglevel, stream=sys.stdout, format=logformat, datefmt="%Y-%m-%d %H:%M:%S"
+    )
+
+
+def main(args):
+    """Wrapper allowing :func:`fib` to be called with string arguments in a CLI fashion
+
+    Instead of returning the value from :func:`fib`, it prints the result to the
+    ``stdout`` in a nicely formatted message.
+
+    Args:
+      args (List[str]): command line parameters as list of strings
+          (for example  ``["--verbose", "42"]``).
+    """
+    args = parse_args(args)
+    setup_logging(args.loglevel)
+    _logger.debug("Starting crazy calculations...")
+    print(f"The {args.n}-th Fibonacci number is {fib(args.n)}")
+    _logger.info("Script ends here")
+
+
+def run():
+    """Calls :func:`main` passing the CLI arguments extracted from :obj:`sys.argv`
+
+    This function can be used as entry point to create console scripts with setuptools.
+    """
+    main(sys.argv[1:])
+
+
+if __name__ == "__main__":
+    # ^  This is a guard statement that will prevent the following code from
+    #    being executed in the case someone imports this file instead of
+    #    executing it as a script.
+    #    https://docs.python.org/3/library/__main__.html
+
+    # After installing your project with pip, users can also run your Python
+    # modules as scripts via the ``-m`` flag, as defined in PEP 338::
+    #
+    #     python -m python_one_password.skeleton 42
+    #
+    run()
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644 (file)
index 0000000..6f8be37
--- /dev/null
@@ -0,0 +1,10 @@
+"""
+    Dummy conftest.py for python_one_password.
+
+    If you don't know what this is for, just leave it empty.
+    Read more about conftest.py under:
+    - https://docs.pytest.org/en/stable/fixture.html
+    - https://docs.pytest.org/en/stable/writing_plugins.html
+"""
+
+# import pytest
diff --git a/tests/test_skeleton.py b/tests/test_skeleton.py
new file mode 100644 (file)
index 0000000..4556355
--- /dev/null
@@ -0,0 +1,25 @@
+import pytest
+
+from python_one_password.skeleton import fib, main
+
+__author__ = "Matthew Watkins"
+__copyright__ = "Matthew Watkins"
+__license__ = "Apache-2.0"
+
+
+def test_fib():
+    """API Tests"""
+    assert fib(1) == 1
+    assert fib(2) == 1
+    assert fib(7) == 13
+    with pytest.raises(AssertionError):
+        fib(-10)
+
+
+def test_main(capsys):
+    """CLI Tests"""
+    # capsys is a pytest fixture that allows asserts against stdout/stderr
+    # https://docs.pytest.org/en/stable/capture.html
+    main(["7"])
+    captured = capsys.readouterr()
+    assert "The 7-th Fibonacci number is 13" in captured.out
diff --git a/tox.ini b/tox.ini
new file mode 100644 (file)
index 0000000..69f8159
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,93 @@
+# Tox configuration file
+# Read more under https://tox.wiki/
+# THIS SCRIPT IS SUPPOSED TO BE AN EXAMPLE. MODIFY IT ACCORDING TO YOUR NEEDS!
+
+[tox]
+minversion = 3.24
+envlist = default
+isolated_build = True
+
+
+[testenv]
+description = Invoke pytest to run automated tests
+setenv =
+    TOXINIDIR = {toxinidir}
+passenv =
+    HOME
+    SETUPTOOLS_*
+extras =
+    testing
+commands =
+    pytest {posargs}
+
+
+# # To run `tox -e lint` you need to make sure you have a
+# # `.pre-commit-config.yaml` file. See https://pre-commit.com
+# [testenv:lint]
+# description = Perform static analysis and style checks
+# skip_install = True
+# deps = pre-commit
+# passenv =
+#     HOMEPATH
+#     PROGRAMDATA
+#     SETUPTOOLS_*
+# commands =
+#     pre-commit run --all-files {posargs:--show-diff-on-failure}
+
+
+[testenv:{build,clean}]
+description =
+    build: Build the package in isolation according to PEP517, see https://github.com/pypa/build
+    clean: Remove old distribution files and temporary build artifacts (./build and ./dist)
+# https://setuptools.pypa.io/en/stable/build_meta.html#how-to-use-it
+skip_install = True
+changedir = {toxinidir}
+deps =
+    build: build[virtualenv]
+passenv =
+    SETUPTOOLS_*
+commands =
+    clean: python -c 'import shutil; [shutil.rmtree(p, True) for p in ("build", "dist", "docs/_build")]'
+    clean: python -c 'import pathlib, shutil; [shutil.rmtree(p, True) for p in pathlib.Path("src").glob("*.egg-info")]'
+    build: python -m build {posargs}
+# By default, both `sdist` and `wheel` are built. If your sdist is too big or you don't want
+# to make it available, consider running: `tox -e build -- --wheel`
+
+
+[testenv:{docs,doctests,linkcheck}]
+description =
+    docs: Invoke sphinx-build to build the docs
+    doctests: Invoke sphinx-build to run doctests
+    linkcheck: Check for broken links in the documentation
+passenv =
+    SETUPTOOLS_*
+setenv =
+    DOCSDIR = {toxinidir}/docs
+    BUILDDIR = {toxinidir}/docs/_build
+    docs: BUILD = html
+    doctests: BUILD = doctest
+    linkcheck: BUILD = linkcheck
+deps =
+    -r {toxinidir}/docs/requirements.txt
+    # ^  requirements.txt shared with Read The Docs
+commands =
+    sphinx-build --color -b {env:BUILD} -d "{env:BUILDDIR}/doctrees" "{env:DOCSDIR}" "{env:BUILDDIR}/{env:BUILD}" {posargs}
+
+
+[testenv:publish]
+description =
+    Publish the package you have been developing to a package index server.
+    By default, it uses testpypi. If you really want to publish your package
+    to be publicly accessible in PyPI, use the `-- --repository pypi` option.
+skip_install = True
+changedir = {toxinidir}
+passenv =
+    # See: https://twine.readthedocs.io/en/latest/
+    TWINE_USERNAME
+    TWINE_PASSWORD
+    TWINE_REPOSITORY
+    TWINE_REPOSITORY_URL
+deps = twine
+commands =
+    python -m twine check dist/*
+    python -m twine upload {posargs:--repository {env:TWINE_REPOSITORY:testpypi}} dist/*