diff options
-rw-r--r-- | .coveragerc | 6 | ||||
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | .pylintrc | 575 | ||||
-rw-r--r-- | .travis.yml | 44 | ||||
-rw-r--r-- | LICENSE | 83 | ||||
-rw-r--r-- | Makefile | 95 | ||||
-rw-r--r-- | Pipfile | 9 | ||||
-rw-r--r-- | Pipfile.lock | 289 | ||||
-rw-r--r-- | README.md | 307 | ||||
-rw-r--r-- | README.rst | 132 | ||||
-rw-r--r-- | docs/Makefile | 20 | ||||
-rw-r--r-- | docs/source/conf.py | 176 | ||||
-rw-r--r-- | docs/source/configuration.rst | 725 | ||||
-rw-r--r-- | docs/source/index.rst | 23 | ||||
-rw-r--r-- | docs/source/usage.rst | 356 | ||||
-rwxr-xr-x | nncli | 56 | ||||
-rw-r--r-- | nncli/__init__.py | 4 | ||||
-rw-r--r-- | nncli/__main__.py | 6 | ||||
-rw-r--r-- | nncli/clipboard.py (renamed from nnotes_cli/clipboard.py) | 3 | ||||
-rw-r--r-- | nncli/config.py (renamed from nnotes_cli/config.py) | 28 | ||||
-rw-r--r-- | nncli/nextcloud_note.py (renamed from nnotes_cli/nextcloud_note.py) | 37 | ||||
-rw-r--r-- | nncli/nncli.py (renamed from nnotes_cli/nncli.py) | 42 | ||||
-rw-r--r-- | nncli/notes_db.py (renamed from nnotes_cli/notes_db.py) | 32 | ||||
-rw-r--r-- | nncli/temp.py (renamed from nnotes_cli/temp.py) | 4 | ||||
-rw-r--r-- | nncli/user_input.py (renamed from nnotes_cli/user_input.py) | 5 | ||||
-rw-r--r-- | nncli/utils.py (renamed from nnotes_cli/utils.py) | 31 | ||||
-rw-r--r-- | nncli/view_help.py (renamed from nnotes_cli/view_help.py) | 5 | ||||
-rw-r--r-- | nncli/view_log.py (renamed from nnotes_cli/view_log.py) | 5 | ||||
-rw-r--r-- | nncli/view_note.py (renamed from nnotes_cli/view_note.py) | 4 | ||||
-rw-r--r-- | nncli/view_titles.py (renamed from nnotes_cli/view_titles.py) | 5 | ||||
-rw-r--r-- | nnotes_cli/__init__.py | 17 | ||||
-rw-r--r-- | pyproject.toml | 24 | ||||
-rw-r--r-- | pytest.ini | 2 | ||||
-rw-r--r-- | setup.cfg | 12 | ||||
-rw-r--r-- | setup.py | 64 | ||||
-rw-r--r-- | tests/test_config.py | 30 | ||||
-rw-r--r-- | tests/test_nncli.py | 187 | ||||
-rw-r--r-- | tests/test_version.py | 35 | ||||
-rw-r--r-- | tox.ini | 29 |
39 files changed, 2687 insertions, 823 deletions
diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..579f18d --- /dev/null +++ b/.coveragerc @@ -0,0 +1,6 @@ +[run] +branch = True +omit = nncli/__main__.py + +[report] +show_missing = True @@ -2,6 +2,7 @@ build/ dist/ MANIFEST *.egg-info/ -nnotes_cli/version.py .coverage .pytest_cache/ +docs/build/ +.tox diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..b2edc99 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,575 @@ +[MASTER] + +# 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= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS .git + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use. +jobs=1 + +# Control the amount of potential inferred values when inferring a single +# object. This can help the performance when dealing with large functions or +# complex, nested conditions. +limit-inference-results=100 + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Pickle collected data for later comparisons. +persistent=no + +# Specify a configuration file. +#rcfile= + +# When enabled, pylint would attempt to guess common misconfiguration and emit +# user-friendly hints instead of false-positive error messages. +suggestion-mode=yes + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED. +confidence= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once). You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable=unsubscriptable-object, + print-statement, + parameter-unpacking, + unpacking-in-except, + old-raise-syntax, + backtick, + long-suffix, + old-ne-operator, + old-octal-literal, + import-star-module-level, + non-ascii-bytes-literal, + raw-checker-failed, + bad-inline-option, + locally-disabled, + locally-enabled, + file-ignored, + suppressed-message, + useless-suppression, + deprecated-pragma, + use-symbolic-message-instead, + apply-builtin, + basestring-builtin, + buffer-builtin, + cmp-builtin, + coerce-builtin, + execfile-builtin, + file-builtin, + long-builtin, + raw_input-builtin, + reduce-builtin, + standarderror-builtin, + unicode-builtin, + xrange-builtin, + coerce-method, + delslice-method, + getslice-method, + setslice-method, + no-absolute-import, + old-division, + dict-iter-method, + dict-view-method, + next-method-called, + metaclass-assignment, + indexing-exception, + raising-string, + reload-builtin, + oct-method, + hex-method, + nonzero-method, + cmp-method, + input-builtin, + round-builtin, + intern-builtin, + unichr-builtin, + map-builtin-not-iterating, + zip-builtin-not-iterating, + range-builtin-not-iterating, + filter-builtin-not-iterating, + using-cmp-argument, + eq-without-hash, + div-method, + idiv-method, + rdiv-method, + exception-message-attribute, + invalid-str-codec, + sys-max-int, + bad-python3-import, + deprecated-string-function, + deprecated-str-translate-call, + deprecated-itertools-function, + deprecated-types-field, + next-method-defined, + dict-items-not-iterating, + dict-keys-not-iterating, + dict-values-not-iterating, + deprecated-operator-function, + deprecated-urllib-function, + xreadlines-attribute, + deprecated-sys-function, + exception-escape, + comprehension-escape + +# 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. +enable=c-extension-no-member + + +[REPORTS] + +# 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= + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio). You can also give a reporter class, e.g. +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages. +reports=yes + +# Activate the evaluation score. +score=yes + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + +# Complete name of functions that never returns. When checking for +# inconsistent-return-statements if a never returning function is called then +# it will be considered as an explicit return statement and no message will be +# printed. +never-returning-functions=sys.exit + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# 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 + +# A regular expression matching the name of dummy variables (i.e. expected to +# not be used). +dummy-variables-rgx=_$|dummy + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore. +ignored-argument-names=mock.* + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format. +logging-modules=logging + + +[TYPECHECK] + +# 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, pytest.fixture + +# 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=REQUEST, + acl_users, + aq_parent, + assert_called_once_with, + assert_called_once, + call_count, + print, + call_args_list, + assert_any_call, + assert_not_called + +# 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 + +# Tells whether to warn about missing members when the owner of the attribute +# is inferred to be None. +ignore-none=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# 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=SQLObject, + DateTimeField, + CharField, + ForecastioDataBlock + +# 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= + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME, + XXX, + TODO + + +[BASIC] + +# Naming style matching correct argument names. +argument-naming-style=snake_case + +# Regular expression matching correct argument names. Overrides argument- +# naming-style. +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming style matching correct attribute names. +attr-naming-style=snake_case + +# Regular expression matching correct attribute names. Overrides attr-naming- +# style. +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Bad variable names which should always be refused, separated by a comma. +bad-names=foo, + bar, + baz, + toto, + tutu, + tata + +# Naming style matching correct class attribute names. +class-attribute-naming-style=any + +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style. +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming style matching correct class names. +class-naming-style=PascalCase + +# Regular expression matching correct class names. Overrides class-naming- +# style. +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming style matching correct constant names. +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names. Overrides const-naming- +# style. +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming style matching correct function names. +function-naming-style=snake_case + +# Regular expression matching correct function names. Overrides function- +# naming-style. +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Good variable names which should always be accepted, separated by a comma. +good-names=i, + j, + k, + ex, + Run, + main, + _ + +# Include a hint for the correct naming format with invalid-name. +include-naming-hint=no + +# Naming style matching correct inline iteration names. +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style. +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming style matching correct method names. +method-naming-style=snake_case + +# Regular expression matching correct method names. Overrides method-naming- +# style. +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming style matching correct module names. +module-naming-style=snake_case + +# Regular expression matching correct module names. Overrides module-naming- +# style. +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=__.*__ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +# These decorators are taken in consideration only for invalid-name. +property-classes=abc.abstractproperty + +# Naming style matching correct variable names. +variable-naming-style=snake_case + +# Regular expression matching correct variable names. Overrides variable- +# naming-style. +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )?<?https?://\S+>?$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=8 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=80 + +# Maximum number of lines in a module. +max-module-lines=1000 + +# 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 + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# 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 + + +[SPELLING] + +# Limits count of emitted suggestions for spelling mistakes. +max-spelling-suggestions=4 + +# 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 + + +[SIMILARITIES] + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + +# Minimum lines number of a similarity. +min-similarity-lines=4 + + +[DESIGN] + +# Maximum number of arguments for function / method. +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in an if statement. +max-bool-expr=5 + +# Maximum number of branch for function / method body. +max-branches=20 + +# Maximum number of locals for function / method body. +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body. +max-returns=6 + +# Maximum number of statements in function / method body. +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# 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 + + +[IMPORTS] + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# 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 + +# Deprecated modules which should not be used, separated by a comma. +deprecated-modules=regsub, + TERMIOS, + Bastion, + rexec + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled). +ext-import-graph= + +# 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 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 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception". +overgeneral-exceptions=Exception diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d2ae20f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,44 @@ +# https://travis-ci.org/djmoch/nncli +language: python + +matrix: + fast_finish: true + +.mixins: +- &xenial-mixin + dist: xenial + sudo: true + addons: + apt: + packages: + - libgnutls-dev + +env: + - PIPENV_HIDE_EMOJIS=1 PIPENV_NO_INHERIT=1 + +install: + - pip install -U pip pipenv python-coveralls + - make test-install + +jobs: + include: + - stage: test + script: make test + python: 3.4 + - stage: test + script: make test + python: 3.5 + - stage: test + script: make test + python: 3.6 + - stage: test + script: make test + <<: *xenial-mixin + python: 3.7 + # - stage: lint + # script: make lint + # python: 3.6 + - stage: coverage + script: make coverage + after_success: coveralls + python: 3.5 @@ -21,3 +21,86 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------- + +Portions of this software are adapted from sncli by Eric Davis: + +** The MIT License ** + +Copyright (c) 2014 Eric Davis (edavis@insanum.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Dude... just buy me a beer. :-) + +------------------------------------------------------------------------------- + +Portions of nextcloud_note.py are adapted from simplenote.py by Daniel +Schauenberg: + +Copyright (c) 2011 Daniel Schauenberg + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +------------------------------------------------------------------------------- + +Portions of notes_db and utils modules are adapted from the +corresponding module in nvpy by Charl P. Botha: + +Copyright (c) 2012, Charl P. Botha +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the <organization> nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL CHARL P. BOTHA BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f6c3472 --- /dev/null +++ b/Makefile @@ -0,0 +1,95 @@ +.PHONY: clean clean-test clean-pyc clean-build help lint coverage coverage-html release dist install run debug docs +.DEFAULT_GOAL := help + +define BROWSER_PYSCRIPT +import os, webbrowser, sys + +try: + from urllib import pathname2url +except: + from urllib.request import pathname2url + +webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) +endef +export BROWSER_PYSCRIPT + +define PRINT_HELP_PYSCRIPT +import re, sys + +for line in sys.stdin: + match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) + if match: + target, help = match.groups() + print("%-20s %s" % (target, help)) +endef +export PRINT_HELP_PYSCRIPT + +BROWSER := python -c "$$BROWSER_PYSCRIPT" +PIPENV := pipenv +PIPRUN := $(PIPENV) run +PIPINST := $(PIPENV) --bare install --dev + +help: + @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) + +clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts + make -C docs clean + +clean-build: ## remove build artifacts + rm -fr build/ + rm -fr dist/ + rm -fr .eggs/ + find . -name '*.egg-info' -exec rm -fr {} + + find . -name '*.egg' -exec rm -f {} + + +clean-pyc: ## remove Python file artifacts + find . -name '*.pyc' -exec rm -f {} + + find . -name '*.pyo' -exec rm -f {} + + find . -name '*~' -exec rm -f {} + + find . -name '__pycache__' -exec rm -fr {} + + $(PIPRUN) pip uninstall -y nncli + +clean-test: ## remove test and coverage artifacts + rm -f .coverage + rm -fr htmlcov/ + rm -fr .pytest_cache + rm -fr .tox + +lint: ## check style with pylint + $(PIPRUN) pylint nncli tests --disable=parse-error + +test: ## run tests quickly with the default Python + $(PIPRUN) python -m pytest + +test-all: ## run tests on every Python version with tox + $(PIPRUN) tox + +test-install: ## install dependenices from Pipfile (for tox / CI builds) + $(PIPINST) + +coverage: ## check code coverage quickly with the default Python + $(PIPRUN) python -m pytest --cov=nncli + +coverage-html: coverage ## generate an HTML report and open in browser + $(PIPRUN) coverage html + $(BROWSER) htmlcov/index.html + +release: dist ## package and upload a release + $(PIPRUN) flit publish + +dist: ## builds source and wheel package + $(PIPRUN) flit build + ls -l dist + +docs: ## builds the sphinx documentation and opens in the browser + make -C docs html + $(BROWSER) docs/build/html/index.html + +install: ## install the package to the active Python's site-packages + $(PIPRUN) flit install --deps=none + +run: ## run the package from site-packages + $(PIPRUN) python -m nncli $(cmd) + +debug: install ## debug the package from site packages + $(PIPRUN) pudb3 $$($(PIPRUN) which nncli) $(cmd) @@ -7,8 +7,6 @@ name = "pypi" appdirs = "*" requests = "*" urwid = "*" -setuptools = "*" -setuptools-scm = "*" [dev-packages] pytest = "*" @@ -17,3 +15,10 @@ pytest-mock = "*" pytest-runner = "*" pylint = "*" pudb = "*" +sphinx = "*" +flit = "*" +setuptools = "*" +mock = "*" +tox = "*" +pathlib2 = {version = "*", markers = "python_version < '3.5'"} +scandir = {version = "*", markers = "python_version < '3.5'"} diff --git a/Pipfile.lock b/Pipfile.lock index 8525be7..a1d93f9 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b4bc66838172733ffa35a5998d87982699b21d67eccdb8d913fffd8c7dcd101a" + "sha256": "3dd4d429a27a82ab0f5daa11fb974392ab9f45ac6b20647762d79a1c4ab1bd55" }, "pipfile-spec": 6, "requires": {}, @@ -51,20 +51,12 @@ "index": "pypi", "version": "==2.19.1" }, - "setuptools-scm": { - "hashes": [ - "sha256:1191f2a136b5e86f7ca8ab00a97ef7aef997131f1f6d4971be69a1ef387d8b40", - "sha256:cc6953d224a22f10e933fa2f55c95979317c55259016adcf93310ba2997febfa" - ], - "index": "pypi", - "version": "==3.1.0" - }, "urllib3": { "hashes": [ "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" ], - "markers": "python_version != '3.1.*' and python_version != '3.3.*' and python_version >= '2.6' and python_version != '3.0.*' and python_version != '3.2.*' and python_version < '4'", + "markers": "python_version != '3.1.*' and python_version != '3.3.*' and python_version < '4' and python_version != '3.0.*' and python_version != '3.2.*' and python_version >= '2.6'", "version": "==1.23" }, "urwid": { @@ -76,6 +68,13 @@ } }, "develop": { + "alabaster": { + "hashes": [ + "sha256:674bb3bab080f598371f4443c5008cbfeb1a5e622dd312395d2d82af2c54c456", + "sha256:b63b1f4dc77c074d386752ec4a8a7517600f6c0db8cd42980cae17ab7b3275d7" + ], + "version": "==0.7.11" + }, "astroid": { "hashes": [ "sha256:292fa429e69d60e4161e7612cb7cc8fa3609e2e309f80c224d93a76d5e7b58be", @@ -85,18 +84,39 @@ }, "atomicwrites": { "hashes": [ - "sha256:6b5282987b21cd79151f51caccead7a09d0a32e89c568bd9e3c4aaa7bbdf3f3a", - "sha256:e16334d50fe0f90919ef7339c24b9b62e6abaa78cd2d226f3d94eb067eb89043" + "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", + "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee" ], - "markers": "python_version != '3.2.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.3.*' and python_version != '3.0.*'", - "version": "==1.2.0" + "markers": "python_version != '3.1.*' and python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.3.*'", + "version": "==1.2.1" }, "attrs": { "hashes": [ - "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", - "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b" + "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", + "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb" + ], + "version": "==18.2.0" + }, + "babel": { + "hashes": [ + "sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669", + "sha256:8cba50f48c529ca3fa18cf81fa9403be176d374ac4d60738b839122dfaaa3d23" + ], + "version": "==2.6.0" + }, + "certifi": { + "hashes": [ + "sha256:376690d6f16d32f9d1fe8932551d80b23e9d393a8578c5633a2ed39a64861638", + "sha256:456048c7e371c089d0a77a5212fb37a2c2dce1e24146e3b7e0261736aaeaa22a" + ], + "version": "==2018.8.24" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" ], - "version": "==18.1.0" + "version": "==3.0.4" }, "coverage": { "hashes": [ @@ -132,18 +152,56 @@ "sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80" ], - "markers": "python_version < '4' and python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*' and python_version >= '2.6'", + "markers": "python_version >= '2.6' and python_version != '3.1.*' and python_version != '3.0.*' and python_version != '3.2.*' and python_version < '4'", "version": "==4.5.1" }, + "docutils": { + "hashes": [ + "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", + "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", + "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" + ], + "version": "==0.14" + }, + "flit": { + "hashes": [ + "sha256:178e6865185b1802aa3b1944f4957d2c83fc56294dc8047d2c4722131f696e61", + "sha256:da823d4acae9bda42dcc0c7ab1d9be475a8a47aae5fd6dde63841d9f430ccb2f" + ], + "index": "pypi", + "version": "==1.1" + }, + "idna": { + "hashes": [ + "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", + "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" + ], + "version": "==2.7" + }, + "imagesize": { + "hashes": [ + "sha256:3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8", + "sha256:f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5" + ], + "markers": "python_version != '3.1.*' and python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.3.*'", + "version": "==1.1.0" + }, "isort": { "hashes": [ "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" ], - "markers": "python_version >= '2.7' and python_version != '3.3.*' and python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*'", + "markers": "python_version != '3.1.*' and python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.3.*'", "version": "==4.3.4" }, + "jinja2": { + "hashes": [ + "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", + "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + ], + "version": "==2.10" + }, "lazy-object-proxy": { "hashes": [ "sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", @@ -178,6 +236,12 @@ ], "version": "==1.3.1" }, + "markupsafe": { + "hashes": [ + "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" + ], + "version": "==1.0" + }, "mccabe": { "hashes": [ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", @@ -185,6 +249,14 @@ ], "version": "==0.6.1" }, + "mock": { + "hashes": [ + "sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1", + "sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba" + ], + "index": "pypi", + "version": "==2.0.0" + }, "more-itertools": { "hashes": [ "sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", @@ -193,12 +265,35 @@ ], "version": "==4.3.0" }, + "packaging": { + "hashes": [ + "sha256:e9215d2d2535d3ae866c3d6efc77d5b24a0192cce0ff20e42896cc0664f889c0", + "sha256:f019b770dd64e585a99714f1fd5e01c7a8f11b45635aa953fd41c689a657375b" + ], + "version": "==17.1" + }, + "pathlib2": { + "hashes": [ + "sha256:8eb170f8d0d61825e09a95b38be068299ddeda82f35e96c3301a8a5e7604cb83", + "sha256:d1aa2a11ba7b8f7b21ab852b1fb5afb277e1bb99d5dfc663380b5015c0d80c5a" + ], + "index": "pypi", + "markers": "python_version < '3.5'", + "version": "==2.3.2" + }, + "pbr": { + "hashes": [ + "sha256:1b8be50d938c9bb75d0eaf7eda111eec1bf6dc88a62a6412e33bf077457e0f45", + "sha256:b486975c0cafb6beeb50ca0e17ba047647f229087bd74e37f4a7e2cac17d2caa" + ], + "version": "==4.2.0" + }, "pluggy": { "hashes": [ "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" ], - "markers": "python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.3.*' and python_version >= '2.7'", + "markers": "python_version != '3.1.*' and python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.3.*'", "version": "==0.7.1" }, "pudb": { @@ -213,7 +308,7 @@ "sha256:06a30435d058473046be836d3fc4f27167fd84c45b99704f2fb5509ef61f9af1", "sha256:50402e9d1c9005d759426988a492e0edaadb7f4e68bcddfea586bc7432d009c6" ], - "markers": "python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.3.*' and python_version != '3.1.*' and python_version >= '2.7'", + "markers": "python_version != '3.1.*' and python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.3.*'", "version": "==1.6.0" }, "pygments": { @@ -231,13 +326,20 @@ "index": "pypi", "version": "==2.1.1" }, + "pyparsing": { + "hashes": [ + "sha256:0832bcf47acd283788593e7a0f542407bd9550a55a8a8435214a1960e04bcb04", + "sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010" + ], + "version": "==2.2.0" + }, "pytest": { "hashes": [ - "sha256:2e7c330338b2732ddb992217962e3454aa7290434e75329b1a6739cea41bea6b", - "sha256:4abcd98faeea3eb95bd05aa6a7b121d5f89d72e4d36ddb0dcbbfd1ec9f3651d1" + "sha256:2d7c49e931316cc7d1638a3e5f54f5d7b4e5225972b3c9838f3584788d27f349", + "sha256:ad0c7db7b5d4081631e0155f5c61b80ad76ce148551aaafe3a718d65a7508b18" ], "index": "pypi", - "version": "==3.7.3" + "version": "==3.7.4" }, "pytest-cov": { "hashes": [ @@ -263,6 +365,52 @@ "index": "pypi", "version": "==4.2" }, + "pytoml": { + "hashes": [ + "sha256:dae3c4e31d09eb06a6076d671f2281ee5d2c43cbeae16599c3af20881bb818ac" + ], + "version": "==0.1.18" + }, + "pytz": { + "hashes": [ + "sha256:a061aa0a9e06881eb8b3b2b43f05b9439d6583c206d0a6c340ff72a7b6669053", + "sha256:ffb9ef1de172603304d9d2819af6f5ece76f2e85ec10692a524dd876e72bf277" + ], + "version": "==2018.5" + }, + "requests": { + "hashes": [ + "sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1", + "sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a" + ], + "index": "pypi", + "version": "==2.19.1" + }, + "requests-download": { + "hashes": [ + "sha256:92d895a6ca51ea51aa42bab864bddaee31b5601c7e7e1ade4c27b0eb6695d846", + "sha256:994d9d332befae6616f562769bab163f08d6404dc7e28fb7bfed4a0a43a754ad" + ], + "version": "==0.1.2" + }, + "scandir": { + "hashes": [ + "sha256:04b8adb105f2ed313a7c2ef0f1cf7aff4871aa7a1883fa4d8c44b5551ab052d6", + "sha256:1444134990356c81d12f30e4b311379acfbbcd03e0bab591de2696a3b126d58e", + "sha256:1b5c314e39f596875e5a95dd81af03730b338c277c54a454226978d5ba95dbb6", + "sha256:346619f72eb0ddc4cf355ceffd225fa52506c92a2ff05318cfabd02a144e7c4e", + "sha256:44975e209c4827fc18a3486f257154d34ec6eaec0f90fef0cca1caa482db7064", + "sha256:61859fd7e40b8c71e609c202db5b0c1dbec0d5c7f1449dec2245575bdc866792", + "sha256:a5e232a0bf188362fa00123cc0bb842d363a292de7126126df5527b6a369586a", + "sha256:c14701409f311e7a9b7ec8e337f0815baf7ac95776cc78b419a1e6d49889a383", + "sha256:c7708f29d843fc2764310732e41f0ce27feadde453261859ec0fca7865dfc41b", + "sha256:c9009c527929f6e25604aec39b0a43c3f831d2947d89d6caaab22f057b7055c8", + "sha256:f5c71e29b4e2af7ccdc03a020c626ede51da471173b4a6ad1e904f2b2e04b4bd" + ], + "index": "pypi", + "markers": "python_version < '3.5'", + "version": "==1.9.0" + }, "six": { "hashes": [ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", @@ -270,6 +418,83 @@ ], "version": "==1.11.0" }, + "snowballstemmer": { + "hashes": [ + "sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128", + "sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89" + ], + "version": "==1.2.1" + }, + "sphinx": { + "hashes": [ + "sha256:a07050845cc9a2f4026a6035cc8ed795a5ce7be6528bbc82032385c10807dfe7", + "sha256:d719de667218d763e8fd144b7fcfeefd8d434a6201f76bf9f0f0c1fa6f47fcdb" + ], + "index": "pypi", + "version": "==1.7.8" + }, + "sphinxcontrib-websupport": { + "hashes": [ + "sha256:68ca7ff70785cbe1e7bccc71a48b5b6d965d79ca50629606c7861a21b206d9dd", + "sha256:9de47f375baf1ea07cdb3436ff39d7a9c76042c10a769c52353ec46e4e8fc3b9" + ], + "markers": "python_version != '3.1.*' and python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.3.*'", + "version": "==1.1.0" + }, + "tox": { + "hashes": [ + "sha256:37cf240781b662fb790710c6998527e65ca6851eace84d1595ee71f7af4e85f7", + "sha256:eb61aa5bcce65325538686f09848f04ef679b5cd9b83cc491272099b28739600" + ], + "index": "pypi", + "version": "==3.2.1" + }, + "typed-ast": { + "hashes": [ + "sha256:0948004fa228ae071054f5208840a1e88747a357ec1101c17217bfe99b299d58", + "sha256:10703d3cec8dcd9eef5a630a04056bbc898abc19bac5691612acba7d1325b66d", + "sha256:1f6c4bd0bdc0f14246fd41262df7dfc018d65bb05f6e16390b7ea26ca454a291", + "sha256:25d8feefe27eb0303b73545416b13d108c6067b846b543738a25ff304824ed9a", + "sha256:29464a177d56e4e055b5f7b629935af7f49c196be47528cc94e0a7bf83fbc2b9", + "sha256:2e214b72168ea0275efd6c884b114ab42e316de3ffa125b267e732ed2abda892", + "sha256:3e0d5e48e3a23e9a4d1a9f698e32a542a4a288c871d33ed8df1b092a40f3a0f9", + "sha256:519425deca5c2b2bdac49f77b2c5625781abbaf9a809d727d3a5596b30bb4ded", + "sha256:57fe287f0cdd9ceaf69e7b71a2e94a24b5d268b35df251a88fef5cc241bf73aa", + "sha256:668d0cec391d9aed1c6a388b0d5b97cd22e6073eaa5fbaa6d2946603b4871efe", + "sha256:68ba70684990f59497680ff90d18e756a47bf4863c604098f10de9716b2c0bdd", + "sha256:6de012d2b166fe7a4cdf505eee3aaa12192f7ba365beeefaca4ec10e31241a85", + "sha256:79b91ebe5a28d349b6d0d323023350133e927b4de5b651a8aa2db69c761420c6", + "sha256:8550177fa5d4c1f09b5e5f524411c44633c80ec69b24e0e98906dd761941ca46", + "sha256:898f818399cafcdb93cbbe15fc83a33d05f18e29fb498ddc09b0214cdfc7cd51", + "sha256:94b091dc0f19291adcb279a108f5d38de2430411068b219f41b343c03b28fb1f", + "sha256:a26863198902cda15ab4503991e8cf1ca874219e0118cbf07c126bce7c4db129", + "sha256:a8034021801bc0440f2e027c354b4eafd95891b573e12ff0418dec385c76785c", + "sha256:bc978ac17468fe868ee589c795d06777f75496b1ed576d308002c8a5756fb9ea", + "sha256:c05b41bc1deade9f90ddc5d988fe506208019ebba9f2578c622516fd201f5863", + "sha256:c9b060bd1e5a26ab6e8267fd46fc9e02b54eb15fffb16d112d4c7b1c12987559", + "sha256:edb04bdd45bfd76c8292c4d9654568efaedf76fe78eb246dde69bdb13b2dad87", + "sha256:f19f2a4f547505fe9072e15f6f4ae714af51b5a681a97f187971f50c283193b6" + ], + "markers": "python_version < '3.7' and implementation_name == 'cpython'", + "version": "==1.1.0" + }, + "typing": { + "hashes": [ + "sha256:4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d", + "sha256:57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4", + "sha256:a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a" + ], + "markers": "python_version < '3.5'", + "version": "==3.6.6" + }, + "urllib3": { + "hashes": [ + "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", + "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" + ], + "markers": "python_version != '3.1.*' and python_version != '3.3.*' and python_version < '4' and python_version != '3.0.*' and python_version != '3.2.*' and python_version >= '2.6'", + "version": "==1.23" + }, "urwid": { "hashes": [ "sha256:644d3e3900867161a2fc9287a9762753d66bd194754679adb26aede559bcccbc" @@ -277,11 +502,27 @@ "index": "pypi", "version": "==2.0.1" }, + "virtualenv": { + "hashes": [ + "sha256:2ce32cd126117ce2c539f0134eb89de91a8413a29baac49cbab3eb50e2026669", + "sha256:ca07b4c0b54e14a91af9f34d0919790b016923d157afda5efdde55c96718f752" + ], + "markers": "python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.1.*'", + "version": "==16.0.0" + }, "wrapt": { "hashes": [ "sha256:d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6" ], "version": "==1.10.11" + }, + "zipfile36": { + "hashes": [ + "sha256:a78a8dddf4fa114f7fe73df76ffcce7538e23433b7a6a96c1c904023f122aead", + "sha256:f7e48adf627f75cd74cdb50e7d850623b465f4cf5de913809196e8f3aa57dc4b" + ], + "markers": "python_version in '3.3 3.4 3.5'", + "version": "==0.1.3" } } } diff --git a/README.md b/README.md deleted file mode 100644 index 0852303..0000000 --- a/README.md +++ /dev/null @@ -1,307 +0,0 @@ -nncli -===== - - -[](https://pypi.org/project/nncli/) - -NextCloud Notes Command Line Interface - -nncli is a Python application that gives you access to your NextCloud -Notes account via the command line. It's a "hard" fork of -[sncli](https://github.com/insanum/sncli). You can access your notes via -a customizable console GUI that implements vi-like keybinds or via a -simple command line interface that you can script. - -Notes can be viewed/created/edited in *both an* **online** *and* -**offline** *mode*. All changes are saved to a local cache on disk and -automatically sync'ed when nncli is brought online. - -**Pull requests are welcome!** - -Check your OS distribution for installation packages. - -### Requirements - -* [Python 3](http://python.org) -* [Urwid](http://urwid.org) Python 3 module -* [Requests](https://requests.readthedocs.org/en/master/) Python 3 - module -* A love for the command line! - -### Installation - -* Via pip (latest release): - - `pip3 install nncli` -* Manually: - - Clone this repository to your hard disk: `git clone - https://github.com/djmoch/nncli.git` - - Install _nncli_: `python3 setup.py install` -* Development: - - Clone the repo - - Install Pipenv: `pip install pipenv` - - Stand up development environment: `pipenv install --dev` - -### Features - -* Console GUI - - full two-way sync with NextCloud Notes performed dynamically in the - background - - all actions logged and easily reviewed - - list note titles (configurable format w/ title, date, flags, category, - keys, etc) - - sort notes by date, alpha by title, category, favorite on top - - search for notes using a Google style search pattern or Regular - Expression - - view note contents and meta data - - pipe note contents to external command - - create and edit notes (using your editor) - - edit note category - - delete notes - - favorite/unfavorite notes - - vi-like keybinds (fully configurable) - - Colors! (fully configurable) -* Command Line (scripting) - - force a full two-way sync with NextCloud Notes - - all actions logged and easily reviewed - - list note titles and keys - - search for notes using a Google style search pattern or Regular - Expression - - dump note contents - - create a new note (via stdin or editor) - - import a note with raw json data (stdin or editor) - - edit a note (via editor) - - delete a note - - favorite/unfavorite a note - - view and edit note category - -### HowTo - -``` -Usage: - nncli [OPTIONS] [COMMAND] [COMMAND_ARGS] - - OPTIONS: - -h, --help - usage help - -v, --verbose - verbose output - -n, --nosync - don't perform a server sync - -r, --regex - search string is a regular expression - -k <key>, --key=<key> - note key - -t <title>, --title=<title> - title of note for create (cli mode) - -c <file>, --config=<file> - config file to read from - --version - version information - - COMMANDS: - <none> - console gui mode when no command specified - sync - perform a full sync with the server - list [search_string] - list notes (refined with search string) - export [search_string] - export notes in JSON (refined with search string) - dump [search_string] - dump notes (refined with search string) - create [-] - create a note ('-' content from stdin) - import [-] - import a note in JSON format ('-' JSON from stdin) - export - export a note in JSON format (specified by <key>) - dump - dump a note (specified by <key>) - edit - edit a note (specified by <key>) - delete - delete a note (specified by <key>) - < favorite | unfavorite > - favorite/unfavorite a note (specified by <key>) - cat get - retrieve the category from a note (specified by <key>) - cat set <category> - set the category for a note (specified by <key>) - cat rm - remove category from a note (specified by <key>) -``` - -#### Configuration - -The current NextCloud Notes API does not support oauth authentication so -your NextCloud Notes account password must be stored someplace -accessible to nncli. Use of the `cfg_nn_password_eval` option is -recommended (see below). - -nncli pulls in configuration from the `config` file located in the -standard location for your platform. At the very least, the following -example `config` will get you going (using your account information): - -``` -[nncli] -cfg_nn_username = lebowski@thedude.com -cfg_nn_password = nihilist -cfg_nn_host = nextcloud.thedude.com -``` - -Start nncli with no arguments which starts the console GUI mode. nncli -will begin to sync your existing notes and you'll see log messages at -the bottom of the console. You can view these log messages at any time -by pressing the `l` key. - -View the help by pressing `h`. Here you'll see all the keybinds and -configuration items. The middle column shows the config name that can be -used in your `config` to override the default setting. - -See example configuration file below for more notes. - -``` -[nncli] -cfg_nn_username = lebowski@thedude.com -cfg_nn_password = nihilist -cfg_nn_host = nextcloud.thedude.com - -# as an alternate to cfg_nn_password you could use the following config item -# any shell command can be used; its stdout is used for the password -# trailing newlines are stripped for ease of use -# note: if both password config are given, cfg_nn_password will be used -cfg_nn_password_eval = gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.nncli-pass.gpg - -# see http://urwid.org/manual/userinput.html for examples of more key -# combinations -kb_edit_note = space -kb_page_down = ctrl f - -# note that values must not be quoted -clr_note_focus_bg = light blue - -# if this editor config value is not provided, the $EDITOR env var will be -# used instead -# warning: if neither $EDITOR or cfg_editor is set, it will be impossible to -# edit notes -cfg_editor = nvim - -# alternatively, {fname} and/or {line} are substituted with the filename and -# current line number in nncli's pager. -# If {fname} isn't supplied, the filename is simply appended. -# examples: -cfg_editor = nvim {fname} +{line} -cfg_editor = nano +{line} - -# this is also supported for the pager: -cfg_pager = less -c +{line} -N {fname} -``` - -#### Note Title Format - -The format of each line in the note list is driven by the -`cfg_format_note_title` config item. Various formatting tags are -supported for dynamically building the title string. Each of these -formatting tags supports a width specifier (decimal) and a left -justification (-) like that supported by printf: - -``` -%F - flags (fixed 5 char width) - X - needs sync - * - favorited -%T - category -%D - date -%N - title -``` - -The default note title format pushes the note category to the far right of -the terminal and left justifies the note title after the date and flags: - -``` cfg_format_note_title = '[%D] %F %-N %T' ``` - -Note that the `%D` date format is further defined by the strftime format -specified in `cfg_format_strftime`. - -#### Colors - -nncli utilizes the Python [Uwrid](http://urwid.org) module to implement -the console user interface. - -At this time, nncli does not yet support 256-color terminals and is -limited to just 16-colors. Color names that can be specified in the -`config` file are listed -[here](http://urwid.org/manual/displayattributes.html#standard-foreground-colors). - -### Searching - -nncli supports two styles of search strings. First is a Google style -search string and second is a Regular Expression. - -A Google style search string is a group of tokens (separated by spaces) -with an implied *AND* between each token. This style search is case -insensitive. For example: - -`/category:category1 category:category2 word1 "word2 word3" category:category3` - -Regular expression searching also supports the use of flags (currently -only case-insensitive) by adding a final forward slash followed by the -flags. The following example will do a case-insensitive search for -`something`: - -`(regex) /something/i` - -### Creating from command line - -``` -# create a new note and open in editor -nncli create - -# create a new note with contents of stdin -echo 'hi' | nncli create - -``` - -### Importing - -nncli can import notes from raw json data (via stdin or editor). For -example: - -`echo '{"category":"testing","content":"New note!"}' | nncli import - ` - -Allowed fields are `content`, `category`, `favorite`, and `modified` - -### Exporting - -nncli can export notes as json data to stdout. Example: - -``` -# export a single note by id -nncli -k somekeyid export - -# export all notes -nncli export - -# export notes matching search string -nncli [-r] export some search keywords or regex -``` - -Note that nncli still stores all the notes data in the directory -specified by `cfg_db_path`, so for easy backups, it may be -easier/quicker to simply backup this entire directory. - -### Category - -Note category can be modified directly from the command line. Example: - -``` -# Retrieve note category (e.g. "category1") -nncli -k somekeyid cat get -# Returns "category1" - -# Add a category to a note, overwriting any existing one -nncli -k somekeyid cat set "category3" -# Now tagged as "category3" - -# Remove a category from a note -nncli -k somekeyid cat rm -# Note now has no category -``` -### Tricks - -Advanced text editors usually tailor their behavior based on the file -type being edited. For such editors, notes opened through nncli should -be treated as Markdown by default. However, you can change this -on a per-note basis through the use of modelines. In Vim, for instance, -a modeline is a comment line conforming to the pattern below. - -``` ; vim:ft=votl ``` - -Now when I edit this note Vim will automatically load the votl plugin. -Lots of possibilities here... - -### Thanks - -nncli is a fork of [sncli](https://github.com/insanum/sncli) by -[insanum](https://github.com/insanum). This application further pulls in -and uses modified versions of the -[simplenote.py](https://github.com/mrtazz/simplenote.py) module by -[mrtazz](https://github.com/mrtazz) and the -[notes_db.py](https://github.com/cpbotha/nvpy/blob/master/nvpy/notes_db.py) -module from [nvpy](https://github.com/cpbotha/nvpy) by -[cpbotha](https://github.com/cpbotha). diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..3638ea0 --- /dev/null +++ b/README.rst @@ -0,0 +1,132 @@ +.. image:: https://img.shields.io/pypi/l/nncli.svg + :alt: PyPI - License +.. image:: https://img.shields.io/travis/com/djmoch/nncli.svg + :alt: Travis (.com) + :target: https://travis-ci.com/djmoch/nncli +.. image:: https://img.shields.io/pypi/v/nncli.svg + :alt: PyPI + :target: https://pypi.org/project/nncli +.. image:: https://img.shields.io/coveralls/github/djmoch/nncli.svg + :alt: Coveralls github + :target: https://coveralls.io/github/djmoch/nncli +.. image:: https://img.shields.io/readthedocs/nncli.svg + :alt: Read the Docs + :target: https://nncli.readthedocs.io + +nncli is a Python application that gives you access to your NextCloud +Notes account via the command line. It's a "hard" fork of +sncli_. You can access your notes via +a customizable console GUI that implements vi-like keybinds or via a +simple command line interface that you can script. + +Notes can be viewed/created/edited in *both an* **online** *and* +**offline** *mode*. All changes are saved to a local cache on disk and +automatically sync'ed when nncli is brought online. + +More detailed documentation can be found in the docs. + +Requirements +~~~~~~~~~~~~ + +- `Python 3`_ + +- Urwid_ Python 3 module + +- Requests_ Python 3 module + +- A love for the command line! + +Installation +~~~~~~~~~~~~ + +- Via pip (latest release): + + - ``pip3 install nncli`` + +- Manually: + + - Clone this repository to your hard disk: ``git clone + https://github.com/djmoch/nncli.git`` + + - Install nncli: ``python3 setup.py install`` + +- Development: + + - Clone the repo + + - Install Pipenv: ``pip install pipenv`` + + - Stand up development environment: ``pipenv install --dev`` + +Features +~~~~~~~~ + +- Console GUI + + - full two-way sync with NextCloud Notes performed dynamically in the + background + + - all actions logged and easily reviewed + + - list note titles (configurable format w/ title, date, flags, category, + keys, etc) + + - sort notes by date, alpha by title, category, favorite on top + + - search for notes using a Google style search pattern or Regular + Expression + + - view note contents and meta data + + - pipe note contents to external command + + - create and edit notes (using your editor) + + - edit note category + + - delete notes + + - favorite/unfavorite notes + + - vi-like keybinds (fully configurable) + + - Colors! (fully configurable) + +- Command Line (scripting) + + - force a full two-way sync with NextCloud Notes + + - all actions logged and easily reviewed + + - list note titles and keys + + - search for notes using a Google style search pattern or Regular + Expression + + - dump note contents + + - create a new note (via stdin or editor) + + - import a note with raw json data (stdin or editor) + + - edit a note (via editor) + + - delete a note + + - favorite/unfavorite a note + + - view and edit note category + +Acknowledgements +~~~~~~~~~~~~~~~~ + +nncli is a fork of sncli_ by Eric Davis. This application further pulls in +and uses modified versions of the simplenote.py_ module by Daniel Schauenberg and +the notes_db.py module from nvpy_ by Charl P. Botha. + +.. _sncli: https://github.com/insanum/sncli +.. _Python 3: http://python.org +.. _Urwid: http://urwid.org +.. _Requests: https://requests.readthedocs.org/en/master +.. _simplenote.py: https://github.com/mrtazz/simplenote.py +.. _nvpy: https://github.com/cpbotha/nvpy diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..855249f --- /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 = pipenv run sphinx-build +SPHINXPROJ = nncli +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) diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..baedf52 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,176 @@ +# -*- 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/master/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. +# +import os +import sys +sys.path.insert(0, os.path.abspath(os.path.sep.join(['..', '..']))) +import nncli + +# -- Project information ----------------------------------------------------- + +project = 'nncli' +copyright = '2018, Daniel Moch' +author = 'Daniel Moch' + +# The short X.Y version +version = nncli.__version__ +# The full version, including alpha/beta/rc tags +release = nncli.__version__ + + +# -- 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.todo', + 'sphinx.ext.intersphinx', +] + +# 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 = None + +# 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 = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# -- 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 = 'default' + +# 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 = {} + +# 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 = 'nnclidoc' + + +# -- 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, 'nncli.tex', 'nncli Documentation', + 'Daniel Moch', '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, 'nncli', 'nncli 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, 'nncli', 'nncli Documentation', + author, 'nncli', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Extension configuration ------------------------------------------------- + +# -- Options for intersphinx extension --------------------------------------- +intersphinx_mapping = {'python': ('https://docs.python.org/3', None), + 'urwid': ('http://urwid.org', None)} + +# -- Options for todo extension ---------------------------------------------- + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + +# -- Extension interface ----------------------------------------------------- +def setup(app): + app.add_object_type('confval', 'confval', + objname='configuration value', + indextemplate='pair: %s; configuration value') diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst new file mode 100644 index 0000000..fd6fa80 --- /dev/null +++ b/docs/source/configuration.rst @@ -0,0 +1,725 @@ +.. _configuration: + +Configuration +============= + +The current NextCloud Notes API does not support oauth authentication so +your NextCloud Notes account password must be stored someplace +accessible to nncli. Use of the ``cfg_nn_password_eval`` option is +recommended (see :ref:`config-file`). + +.. index:: single: configuration file + +.. _config-file: + +Configuration File +------------------ + +nncli pulls in configuration from the ``config`` file located in the +standard location for your platform. + +- Windows: ``%USERPROFILE%\AppData\Local\djmoch\nncli`` + +- macOS: ``~/Library/Preferences/nncli`` + +- \*nix: ``$XDG_CONFIG_HOME/nncli/config`` or + ``$HOME/.config/nncli/config`` + +The following directives are accepted within the ``config`` file: + +.. index:: pair: configuration file; general options + +General Options +~~~~~~~~~~~~~~~ + +.. confval:: cfg_nn_host + + Sets the URL of the NextCloud instance to connect to. + + Required. + +.. confval:: cfg_nn_username + + The user name to log in as. + + Required. + +.. confval:: cfg_nn_password + + The password to use for log in. + + Optional. Overrides :confval:`cfg_nn_password_eval` if both are + specified. + +.. confval:: cfg_nn_password_eval + + A command to run to retrieve the password. The command should return + the password on ``stdout``. + + Optional. Required if :confval:`cfg_nn_password` is not specified. + +.. confval:: cfg_db_path + + Specifies the path of the local notes cache. + + Optional. Default value: + + - Windows: ``%USERPROFILE%\AppData\Local\djmoch\nncli\Cache`` + + - macOS: ``~/Library/Caches/nncli`` + + - \*nix: ``~/.cache/nncli`` + +.. confval:: cfg_search_categories + + Set to ``yes`` to include categories in searches. Otherwise set to + ``no``. + + Optional. Default value: ``yes`` + +.. confval:: cfg_sort_mode + + Sets how notes are sorted in the console GUI. Set to ``date`` + to have them sorted by date (newest on top). Set to ``alpha`` to have + them sorted alphabetically. + + Optional. Default value: ``date`` + +.. confval:: cfg_favorite_ontop + + Determines whether notes marked as favorite are sorted on top. + + Optional. Default value: ``yes`` + +.. confval:: cfg_tabstop + + Sets the width of a tabstop character. + + Optional. Default value: ``4`` + +.. confval:: cfg_format_strftime + + Sets the format of the note timestamp (``%D``) in the note title. The + format values are the specified in :py:func:`time.strftime`. + + Optional. Default value: ``%Y/%m/%d`` + +.. confval:: cfg_format_note_title + + Sets the format of each line in the console GUI note list. Various + formatting tags are supported for dynamically building the title + string. Each of these formatting tags supports a width specifier + (decimal) and a left justification (``-``) like that supported by + printf: + + .. code-block:: none + + %F - flags (fixed 2 char width) + X - needs sync + * - favorited + %T - category + %D - date + %N - title + + The default note title format pushes the note category to the far + right of the terminal and left justifies the note title after the + date and flags. + + Optional. Default value: ``[%D] %F %-N %T`` + + Note that the ``%D`` date format is further defined by the strftime + format specified in :confval:`cfg_format_strftime`. + +.. confval:: cfg_status_bar + + Sets whether or not the status bar is visible at the top of the + console GUI. + + Optional. Default value: ``yes`` + +.. confval:: cfg_editor + + Sets the command to run when opening a note for editing. The special + values ``{fname}`` and ``{line}`` can be used to specify respectively + the file name and line number to pass to the command. + + Optional. Default value: ``$EDITOR`` if defined in the user's + environment, else ``vim {fname} +{line}``. + +.. confval:: cfg_pager + + Sets the command to run when opening a note for viewing in an + external pager. + + Optional. Default value: ``$PAGER`` if defined in the user's + environment, else ``less -c``. + +.. confval:: cfg_diff + + .. todo:: Remove ``cfg_diff`` + +.. confval:: cfg_max_logs + + Sets the number of log events to display together in the consule GUI + footer. + + Optional. Default value: ``5`` + +.. confval:: cfg_log_timeout + + Sets the rate to poll for log events. Unit is seconds. + + Optional. Default value: ``5`` + +.. confval:: cfg_log_reversed + + Sets whether or not the log is displayed in reverse-chronological + order. + + Optional. Default value: ``yes`` + +.. confval:: cfg_tempdir + + Sets a directory path to store temporary files in. ``nncli`` uses + :func:`tempfile.mkstemp` under the hood, and the most nuanced + description of how this value is used can be found in the discussion + of the ``dir`` keyword argument there. Basically you should not + specify this if you want to use the platform-standard temporary + folder. + + Optional. Default value: *[blank]* + +.. index:: pair: configuration file; keybindings + +Keybindings +~~~~~~~~~~~ + +Keybindings specify the behavior of the console GUI, and are never +required in the ``config`` file. However, they all have default values, +as outlined below. More information on specifying keybindings can be +found in the :ref:`Urwid documentation <urwid:keyboard-input>`. + +.. confval:: kb_help + + Press to enter the help screen. + + Default value: ``h`` + +.. confval:: kb_quit + + Press to exit the console GUI. + + Default value: ``q`` + +.. confval:: kb_sync + + Press to force a full, bi-directional sync with the server. + + Default value: ``S`` + +.. confval:: kb_down + + Press to move down one row. + + Default value: ``j`` + +.. confval:: kb_up + + Press to move one row up. + + Default value: ``k`` + +.. confval:: kb_page_down + + Press to move one page down. + + Default value: ``space`` + +.. confval:: kb_page_up + + Press to move one page up. + + Default value: ``b`` + +.. confval:: kb_half_page_down + + Press to move one half-page down. + + Default value: ``ctrl d`` + +.. confval:: kb_half_page_up + + Press to move one half-page up. + + Default value: ``ctrl u`` + +.. confval:: kb_bottom + + Press to move to the last line. + + Default value: ``G`` + +.. confval:: kb_top + + Press to move to the first line. + + Default value: ``g`` + +.. confval:: kb_status + + Press to toggle the visibility of the status bar. + + Default value: ``s`` + +.. confval:: kb_create_note + + Press to create a new note and open in the configured editor (see + :confval:`cfg_editor`). + + Default value: ``C`` + +.. confval:: kb_edit_note + + Press to edit the highlighted note in the configured editor (see + :confval:`cfg_editor`). + + Default value: ``e`` + +.. confval:: kb_view_note + + Press to view the highlighted note in read-only mode. + + Default value: ``enter`` + +.. confval:: kb_view_note_ext + + Press to view the highlighted note in the configured pager (see + :confval:`cfg_pager`). + + Default value: ``meta enter`` + +.. confval:: kb_view_note_json + + Press to view the raw JSON contents of the highlighted note in + read-only mode. + + Default value: ``O`` + +.. confval:: kb_pipe_note + + Press to send the contents of the highlighted note to ``stdin`` of + another program. A small command window opens at the bottom of the + screen to enter the desired program. + + Default value: ``|`` + +.. confval:: kb_view_next_note + + Press to view the contents of the next note in read-only mode. + + Default value: ``J`` + +.. confval:: kb_view_prev_note + + Press to view the contents of the previous note in read-only mode. + + Default value: ``K`` + +.. confval:: kb_view_log + + Press to view the log. + + Default value: ``l`` + +.. confval:: kb_tabstop2 + + Press to set the tabstop for the internal pager to a width of two + characters. + + Default value: ``2`` + +.. confval:: kb_tabstop4 + + Press to set the tabstop for the internal pager to a width of four + characters. + + Default value: ``4`` + +.. confval:: kb_tabstop8 + + Press to set the tabstop for the internal pager to a width of eight + characters. + + Default value: ``8`` + +.. confval:: kb_search_gstyle + + Press to initiate a search of your notes against a Google-style + search term. A command window will open at the bottom of the screen + to enter your search term. + + Default value: ``/`` + +.. confval:: kb_search_regex + + Press to initiate a search of your notes against a regular + expression. A command window will open at the bottom of the screen to + enter your search term. + + Default value: ``meta /`` + +.. confval:: kb_search_prev_gstyle + + Press to initiate a reverse search of your notes against a + Google-style search term. A command window will open at the bottom of + the screen to enter your search term. + + Default value: ``?`` + +.. confval:: kb_search_prev_regex + + Press to initiate a reverse search of your notes against a regular + expression. A command window will open at the bottom of the screen + to enter your search term. + + Default value: ``meta ?`` + +.. confval:: kb_search_next + + Press after a search has been initiated to move to the next match. + + Default value: ``n`` + +.. confval:: kb_search_prev + + Press after a search has been initiated to move to the previous + match. + + Default value: ``N`` + +.. confval:: kb_clear_search + + Press to clear the current search. + + Default value: ``A`` + +.. confval:: kb_sort_date + + Press to display notes sorted by date. + + Default value: ``d`` + +.. confval:: kb_sort_alpha + + Press to display notes sorted alphabetically. + + Default value: ``a`` + +.. confval:: kb_sort_categories + + Press to display notes sorted by category. + + Default value: ``ctrl t`` + +.. confval:: kb_note_delete + + Press to delete a note. The note will be deleted locally and + reflected on the server after the next full sync (see + :confval:`kb_sync`). + + Default value: ``D`` + +.. confval:: kb_note_favorite + + Press to toggle the ``favorite`` flag for a note. + + Default value: ``p`` + +.. confval:: kb_note_category + + Press to set/edit the note category. A command window will appear at + the bottom of the screen containing the current category (if it has + one). Set to an empty string to clear the category. + + Default value: ``t`` + +.. confval:: kb_copy_note_text + + Press to copy the note text to the system clipboard. + + Default value: ``y`` + +.. index:: pair: configuration file; colors + +Colors +~~~~~~ + +nncli utilizes the Python Urwid_ module to implement the console user +interface. + +At this time, nncli does not yet support 256-color terminals and is +limited to just 16-colors. Color names that can be specified in the +``config`` file are listed :ref:`here <urwid:16-standard-foreground>`. + +The following pairs of configuration values represent the foreground and +background colors for different elements of the console GUI. In each +case the configuration value corresponding to the foreground color ends +in ``_fg``, and the configuration value corresponding to the +background color ends in ``_bg``. The default color values are listed in +foreground/background format. + +.. _Urwid: http://urwid.org + +.. confval:: clr_default_fg + +.. confval:: clr_default_bg + + The default foreground/background colors. + + Default values: ``default/default`` + +.. confval:: clr_status_bar_fg + +.. confval:: clr_status_bar_bg + + The foreground/background colors for the status bar. + + Default values: ``dark gray/light gray`` + +.. confval:: clr_log_fg + +.. confval:: clr_log_bg + + The foreground/background colors for the log. + + Default values: ``dark gray/light gray`` + +.. confval:: clr_user_input_bar_fg + +.. confval:: clr_user_input_bar_bg + + The foreground/background colors for the input bar. + + Default values: ``white/light red`` + +.. confval:: clr_note_focus_fg + +.. confval:: clr_note_focus_bg + + The foreground/background colors for the selected note. + + Default values: ``white/light red`` + +.. confval:: clr_note_title_day_fg + +.. confval:: clr_note_title_day_bg + + The foreground/background colors for notes edited within the past 24 + hours. + + Default values: ``light red/default`` + +.. confval:: clr_note_title_week_fg + +.. confval:: clr_note_title_week_bg + + The foreground/background colors for notes edited within the past + week, + + Default values: ``light green/default`` + +.. confval:: clr_note_title_month_fg + +.. confval:: clr_note_title_month_bg + + The foreground/background colors for notes edited within the past + month. + + Default values: ``brown/default`` + +.. confval:: clr_note_title_year_fg + +.. confval:: clr_note_title_year_bg + + The foreground/background colors for notes edited within the past + year. + + Default values: ``light blue/default`` + +.. confval:: clr_note_title_ancient_fg + +.. confval:: clr_note_title_ancient_bg + + The foreground/background colors for notes last edited more than one + year ago. + + Default values: ``light blue/default`` + +.. confval:: clr_note_date_fg + +.. confval:: clr_note_date_bg + + The foreground/background colors for the note date (i.e. the ``%D`` + portion of :confval:`cfg_format_note_title`). + + Default values: ``dark blue/default`` + +.. confval:: clr_note_flags_fg + +.. confval:: clr_note_flags_bg + + The foreground/background colors for the note flags (i.e., the ``%F`` + portion of :confval:`cfg_format_note_title`). + + Default values: ``dark magenta/default`` + +.. confval:: clr_note_category_fg + +.. confval:: clr_note_category_bg + + The foreground/background colors for the note category (i.e., the + ``%T`` portion of :confval:`cfg_format_note_title`). + + Default values: ``dark red/default`` + +.. confval:: clr_note_content_fg + +.. confval:: clr_note_content_bg + + The foreground/background colors for the note content as displayed + in the internal pager. + + Default values: ``default/default`` + +.. confval:: clr_note_content_focus_fg + +.. confval:: clr_note_content_focus_bg + + The foreground/background colors for focused content within the + internal pager. + + Default values: ``white/light red`` + +.. confval:: clr_note_content_old_fg + +.. confval:: clr_note_content_old_bg + + The foreground/background colors for old note content as displayed + within the internal pager. + + Default values: ``yellow/dark gray`` + +.. confval:: clr_note_content_old_focus_fg + +.. confval:: clr_note_content_old_focus_bg + + The foreground/background colors for old note focused content as + displayed within the internal pager. + + Default values: ``white/light red`` + +.. confval:: clr_help_focus_fg + +.. confval:: clr_help_focus_bg + + The foreground/background colors for focused content in the help + screen. + + Default values: ``white/light red`` + +.. confval:: clr_help_header_fg + +.. confval:: clr_help_header_bg + + The foreground/background colors for header content in the help + screen. + + Default values: ``dark blue/default`` + +.. confval:: clr_help_config_fg + +.. confval:: clr_help_config_bg + + The foreground/background colors for configuration option name (e.g., + ``clr_help_focus_bg``) in the help screen. + + Default values: ``dark green/default`` + +.. confval:: clr_help_value_fg + +.. confval:: clr_help_value_bg + + The foreground/background colors for the value of a configuration + option as set in ``config``. + + Default values: ``dark red/default`` + +.. confval:: clr_help_descr_fg + +.. confval:: clr_help_descr_bg + + The foreground/background colors for the configuration options + description in the help screen. + + Default values: ``default/default`` + +Examples +-------- + +At the very least, the following example ``config`` will get you going +(using your account information): + +.. code-block:: ini + + [nncli] + cfg_nn_username = lebowski@thedude.com + cfg_nn_password = nihilist + cfg_nn_host = nextcloud.thedude.com + +Start nncli with no arguments which starts the console GUI mode. nncli +will begin to sync your existing notes and you'll see log messages at +the bottom of the console. You can view these log messages at any time +by pressing the ``l`` key. + +View the help by pressing ``h``. Here you'll see all the keybinds and +configuration items. The middle column shows the config name that can be +used in your ``config`` to override the default setting. + +See example configuration file below for more notes. + +.. code-block:: ini + + [nncli] + cfg_nn_username = lebowski@thedude.com + cfg_nn_password = nihilist + cfg_nn_host = nextcloud.thedude.com + + ; as an alternate to cfg_nn_password you could use the following config item + ; any shell command can be used; its stdout is used for the password + ; trailing newlines are stripped for ease of use + ; note: if both password config are given, cfg_nn_password will be used + cfg_nn_password_eval = gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.nncli-pass.gpg + + ; see http://urwid.org/manual/userinput.html for examples of more key + ; combinations + kb_edit_note = space + kb_page_down = ctrl f + + ; note that values must not be quoted + clr_note_focus_bg = light blue + + ; if this editor config value is not provided, the $EDITOR env var will be + ; used instead + ; warning: if neither $EDITOR or cfg_editor is set, it will be impossible to + ; edit notes + cfg_editor = nvim + + ; alternatively, {fname} and/or {line} are substituted with the filename and + ; current line number in nncli's pager. + ; If {fname} isn't supplied, the filename is simply appended. + ; examples: + cfg_editor = nvim {fname} +{line} + cfg_editor = nano +{line} + + ; this is also supported for the pager: + cfg_pager = less -c +{line} -N {fname} diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..6270e93 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,23 @@ +.. nncli documentation master file, created by + sphinx-quickstart on Thu Aug 30 11:10:44 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +NextCloud Notes Command Line Interface +====================================== + +.. include:: ../../README.rst + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + configuration + usage + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` diff --git a/docs/source/usage.rst b/docs/source/usage.rst new file mode 100644 index 0000000..7502ecd --- /dev/null +++ b/docs/source/usage.rst @@ -0,0 +1,356 @@ +Usage +===== + +.. program:: nncli + +When ``nncli`` is run without any options or arguments an interactive +console GUI will appear. The behavior of this interface is highly +configurable (see: :ref:`configuration`). + +In addition to this default behavior, there are several options +available when calling ``nncli`` without a subcommand. + +.. option:: --help, -h + +Displays a brief decription of the ``nncli`` options and subcommands. + +.. option:: --version, -V + +Displays the version information. + +Also available when calling ``nncli`` by itself is the ``--config`` +option, for which see: :ref:`general-options`. + +Subcommands +----------- + +There are a variety of subcommands available from the command line when +using ``nncli``. The intent is for these subcommands to enable +scripting against your NextCloud Notes database. The subcommands are: + +- sync + +- list + +- export + +- dump + +- create + +- import + +- edit + +- delete + +- (un)favorite + +- cat {get,set,rm} + +These subcommands and the options available to them are described below. + +.. _general-options: + +General Subcommand Options +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Several ``nncli`` options apply to multiple subcommands. They are: + +.. option:: --verbose, -v + +Print verbose logging information to ``stdout`` + +.. option:: --nosync, -n + +Operate only on the local notes cache. Do not reach out to the server. + +.. option:: --regex, -r + +For subcommands that accept a search string, treat the search string as +a regular expression. + +.. option:: --key, -k + +The ID of the note to operate on. This option is required for many of +the subcommands. + +.. option:: --config, -c + +Specify the config file to read from. This option is only required to +override the default location (see: :ref:`config-file`). + +nncli sync +~~~~~~~~~~ + +.. program:: nncli sync + +Command format: ``nncli sync`` + +Performs a full, bi-directional sync between the local notes cache and +the NextCloud Notes server. There are no available options for this +subcommand. + +- Available options: None + +- Arguments: None + +nncli list +~~~~~~~~~~ + +.. program:: nncli list + +Command format: ``nncli list [search_string]`` + +List notes by ID, flags, and title. Flags indicate whether the note has +been modified locally (``X``), and/or if it is marked as a favorite +(``*``). + +- Available options: + + - ``--regex, -r`` See :ref:`general-options` + +- Arguments: + + - ``search_string`` Optional. A search term used to refine the search. + +nncli export +~~~~~~~~~~~~ + +.. program:: nncli export + +Command format: ``nncli export [search_string]`` + +Exports notes in raw, JSON format. The JSON format is a superset of the +format outlined in the NextCloud Notes API specification with +information added for managing the local notes cache. Note that nncli +still stores all the notes data in the directory specified by +``cfg_db_path``, so for easy backups, it may be easier/quicker to simply +backup this entire directory. + +- Available options: + + - :ref:`general-options` + + - ``--regex, -r`` Mutually exclusive with ``--key`` + + - ``--key, -k`` + +- Arguments: + + - ``search_string`` Required if ``--regex`` is specified. A search + term used to refine the search. + +Example: + +.. code-block:: sh + + # export a single note by id + nncli -k somekeyid export + + # export all notes + nncli export + + # export notes matching search string + nncli [-r] export some search keywords or regex + +nncli dump +~~~~~~~~~~ + +.. program:: nncli dump + +Command format: ``nncli dump [search_string]`` + +Prints notes to ``stdout``. The printed format is the text of the note +preceeded by a header displaying information about the note title, key, +modified date, category, and flags. Flags indicate whether the note has +been modified locally (``X``), and/or if it is marked as a favorite +(``*``). + +- Available options: + + - :ref:`general-options` + + - ``--regex, -r`` Mutually exclusive with ``--key`` + + - ``--key, -k`` + +- Arguments: + + - ``search_string`` Required if ``--regex`` is specified. A search + term used to refine the search. + +nncli create +~~~~~~~~~~~~ + +.. program:: nncli create + +Command format: ``nncli create [-]`` + +Create a note. Without arguments, this command will open your configured +editor. The note syncs to the server after the editor is closed. + +- Available options: None + +- Arguments: + + - `-` Optional. If specified, the note content is read from ``stdin``. + +Example: + +.. code-block:: sh + + # create a new note and open in editor + nncli create + + # create a new note with contents of stdin + echo 'hi' | nncli create - + +nncli import +~~~~~~~~~~~~ + +.. program:: nncli import + +Command format: ``nncli import [-]`` + +Import a JSON-formatted note. nncli can import notes from raw json data +(via stdin or editor). Allowed fields are ``content``, ``category``, +``favorite``, and ``modified``. + +- Available options: None + +- Arguments: + + - ``-`` Optional. If specified, the note content is read from ``stdin``. + +Example: + +.. code-block:: none + + echo '{"category":"testing","content":"New note!"}' | nncli import - + +nncli edit +~~~~~~~~~~ + +.. program:: nncli edit + +Command format: ``nncli -k <key> edit`` + +Open the note specified by ``<key>`` in the configured editor. The note +syncs to the server after the editor is saved and closed. + +- Available options: + + - ``--key, -k`` Required. See :ref:`general-options` + +- Arguments: None + +nncli delete +~~~~~~~~~~~~ + +.. program:: nncli delete + +Command format: ``nncli -k <key> delete`` + +Delete the note specified by ``<key>``. + +- Available options: + + - ``--key, -k`` Required. See :ref:`general-options` + +- Arguments: None + +nncli favorite +~~~~~~~~~~~~~~ + +.. program:: nncli favorite + +Command format: ``nncli -k <key> favorite|unfavorite`` + +Favorite (or unfavorite) the note specified by ``<key>``. + +- Available options: + + - ``--key, -k`` Required. See :ref:`general-options` + +- Arguments: None + +nncli cat +~~~~~~~~~ + +.. program:: nncli cat + +Command format: ``nncli -k <key> cat get|set|rm`` + +Read or modify a note category from the command line. + +- Available options: + + - ``--key, -k`` Required. See :ref:`general-options` + +- Arguments: + + - ``get`` Get the note category + + - ``set`` Set the note category + + - ``rm`` Remove the note category + +Example: + +.. code-block:: sh + + # Retrieve note category (e.g. "category1") + nncli -k somekeyid cat get + # Returns "category1" + + # Add a category to a note, overwriting any existing one + nncli -k somekeyid cat set "category3" + # Now tagged as "category3" + + # Remove a category from a note + nncli -k somekeyid cat rm + # Note now has no category + +Console GUI Usage +----------------- + +.. index:: single: searching + +Searching +~~~~~~~~~ + +nncli supports two styles of search strings. First is a Google style +search string and second is a Regular Expression. + +A Google style search string is a group of tokens (separated by spaces) +with an implied *AND* between each token. This style search is case +insensitive. For example: + +.. code-block:: none + + /category:category1 category:category2 word1 "word2 word3" category:category3 + +Regular expression searching also supports the use of flags (currently +only case-insensitive) by adding a final forward slash followed by the +flags. The following example will do a case-insensitive search for +``something``: + +.. code-block:: none + + (regex) /something/i + +.. index:: single: modelines + +Modelines +~~~~~~~~~ + +Advanced text editors usually tailor their behavior based on the file +type being edited. For such editors, notes opened through nncli should +be treated as Markdown by default. However, you can change this +on a per-note basis through the use of modelines. In Vim, for instance, +a modeline is a comment line conforming to the pattern below:: + + :: vim: ft=rst + +Now when you edit this note Vim will automatically load the rst plugin. @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -# -# The MIT License (MIT) -# -# Copyright (c) 2018 Daniel Moch -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# - -# -# ** The MIT License ** -# -# Copyright (c) 2014 Eric Davis (edavis@insanum.com) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# Dude... just buy me a beer. :-) -# - -from nnotes_cli import nncli - -if __name__ == '__main__': - nncli.main() - diff --git a/nncli/__init__.py b/nncli/__init__.py new file mode 100644 index 0000000..83d46a5 --- /dev/null +++ b/nncli/__init__.py @@ -0,0 +1,4 @@ +# -*- encoding: utf-8 -*- +"""NextCloud Notes Command Line Interface""" + +__version__ = '0.2.0' diff --git a/nncli/__main__.py b/nncli/__main__.py new file mode 100644 index 0000000..d96036a --- /dev/null +++ b/nncli/__main__.py @@ -0,0 +1,6 @@ +# -*- encoding: utf-8 -*- +"""nncli main module""" +import nncli.nncli + +if __name__ == '__main__': + nncli.nncli.main() diff --git a/nnotes_cli/clipboard.py b/nncli/clipboard.py index 8ef7c86..84ef1fa 100644 --- a/nnotes_cli/clipboard.py +++ b/nncli/clipboard.py @@ -1,7 +1,8 @@ +# -*- encoding: utf-8 -*- + import os from distutils import spawn - class Clipboard(object): def __init__(self): self.copy_command = self.get_copy_command() diff --git a/nnotes_cli/config.py b/nncli/config.py index 31b5172..4e8cc96 100644 --- a/nnotes_cli/config.py +++ b/nncli/config.py @@ -1,29 +1,4 @@ -# -# The MIT License (MIT) -# -# Copyright (c) 2018 Daniel Moch -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# - -# Copyright (c) 2014 Eric Davis -# Licensed under the MIT License +# -*- encoding: utf-8 -*- import os, sys, urwid, collections, configparser, subprocess @@ -296,4 +271,3 @@ class Config: def get_color_descr(self, name): return self.colors[name][1] - diff --git a/nnotes_cli/nextcloud_note.py b/nncli/nextcloud_note.py index f26fb33..5232a49 100644 --- a/nnotes_cli/nextcloud_note.py +++ b/nncli/nextcloud_note.py @@ -1,41 +1,4 @@ -# -# The MIT License (MIT) -# -# Copyright (c) 2018 Daniel Moch -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# - -# Copyright (c) 2014 Eric Davis -# This file is *slightly* modified from simplynote.py. - # -*- coding: utf-8 -*- -""" - nextcloud_note.py - ~~~~~~~~~~~~~~ - - Python library for accessing the NextCloud Notes API (v0.2) - - Modified from simplnote.py - :copyright: (c) 2011 by Daniel Schauenberg - :license: MIT, see LICENSE for more details. -""" import urllib.parse from requests.exceptions import RequestException, ConnectionError diff --git a/nnotes_cli/nncli.py b/nncli/nncli.py index 7ef76a6..340d3c1 100644 --- a/nnotes_cli/nncli.py +++ b/nncli/nncli.py @@ -1,34 +1,9 @@ -# -# The MIT License (MIT) -# -# Copyright (c) 2018 Daniel Moch -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# - -# Copyright (c) 2014 Eric Davis -# Licensed under the MIT License +# -*- encoding: utf-8 -*- import os, sys, getopt, re, signal, time, datetime, shlex, hashlib import subprocess, threading, logging import copy, json, urwid, datetime -import nnotes_cli +import nncli from . import view_titles, view_note, view_help, view_log, user_input from . import utils, temp from .config import Config @@ -1173,17 +1148,7 @@ Usage: sys.exit(0) def version(): - version_info = '' - version_info += nnotes_cli.__productname__ + ' v' + \ - nnotes_cli.__version__ + "\n" - version_info += nnotes_cli.__description__ + "\n\n" - version_info += nnotes_cli.__copyright__ + "\n" - version_info += "Written by " + nnotes_cli.__author__ + \ - " and others\n" - version_info += "Licensed under the terms of the " + \ - nnotes_cli.__license__ + " license\n" - version_info += "The latest code is available at: " + \ - nnotes_cli.__url__ + version_info = 'nncli {}'.format(nncli.__version__) print(version_info) exit(0) @@ -1338,4 +1303,3 @@ def main(argv=sys.argv[1:]): else: usage() - diff --git a/nnotes_cli/notes_db.py b/nncli/notes_db.py index c66bedf..9c688eb 100644 --- a/nnotes_cli/notes_db.py +++ b/nncli/notes_db.py @@ -1,33 +1,4 @@ -# -# The MIT License (MIT) -# -# Copyright (c) 2018 Daniel Moch -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# - -# Copyright (c) 2014 Eric Davis -# This file is *heavily* modified from nvpy. - -# nvPY: cross-platform note-taking app with simplenote syncing -# copyright 2012 by Charl P. Botha <cpbotha@vxlabs.com> -# new BSD license +# -*- encoding: utf-8 -*- import os, time, re, glob, json, copy, threading from . import utils @@ -675,4 +646,3 @@ class NotesDB(): self.go_cond.acquire() self.go_cond.notify() self.go_cond.release() - diff --git a/nnotes_cli/temp.py b/nncli/temp.py index 3850f7b..5bebbe6 100644 --- a/nnotes_cli/temp.py +++ b/nncli/temp.py @@ -1,6 +1,4 @@ - -# Copyright (c) 2014 Eric Davis -# Licensed under the MIT License +# -*- encoding: utf-8 -*- import os, json, tempfile diff --git a/nnotes_cli/user_input.py b/nncli/user_input.py index 79be6a3..d956145 100644 --- a/nnotes_cli/user_input.py +++ b/nncli/user_input.py @@ -1,6 +1,4 @@ - -# Copyright (c) 2014 Eric Davis -# Licensed under the MIT License +# -*- encoding: utf-8 -*- import urwid @@ -23,4 +21,3 @@ class UserInput(urwid.Edit): else: return super(UserInput, self).keypress(size, key) return None - diff --git a/nnotes_cli/utils.py b/nncli/utils.py index 4ad76e5..0a83c96 100644 --- a/nnotes_cli/utils.py +++ b/nncli/utils.py @@ -1,33 +1,4 @@ -# -# The MIT License (MIT) -# -# Copyright (c) 2018 Daniel Moch -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# - -# Copyright (c) 2014 Eric Davis -# This file is *heavily* modified from nvpy. - -# nvPY: cross-platform note-taking app with simplenote syncing -# copyright 2012 by Charl P. Botha <cpbotha@vxlabs.com> -# new BSD license +# -*- encoding: utf-8 -*- import datetime, random, re diff --git a/nnotes_cli/view_help.py b/nncli/view_help.py index 2593a08..4dc247e 100644 --- a/nnotes_cli/view_help.py +++ b/nncli/view_help.py @@ -1,6 +1,4 @@ - -# Copyright (c) 2014 Eric Davis -# Licensed under the MIT License +# -*- encoding: utf-8 -*- import re, urwid @@ -125,4 +123,3 @@ class ViewHelp(urwid.ListBox): def keypress(self, size, key): return key - diff --git a/nnotes_cli/view_log.py b/nncli/view_log.py index cc0f0a5..a529bf7 100644 --- a/nnotes_cli/view_log.py +++ b/nncli/view_log.py @@ -1,6 +1,4 @@ - -# Copyright (c) 2014 Eric Davis -# Licensed under the MIT License +# -*- encoding: utf-8 -*- import urwid @@ -47,4 +45,3 @@ class ViewLog(urwid.ListBox): def keypress(self, size, key): return key - diff --git a/nnotes_cli/view_note.py b/nncli/view_note.py index a06e76b..8732a50 100644 --- a/nnotes_cli/view_note.py +++ b/nncli/view_note.py @@ -1,6 +1,4 @@ - -# Copyright (c) 2014 Eric Davis -# Licensed under the MIT License +# -*- encoding: utf-8 -*- import time, urwid from . import utils diff --git a/nnotes_cli/view_titles.py b/nncli/view_titles.py index fac4c3a..58ccebf 100644 --- a/nnotes_cli/view_titles.py +++ b/nncli/view_titles.py @@ -1,6 +1,4 @@ - -# Copyright (c) 2014 Eric Davis -# Licensed under the MIT License +# encoding: utf-8 -*- import re, time, datetime, urwid, subprocess from . import utils, view_note @@ -189,4 +187,3 @@ class ViewTitles(urwid.ListBox): def keypress(self, size, key): return key - diff --git a/nnotes_cli/__init__.py b/nnotes_cli/__init__.py deleted file mode 100644 index 9908156..0000000 --- a/nnotes_cli/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -try: - from . import version - __version__ = version.version -except ImportError: - try: - from setuptools_scm import get_version - __version__ = get_version(root='..', relative_to=__file__) - except: - __version__ = '??-dev' - -__productname__ = 'nncli' -__copyright__ = "Copyright (c) 2018 Daniel Moch" -__author__ = "Daniel Moch" -__author_email__ = "daniel@danielmoch.com" -__description__ = "NextCloud Notes Command Line Interface" -__url__ = "https://github.com/djmoch/nncli" -__license__ = "MIT" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..0be3515 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,24 @@ +[build-system] +requires = ["flit"] +build-backend = "flit.buildapi" + +[tool.flit.metadata] +module = "nncli" +author = "Daniel Moch" +author-email = "daniel@danielmoch.com" +home-page = "https://github.com/djmoch/nncli" +description-file = "README.rst" +requires = ["urwid", "requests", "appdirs"] +classifiers = ["License :: OSI Approved :: MIT License", + "Development Status :: 4 - Beta", + "Environment :: Console :: Curses", + "Intended Audience :: End Users/Desktop", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3 :: Only"] +requires-python = ">=3" + +[tool.flit.metadata.requires-extra] +dev = ["pipenv"] + +[tool.flit.scripts] +nncli = "nncli.nncli:main" diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..86d57a4 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +mock_use_standalone_module = true diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index b0bd258..0000000 --- a/setup.cfg +++ /dev/null @@ -1,12 +0,0 @@ -[aliases] -test=pytest - -[tool:pytest] -testpaths = tests -addopts = --cov=nnotes_cli --cov-report=term-missing - -[yapf] -coalesce_brackets = true -dedent_closing_brackets = true -space_between_ending_comma_and_closing_bracket = false -split_arguments_when_comma_terminated = true diff --git a/setup.py b/setup.py deleted file mode 100644 index 9391552..0000000 --- a/setup.py +++ /dev/null @@ -1,64 +0,0 @@ -# -# The MIT License (MIT) -# -# Copyright (c) 2018 Daniel Moch -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# - -# Copyright (c) 2014 Eric Davis -# Licensed under the MIT License - -from setuptools import setup -import nnotes_cli - -deps = ['urwid', 'requests', 'appdirs'] -test_deps = ['pytest', 'pytest-cov', 'pytest-runner', 'pytest-mock'] - -with open("README.md", "r") as fh: - long_description = fh.read() - -setup( - name=nnotes_cli.__productname__, - description=nnotes_cli.__description__, - long_description=long_description, - long_description_content_type="text/markdown", - author=nnotes_cli.__author__, - author_email=nnotes_cli.__author_email__, - url=nnotes_cli.__url__, - license=nnotes_cli.__license__, - requires=deps, - install_requires=deps, - tests_require=test_deps, - use_scm_version= {'write_to': 'nnotes_cli/version.py'}, - setup_requires=['setuptools_scm'], - packages=['nnotes_cli'], - entry_points={ - 'console_scripts': [ - 'nncli = nnotes_cli.nncli:main' - ] - }, - classifiers=[ - 'Development Status :: 4 - Beta', - 'Environment :: Console :: Curses', - 'Intended Audience :: End Users/Desktop', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python :: 3 :: Only', - ], -) diff --git a/tests/test_config.py b/tests/test_config.py index 75fe1e9..0e6ffe1 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,33 +1,13 @@ -# -# The MIT License (MIT) -# -# Copyright (c) 2018 Daniel Moch -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# +# -*- encoding: utf-8 -*- + import os import sys -from nnotes_cli.config import Config +from nncli.config import Config from pytest import raises -def test_init(): +def test_init(mocker): + mocker.patch('subprocess.check_output') config = Config() if sys.platform == 'linux': diff --git a/tests/test_nncli.py b/tests/test_nncli.py index 394135a..78d213b 100644 --- a/tests/test_nncli.py +++ b/tests/test_nncli.py @@ -1,278 +1,279 @@ -# -# The MIT License (MIT) -# -# Copyright (c) 2018 Daniel Moch -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# +# -*- encoding: utf-8 -*- + import logging import os import pytest import shutil from logging.handlers import RotatingFileHandler -from nnotes_cli.nncli import nncli +import nncli.nncli +@pytest.fixture def mock_nncli(mocker): mocker.patch('logging.getLogger') - mocker.patch('nnotes_cli.config.Config') - mocker.patch('nnotes_cli.notes_db.NotesDB') + mocker.patch('nncli.nncli.NotesDB') mocker.patch('os.mkdir') mocker.patch.object(RotatingFileHandler, '_open') + mocker.patch('subprocess.check_output') + +def mock_get_config(mocker, return_list): + mocker.patch.object( + nncli.nncli.Config, + 'get_config', + new=mocker.MagicMock(side_effect=return_list) + ) def assert_initialized(): - logging.getLogger.assert_called_once() + assert logging.getLogger.call_count == 2 RotatingFileHandler._open.assert_called_once() - assert os.mkdir.call_count == 2 + os.mkdir.assert_called_once() -@pytest.mark.parametrize('mock_nncli', [mock_nncli]) def test_init_no_tempdir(mocker, mock_nncli): - mock_nncli(mocker) - - with open('test_cfg', 'w') as config_file: - config_file.write('[nncli]\n') - config_file.write('cfg_db_path=duh') - - nn = nncli(False, config_file='test_cfg') + mock_get_config(mocker, ['what', '', 'duh', 'duh', 'duh']) + nn = nncli.nncli.nncli(False) assert_initialized() assert nn.tempdir == None os.mkdir.assert_called_with('duh') - os.remove('test_cfg') - -@pytest.mark.parametrize('mock_nncli', [mock_nncli]) def test_init(mocker, mock_nncli): - mock_nncli(mocker) - - with open('test_cfg', 'w') as config_file: - config_file.write('[nncli]\n') - config_file.write('cfg_tempdir=blah\n') - config_file.write('cfg_db_path=duh') - - nn = nncli(False, config_file='test_cfg') + mock_get_config(mocker, ['what', 'blah', 'duh', 'duh', 'duh']) + nn = nncli.nncli.nncli(False) assert_initialized() assert nn.tempdir == 'blah' - os.remove('test_cfg') - -@pytest.mark.parametrize('mock_nncli', [mock_nncli]) def test_init_notesdb_fail(mocker, mock_nncli): - os.mkdir('duh') - mock_nncli(mocker) - - with open('duh/1.json', 'w') as bad_file: - bad_file.write('bad_json_data') - - with open('test_cfg', 'w') as config_file: - config_file.write('[nncli]\n') - config_file.write('cfg_db_path=duh') - + mock_get_config(mocker, ['what', 'blah', 'duh', 'duh', 'duh']) + mocker.patch('nncli.nncli.NotesDB', + new=mocker.MagicMock(side_effect=SystemExit) + ) with pytest.raises(SystemExit): - nn = nncli(False, config_file='test_cfg') - - shutil.rmtree('duh') + nn = nncli.nncli.nncli(False) -@pytest.mark.parametrize('mock_nncli', [mock_nncli]) def test_get_editor(mocker, mock_nncli): - mock_nncli(mocker) - - with open('test_cfg', 'w') as config_file: - config_file.write('[nncli]\n') - config_file.write('cfg_db_path=duh') - config_file.write('cfg_editor=vim') - - nn = nncli(False, config_file='test_cfg') + mock_get_config(mocker, ['what', 'blah', 'duh', 'duh', 'duh', 'vim', '']) + nn = nncli.nncli.nncli(False) assert_initialized() assert nn.get_editor() == 'vim' + assert nn.get_editor() == None - os.remove('test_cfg') - -@pytest.mark.parametrize('mock_nncli', [mock_nncli]) -def test_no_editor(mocker, mock_nncli): - mock_nncli(mocker) - - with open('test_cfg', 'w') as config_file: - config_file.write('[nncli]\n') - config_file.write('cfg_db_path=duh') - - nn = nncli(False, config_file='test_cfg') - nn.config.configs['editor'] = [''] +def test_get_pager(mocker, mock_nncli): + mock_get_config(mocker, ['what', 'blah', 'duh', 'duh', 'duh', 'less', '']) + nn = nncli.nncli.nncli(False) assert_initialized() + assert nn.get_editor() == 'less' assert nn.get_editor() == None - os.remove('test_cfg') - -def test_get_pager(): - pass - -def test_get_diff(): - pass +def test_get_diff(mocker, mock_nncli): + mock_get_config(mocker, ['what', 'blah', 'duh', 'duh', 'duh', 'diff', '']) + nn = nncli.nncli.nncli(False) + assert_initialized() + assert nn.get_editor() == 'diff' + assert nn.get_editor() == None -def test_exec_cmd_on_note(): - pass +@pytest.mark.skip +def test_exec_cmd_on_note(mocker, mock_nncli): + mocker.patch.object( + 'nncli.nncli.nncli', + get_editor, + new=mocker.MagicMock(return_value='vim')) + mocker.patch('nncli.temp.tempfile_create') +@pytest.mark.skip def test_exec_diff_on_note(): pass +@pytest.mark.skip def test_gui_header_clear(): pass +@pytest.mark.skip def test_gui_header_set(): pass +@pytest.mark.skip def test_gui_header_get(): pass +@pytest.mark.skip def test_gui_header_focus(): pass +@pytest.mark.skip def test_gui_footer_log_clear(): pass +@pytest.mark.skip def test_gui_footer_log_set(): pass +@pytest.mark.skip def test_gui_footer_log_get(): pass +@pytest.mark.skip def test_gui_footer_input_clear(): pass +@pytest.mark.skip def test_gui_footer_input_set(): pass +@pytest.mark.skip def test_gui_footer_input_get(): pass +@pytest.mark.skip def test_gui_footer_focus_input(): pass +@pytest.mark.skip def test_gui_body_clear(): pass +@pytest.mark.skip def test_gui_body_set(): pass +@pytest.mark.skip def test_gui_body_get(): pass +@pytest.mark.skip def test_gui_body_focus(): pass +@pytest.mark.skip def test_log_timeout(): pass +@pytest.mark.skip def test_log(): pass +@pytest.mark.skip def test_gui_update_view(): pass +@pytest.mark.skip def test_gui_update_status_bar(): pass +@pytest.mark.skip def test_gui_switch_frame_body(): pass +@pytest.mark.skip def test_delete_note_callback(): pass +@pytest.mark.skip def test_gui_yes_no_input(): pass +@pytest.mark.skip def test_gui_search_input(): pass +@pytest.mark.skip def test_gui_category_input(): pass +@pytest.mark.skip def test_gui_pipe_input(): pass +@pytest.mark.skip def test_gui_frame_keypress(): pass +@pytest.mark.skip def test_gui_init_view(): pass +@pytest.mark.skip def test_gui_clear(): pass +@pytest.mark.skip def test_gui_reset(): pass +@pytest.mark.skip def test_gui_stop(): pass +@pytest.mark.skip def test_gui(): pass +@pytest.mark.skip def test_cli_list_notes(): pass +@pytest.mark.skip def test_cli_note_dump(): pass +@pytest.mark.skip def test_cli_dump_notes(): pass +@pytest.mark.skip def test_cli_note_create(): pass +@pytest.mark.skip def test_cli_note_import(): pass +@pytest.mark.skip def test_cli_note_export(): pass +@pytest.mark.skip def test_cli_export_notes(): pass +@pytest.mark.skip def test_cli_note_edit(): pass +@pytest.mark.skip def test_cli_note_delete(): pass +@pytest.mark.skip def test_cli_note_favorite(): pass +@pytest.mark.skip def test_cli_note_category_get(): pass +@pytest.mark.skip def test_cli_note_category_set(): pass +@pytest.mark.skip def test_cli_note_category_rm(): pass +@pytest.mark.skip def test_SIGINT_handler(): pass +@pytest.mark.skip def test_usage(): pass +@pytest.mark.skip def test_version(): pass +@pytest.mark.skip def test_main(): pass +@pytest.mark.skip def test_nncli_start(): pass diff --git a/tests/test_version.py b/tests/test_version.py deleted file mode 100644 index af1224a..0000000 --- a/tests/test_version.py +++ /dev/null @@ -1,35 +0,0 @@ -# -# The MIT License (MIT) -# -# Copyright (c) 2018 Daniel Moch -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -import nnotes_cli -import pytest - -from nnotes_cli import version -from setuptools_scm import get_version - -@pytest.mark.skip(reason="test_version will fail outside of a Git repo") -def test_version(): - vers = get_version(root="..", relative_to=__file__) - - assert nnotes_cli.__version__ == vers - assert version.version == vers @@ -0,0 +1,29 @@ +[tox] +envlist = py34, py35, py36, py37, pylint, coverage +skipsdist = True + +[testenv:pylint] +deps = pylint +whitelist_externals = make +commands = make lint + +[testenv:coverage] +deps = pipenv +setenv = + PIPENV_NO_INHERIT = 1 + PIPENV_HIDE_EMOJIS = 1 +whitelist_externals = make +commands = + make test-install + make coverage + +[testenv] +deps = pipenv +setenv = + PIPENV_NO_INHERIT = 1 + PIPENV_HIDE_EMOJIS = 1 +whitelist_externals = make +commands = + make test-install + make install + make test |