mirror of
https://github.com/ProtoThis/python-synology.git
synced 2025-08-08 06:36:06 +00:00
Migrate to poetry, nox and GitHub actions (#78)
* Replace setup files with pyproject.toml Now we can use poetry to manage the package. poetry install to install the package in a venv poetry run ... to launch pylint, pytest or black * Add CI with GitHub Action Add a tests and release workflow Add release drafter Add dependabot * Remove old CI based on travis and pylint * Add linting configuration files Linting mainly based on flake8 and plugins. Add specific files for darglint and mypy. * Update .gitignore * Add test suite with nox and pre-commit Test suite inculde pre-commit, safety, mypy, tests, typguard and documentation checks. * Add .gitattributes * Update code coverage target to 80% * Code style update by Black * Update poetry lock file * Deactivate temporarly some linting tests * Add a contributing guide * Remove Python 3.6 in GitHub Action * Patch noxfile.py to be able to test mypy session * Rebase version to 1.0.0
This commit is contained in:
12
.flake8
Normal file
12
.flake8
Normal file
@ -0,0 +1,12 @@
|
||||
[flake8]
|
||||
select = B,B9,C,DAR,E,F,N,RST,S,W
|
||||
# Some tests have been added to the ignore list to avoid reworking too much
|
||||
# the code in this PR: D107, D403, B950, E266, C901, F401, E302.
|
||||
# The error will be processed in a dedicated PR.
|
||||
# targeted ignore list is:
|
||||
# ignore = E203,E501,RST201,RST203,RST301,W503
|
||||
ignore = E203,E501,RST201,RST203,RST301,W503, D107, D403, B950, E266, C901, F401, E302
|
||||
max-line-length = 80
|
||||
max-complexity = 10
|
||||
docstring-convention = google
|
||||
per-file-ignores = tests/*:S101
|
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
18
.github/dependabot.yml
vendored
Normal file
18
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
- package-ecosystem: pip
|
||||
directory: "/.github/workflows"
|
||||
schedule:
|
||||
interval: daily
|
||||
- package-ecosystem: pip
|
||||
directory: "/docs"
|
||||
schedule:
|
||||
interval: daily
|
||||
- package-ecosystem: pip
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
29
.github/release-drafter.yml
vendored
Normal file
29
.github/release-drafter.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
categories:
|
||||
- title: ":boom: Breaking Changes"
|
||||
label: "breaking"
|
||||
- title: ":rocket: Features"
|
||||
label: "enhancement"
|
||||
- title: ":fire: Removals and Deprecations"
|
||||
label: "removal"
|
||||
- title: ":beetle: Fixes"
|
||||
label: "bug"
|
||||
- title: ":racehorse: Performance"
|
||||
label: "performance"
|
||||
- title: ":rotating_light: Testing"
|
||||
label: "testing"
|
||||
- title: ":construction_worker: Continuous Integration"
|
||||
label: "ci"
|
||||
- title: ":books: Documentation"
|
||||
label: "documentation"
|
||||
- title: ":hammer: Refactoring"
|
||||
label: "refactoring"
|
||||
- title: ":lipstick: Style"
|
||||
label: "style"
|
||||
- title: ":package: Dependencies"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "build"
|
||||
template: |
|
||||
## Changes
|
||||
|
||||
$CHANGES
|
5
.github/workflows/constraints.txt
vendored
Normal file
5
.github/workflows/constraints.txt
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
pip==20.2.4
|
||||
nox==2020.8.22
|
||||
nox-poetry==0.5.0
|
||||
poetry==1.0.10
|
||||
virtualenv==20.0.35
|
79
.github/workflows/release.yml
vendored
Normal file
79
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v2.3.3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2.1.4
|
||||
with:
|
||||
python-version: "3.9"
|
||||
|
||||
- name: Upgrade pip
|
||||
run: |
|
||||
pip install --constraint=.github/workflows/constraints.txt pip
|
||||
pip --version
|
||||
|
||||
- name: Install Poetry
|
||||
run: |
|
||||
pip install --constraint=.github/workflows/constraints.txt poetry
|
||||
poetry --version
|
||||
|
||||
- name: Check if there is a parent commit
|
||||
id: check-parent-commit
|
||||
run: |
|
||||
echo "::set-output name=sha::$(git rev-parse --verify --quiet HEAD^)"
|
||||
|
||||
- name: Detect and tag new version
|
||||
id: check-version
|
||||
if: steps.check-parent-commit.outputs.sha
|
||||
uses: salsify/action-detect-and-tag-new-version@v2.0.1
|
||||
with:
|
||||
version-command: |
|
||||
bash -o pipefail -c "poetry version | awk '{ print \$2 }'"
|
||||
|
||||
- name: Bump version for developmental release
|
||||
if: "! steps.check-version.outputs.tag"
|
||||
run: |
|
||||
poetry version patch &&
|
||||
version=$(poetry version | awk '{ print $2 }') &&
|
||||
poetry version $version.dev.$(date +%s)
|
||||
|
||||
- name: Build package
|
||||
run: |
|
||||
poetry build --ansi
|
||||
|
||||
- name: Publish package on PyPI
|
||||
if: steps.check-version.outputs.tag
|
||||
uses: pypa/gh-action-pypi-publish@v1.4.1
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_TOKEN }}
|
||||
|
||||
- name: Publish package on TestPyPI
|
||||
if: "! steps.check-version.outputs.tag"
|
||||
uses: pypa/gh-action-pypi-publish@v1.4.1
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.TEST_PYPI_TOKEN }}
|
||||
repository_url: https://test.pypi.org/legacy/
|
||||
|
||||
- name: Publish release notes
|
||||
uses: release-drafter/release-drafter@v5.12.0
|
||||
with:
|
||||
publish: ${{ steps.check-version.outputs.tag != '' }}
|
||||
tag: ${{ steps.check-version.outputs.tag }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
140
.github/workflows/tests.yml
vendored
Normal file
140
.github/workflows/tests.yml
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: ${{ matrix.session }} ${{ matrix.python-version }} / ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Commented session will be activated in the future
|
||||
- { python-version: 3.9, os: ubuntu-latest, session: "pre-commit" }
|
||||
- { python-version: 3.9, os: ubuntu-latest, session: "safety" }
|
||||
# - { python-version: 3.9, os: ubuntu-latest, session: "mypy" }
|
||||
# - { python-version: 3.8, os: ubuntu-latest, session: "mypy" }
|
||||
# - { python-version: 3.7, os: ubuntu-latest, session: "mypy" }
|
||||
- { python-version: 3.9, os: ubuntu-latest, session: "tests" }
|
||||
- { python-version: 3.8, os: ubuntu-latest, session: "tests" }
|
||||
- { python-version: 3.7, os: ubuntu-latest, session: "tests" }
|
||||
- { python-version: 3.9, os: windows-latest, session: "tests" }
|
||||
- { python-version: 3.9, os: macos-latest, session: "tests" }
|
||||
# - { python-version: 3.9, os: ubuntu-latest, session: "typeguard" }
|
||||
# - { python-version: 3.9, os: ubuntu-latest, session: "xdoctest" }
|
||||
# - { python-version: 3.8, os: ubuntu-latest, session: "docs-build" }
|
||||
|
||||
env:
|
||||
NOXSESSION: ${{ matrix.session }}
|
||||
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v2.3.3
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2.1.4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Upgrade pip
|
||||
run: |
|
||||
pip install --constraint=.github/workflows/constraints.txt pip
|
||||
pip --version
|
||||
|
||||
- name: Install Poetry
|
||||
run: |
|
||||
pip install --constraint=.github/workflows/constraints.txt poetry
|
||||
poetry --version
|
||||
|
||||
- name: Install Nox
|
||||
run: |
|
||||
pip install --constraint=.github/workflows/constraints.txt nox nox-poetry
|
||||
nox --version
|
||||
|
||||
- name: Compute pre-commit cache key
|
||||
if: matrix.session == 'pre-commit'
|
||||
id: pre-commit-cache
|
||||
shell: python
|
||||
run: |
|
||||
import hashlib
|
||||
import sys
|
||||
|
||||
python = "py{}.{}".format(*sys.version_info[:2])
|
||||
payload = sys.version.encode() + sys.executable.encode()
|
||||
digest = hashlib.sha256(payload).hexdigest()
|
||||
result = "${{ runner.os }}-{}-{}-pre-commit".format(python, digest[:8])
|
||||
|
||||
print("::set-output name=result::{}".format(result))
|
||||
|
||||
- name: Restore pre-commit cache
|
||||
uses: actions/cache@v2.1.2
|
||||
if: matrix.session == 'pre-commit'
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: ${{ steps.pre-commit-cache.outputs.result }}-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
restore-keys: |
|
||||
${{ steps.pre-commit-cache.outputs.result }}-
|
||||
|
||||
- name: Run Nox
|
||||
run: |
|
||||
nox --force-color --python=${{ matrix.python-version }}
|
||||
|
||||
- name: Upload coverage data
|
||||
if: always() && matrix.session == 'tests'
|
||||
uses: "actions/upload-artifact@v2.2.0"
|
||||
with:
|
||||
name: coverage-data
|
||||
path: ".coverage.*"
|
||||
|
||||
- name: Upload documentation
|
||||
if: matrix.session == 'docs-build'
|
||||
uses: actions/upload-artifact@v2.2.0
|
||||
with:
|
||||
name: docs
|
||||
path: docs/_build
|
||||
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
needs: tests
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v2.3.2
|
||||
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@v2.1.4
|
||||
with:
|
||||
python-version: 3.9
|
||||
|
||||
- name: Upgrade pip
|
||||
run: |
|
||||
pip install --constraint=.github/workflows/constraints.txt pip
|
||||
pip --version
|
||||
|
||||
- name: Install Poetry
|
||||
run: |
|
||||
pip install --constraint=.github/workflows/constraints.txt poetry
|
||||
poetry --version
|
||||
|
||||
- name: Install Nox
|
||||
run: |
|
||||
pip install --constraint=.github/workflows/constraints.txt nox nox-poetry
|
||||
nox --version
|
||||
|
||||
- name: Download coverage data
|
||||
uses: actions/download-artifact@v2.0.5
|
||||
with:
|
||||
name: coverage-data
|
||||
|
||||
- name: Combine coverage data and display human readable report
|
||||
run: |
|
||||
nox --force-color --session=coverage
|
||||
|
||||
- name: Create coverage report
|
||||
run: |
|
||||
nox --force-color --session=coverage -- xml
|
||||
|
||||
- name: Upload coverage report
|
||||
uses: codecov/codecov-action@v1.0.14
|
14
.gitignore
vendored
14
.gitignore
vendored
@ -1,3 +1,17 @@
|
||||
# From cookiecutter-hypermodern-python
|
||||
.mypy_cache/
|
||||
/.coverage
|
||||
/.nox/
|
||||
/.python-version
|
||||
/.pytype/
|
||||
/dist/
|
||||
/docs/_build/
|
||||
/src/*.egg-info/
|
||||
__pycache__/
|
||||
|
||||
# Following are kept for not anoying current developers. Could be remove in
|
||||
# a future package release.
|
||||
|
||||
# Python
|
||||
*.py[cod]
|
||||
|
||||
|
51
.pre-commit-config.yaml
Normal file
51
.pre-commit-config.yaml
Normal file
@ -0,0 +1,51 @@
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: black
|
||||
name: black
|
||||
entry: black
|
||||
language: system
|
||||
types: [python]
|
||||
require_serial: true
|
||||
- id: check-added-large-files
|
||||
name: Check for added large files
|
||||
entry: check-added-large-files
|
||||
language: system
|
||||
- id: check-toml
|
||||
name: Check Toml
|
||||
entry: check-toml
|
||||
language: system
|
||||
types: [toml]
|
||||
- id: check-yaml
|
||||
name: Check Yaml
|
||||
entry: check-yaml
|
||||
language: system
|
||||
types: [yaml]
|
||||
- id: end-of-file-fixer
|
||||
name: Fix End of Files
|
||||
entry: end-of-file-fixer
|
||||
language: system
|
||||
types: [text]
|
||||
stages: [commit, push, manual]
|
||||
- id: flake8
|
||||
name: flake8
|
||||
entry: flake8
|
||||
language: system
|
||||
types: [python]
|
||||
require_serial: true
|
||||
- id: reorder-python-imports
|
||||
name: Reorder python imports
|
||||
entry: reorder-python-imports
|
||||
language: system
|
||||
types: [python]
|
||||
args: [--application-directories=src]
|
||||
- id: trailing-whitespace
|
||||
name: Trim Trailing Whitespace
|
||||
entry: trailing-whitespace-fixer
|
||||
language: system
|
||||
types: [text]
|
||||
stages: [commit, push, manual]
|
||||
- repo: https://github.com/prettier/prettier
|
||||
rev: 2.1.2
|
||||
hooks:
|
||||
- id: prettier
|
38
.travis.yml
38
.travis.yml
@ -1,38 +0,0 @@
|
||||
os: linux
|
||||
dist: xenial
|
||||
|
||||
language: python
|
||||
python:
|
||||
- 3.6
|
||||
- 3.7
|
||||
- 3.8
|
||||
cache:
|
||||
pip: true
|
||||
|
||||
before_install:
|
||||
- pip install -r requirements_all.txt
|
||||
- pip install -e .
|
||||
install:
|
||||
- python setup.py install
|
||||
- python setup.py sdist
|
||||
before_script:
|
||||
- pylint src tests
|
||||
- black --check --fast .
|
||||
script:
|
||||
- py.test
|
||||
|
||||
deploy:
|
||||
- provider: pypi
|
||||
user: $pypi_test_user
|
||||
password: $pypi_test_pass
|
||||
server: $pypi_test
|
||||
on:
|
||||
branch: deploy-test
|
||||
python: 3.8
|
||||
- provider: pypi
|
||||
user: $pypi_user
|
||||
password: $pypi_pass
|
||||
server: $pypi
|
||||
on:
|
||||
branch: deploy
|
||||
python: 3.8
|
121
CONTRIBUTING.rst
Normal file
121
CONTRIBUTING.rst
Normal file
@ -0,0 +1,121 @@
|
||||
Contributor Guide
|
||||
=================
|
||||
|
||||
Thank you for your interest in improving this project.
|
||||
This project is open-source under the `MIT license`_ and
|
||||
welcomes contributions in the form of bug reports, feature requests, and pull requests.
|
||||
|
||||
Here is a list of important resources for contributors:
|
||||
|
||||
- `Source Code`_
|
||||
- `Documentation`_
|
||||
- `Issue Tracker`_
|
||||
- `Code of Conduct`_
|
||||
|
||||
.. _MIT license: https://opensource.org/licenses/MIT
|
||||
.. _Source Code: https://github.com/ProtoThis/python-synology
|
||||
.. _Documentation: https://python-synology.readthedocs.io/
|
||||
.. _Issue Tracker: https://github.com/ProtoThis/python-synology/issues
|
||||
|
||||
How to report a bug
|
||||
-------------------
|
||||
|
||||
Report bugs on the `Issue Tracker`_.
|
||||
|
||||
When filing an issue, make sure to answer these questions:
|
||||
|
||||
- Which operating system and Python version are you using?
|
||||
- Which version of this project are you using?
|
||||
- What did you do?
|
||||
- What did you expect to see?
|
||||
- What did you see instead?
|
||||
|
||||
The best way to get your bug fixed is to provide a test case,
|
||||
and/or steps to reproduce the issue.
|
||||
|
||||
|
||||
How to request a feature
|
||||
------------------------
|
||||
|
||||
Request features on the `Issue Tracker`_.
|
||||
|
||||
|
||||
How to set up your development environment
|
||||
------------------------------------------
|
||||
|
||||
You need Python 3.6+ and the following tools:
|
||||
|
||||
- Poetry_
|
||||
- Nox_
|
||||
- nox-poetry_
|
||||
|
||||
Install the package with development requirements:
|
||||
|
||||
.. code:: console
|
||||
|
||||
$ poetry install
|
||||
|
||||
You can now run an interactive Python session:
|
||||
|
||||
.. code:: console
|
||||
|
||||
$ poetry run python
|
||||
|
||||
.. _Poetry: https://python-poetry.org/
|
||||
.. _Nox: https://nox.thea.codes/
|
||||
.. _nox-poetry: https://nox-poetry.readthedocs.io/
|
||||
|
||||
|
||||
How to test the project
|
||||
-----------------------
|
||||
|
||||
Run the full test suite:
|
||||
|
||||
.. code:: console
|
||||
|
||||
$ nox
|
||||
|
||||
List the available Nox sessions:
|
||||
|
||||
.. code:: console
|
||||
|
||||
$ nox --list-sessions
|
||||
|
||||
You can also run a specific Nox session.
|
||||
For example, invoke the unit test suite like this:
|
||||
|
||||
.. code:: console
|
||||
|
||||
$ nox --session=tests
|
||||
|
||||
Unit tests are located in the ``tests`` directory,
|
||||
and are written using the pytest_ testing framework.
|
||||
|
||||
.. _pytest: https://pytest.readthedocs.io/
|
||||
|
||||
|
||||
How to submit changes
|
||||
---------------------
|
||||
|
||||
Open a `pull request`_ to submit changes to this project.
|
||||
|
||||
Your pull request needs to meet the following guidelines for acceptance:
|
||||
|
||||
- The Nox test suite must pass without errors and warnings.
|
||||
- Include unit tests. This project maintains 100% code coverage.
|
||||
- If your changes add functionality, update the documentation accordingly.
|
||||
|
||||
Feel free to submit early, though—we can always iterate on this.
|
||||
|
||||
To run linting and code formatting checks before commiting your change, you can install pre-commit as a Git hook by running the following command:
|
||||
|
||||
.. code:: console
|
||||
|
||||
$ nox --session=pre-commit -- install
|
||||
|
||||
It is recommended to open an issue before starting work on anything.
|
||||
This will allow a chance to talk it over with the owners and validate your approach.
|
||||
|
||||
.. _pull request: https://github.com/ProtoThis/python-synology/pulls
|
||||
.. github-only
|
||||
.. _Code of Conduct: CODE_OF_CONDUCT.rst
|
9
codecov.yml
Normal file
9
codecov.yml
Normal file
@ -0,0 +1,9 @@
|
||||
comment: false
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: "80"
|
||||
patch:
|
||||
default:
|
||||
target: "100"
|
20
mypy.ini
Normal file
20
mypy.ini
Normal file
@ -0,0 +1,20 @@
|
||||
[mypy]
|
||||
check_untyped_defs = True
|
||||
disallow_any_generics = True
|
||||
disallow_incomplete_defs = True
|
||||
disallow_subclassing_any = True
|
||||
disallow_untyped_calls = True
|
||||
disallow_untyped_decorators = True
|
||||
disallow_untyped_defs = True
|
||||
no_implicit_optional = True
|
||||
no_implicit_reexport = True
|
||||
pretty = True
|
||||
show_column_numbers = True
|
||||
show_error_codes = True
|
||||
show_error_context = True
|
||||
strict_equality = True
|
||||
warn_redundant_casts = True
|
||||
warn_return_any = True
|
||||
warn_unreachable = True
|
||||
warn_unused_configs = True
|
||||
warn_unused_ignores = True
|
188
noxfile.py
Normal file
188
noxfile.py
Normal file
@ -0,0 +1,188 @@
|
||||
"""Nox sessions."""
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from textwrap import dedent
|
||||
|
||||
import nox
|
||||
import nox_poetry.patch
|
||||
from nox.sessions import Session
|
||||
|
||||
|
||||
package = "synology_dsm"
|
||||
python_versions = ["3.9", "3.8", "3.7"]
|
||||
# Comment some sessions as they need to work on the code to not fail.
|
||||
# Will be activated in future release.
|
||||
nox.options.sessions = (
|
||||
"pre-commit",
|
||||
"safety",
|
||||
# "mypy",
|
||||
"tests",
|
||||
# "typeguard",
|
||||
# "xdoctest",
|
||||
# "docs-build",
|
||||
)
|
||||
|
||||
|
||||
def activate_virtualenv_in_precommit_hooks(session: Session) -> None:
|
||||
"""Activate virtualenv in hooks installed by pre-commit.
|
||||
|
||||
This function patches git hooks installed by pre-commit to activate the
|
||||
session's virtual environment. This allows pre-commit to locate hooks in
|
||||
that environment when invoked from git.
|
||||
|
||||
Args:
|
||||
session: The Session object.
|
||||
"""
|
||||
if session.bin is None:
|
||||
return
|
||||
|
||||
virtualenv = session.env.get("VIRTUAL_ENV")
|
||||
if virtualenv is None:
|
||||
return
|
||||
|
||||
hookdir = Path(".git") / "hooks"
|
||||
if not hookdir.is_dir():
|
||||
return
|
||||
|
||||
for hook in hookdir.iterdir():
|
||||
if hook.name.endswith(".sample") or not hook.is_file():
|
||||
continue
|
||||
|
||||
text = hook.read_text()
|
||||
bindir = repr(session.bin)[1:-1] # strip quotes
|
||||
if not (
|
||||
Path("A") == Path("a") and bindir.lower() in text.lower() or bindir in text
|
||||
):
|
||||
continue
|
||||
|
||||
lines = text.splitlines()
|
||||
if not (lines[0].startswith("#!") and "python" in lines[0].lower()):
|
||||
continue
|
||||
|
||||
header = dedent(
|
||||
f"""\
|
||||
import os
|
||||
os.environ["VIRTUAL_ENV"] = {virtualenv!r}
|
||||
os.environ["PATH"] = os.pathsep.join((
|
||||
{session.bin!r},
|
||||
os.environ.get("PATH", ""),
|
||||
))
|
||||
"""
|
||||
)
|
||||
|
||||
lines.insert(1, header)
|
||||
hook.write_text("\n".join(lines))
|
||||
|
||||
|
||||
@nox.session(name="pre-commit", python="3.9")
|
||||
def precommit(session: Session) -> None:
|
||||
"""Lint using pre-commit."""
|
||||
args = session.posargs or ["run", "--all-files", "--show-diff-on-failure"]
|
||||
session.install(
|
||||
"black",
|
||||
"darglint",
|
||||
"flake8",
|
||||
"flake8-bandit",
|
||||
"flake8-bugbear",
|
||||
"flake8-docstrings",
|
||||
"flake8-rst-docstrings",
|
||||
"pep8-naming",
|
||||
"pre-commit",
|
||||
"pre-commit-hooks",
|
||||
"reorder-python-imports",
|
||||
)
|
||||
session.run("pre-commit", *args)
|
||||
if args and args[0] == "install":
|
||||
activate_virtualenv_in_precommit_hooks(session)
|
||||
|
||||
|
||||
@nox.session(python="3.9")
|
||||
def safety(session: Session) -> None:
|
||||
"""Scan dependencies for insecure packages."""
|
||||
requirements = nox_poetry.export_requirements(session)
|
||||
session.install("safety")
|
||||
session.run("safety", "check", f"--file={requirements}", "--bare")
|
||||
|
||||
|
||||
@nox.session(python=python_versions)
|
||||
def mypy(session: Session) -> None:
|
||||
"""Type-check using mypy."""
|
||||
args = session.posargs or ["src", "tests"]
|
||||
session.install(".")
|
||||
session.install("mypy", "pytest")
|
||||
session.run("mypy", *args)
|
||||
if not session.posargs:
|
||||
session.run("mypy", f"--python-executable={sys.executable}", "noxfile.py")
|
||||
|
||||
|
||||
@nox.session(python=python_versions)
|
||||
def tests(session: Session) -> None:
|
||||
"""Run the test suite."""
|
||||
session.install(".")
|
||||
session.install("coverage[toml]", "pytest", "pygments")
|
||||
try:
|
||||
session.run("coverage", "run", "--parallel", "-m", "pytest", *session.posargs)
|
||||
finally:
|
||||
if session.interactive:
|
||||
session.notify("coverage")
|
||||
|
||||
|
||||
@nox.session
|
||||
def coverage(session: Session) -> None:
|
||||
"""Produce the coverage report."""
|
||||
# Do not use session.posargs unless this is the only session.
|
||||
has_args = session.posargs and len(session._runner.manifest) == 1
|
||||
args = session.posargs if has_args else ["report"]
|
||||
|
||||
session.install("coverage[toml]")
|
||||
|
||||
if not has_args and any(Path().glob(".coverage.*")):
|
||||
session.run("coverage", "combine")
|
||||
|
||||
session.run("coverage", *args)
|
||||
|
||||
|
||||
@nox.session(python=python_versions)
|
||||
def typeguard(session: Session) -> None:
|
||||
"""Runtime type checking using Typeguard."""
|
||||
session.install(".")
|
||||
session.install("pytest", "typeguard", "pygments")
|
||||
session.run("pytest", f"--typeguard-packages={package}", *session.posargs)
|
||||
|
||||
|
||||
@nox.session(python=python_versions)
|
||||
def xdoctest(session: Session) -> None:
|
||||
"""Run examples with xdoctest."""
|
||||
args = session.posargs or ["all"]
|
||||
session.install(".")
|
||||
session.install("xdoctest[colors]")
|
||||
session.run("python", "-m", "xdoctest", package, *args)
|
||||
|
||||
|
||||
@nox.session(name="docs-build", python="3.8")
|
||||
def docs_build(session: Session) -> None:
|
||||
"""Build the documentation."""
|
||||
args = session.posargs or ["docs", "docs/_build"]
|
||||
session.install(".")
|
||||
session.install("sphinx", "sphinx-rtd-theme")
|
||||
|
||||
build_dir = Path("docs", "_build")
|
||||
if build_dir.exists():
|
||||
shutil.rmtree(build_dir)
|
||||
|
||||
session.run("sphinx-build", *args)
|
||||
|
||||
|
||||
@nox.session(python="3.8")
|
||||
def docs(session: Session) -> None:
|
||||
"""Build and serve the documentation with live reloading on file changes."""
|
||||
args = session.posargs or ["--open-browser", "docs", "docs/_build"]
|
||||
session.install(".")
|
||||
session.install("sphinx", "sphinx-autobuild", "sphinx-rtd-theme")
|
||||
|
||||
build_dir = Path("docs", "_build")
|
||||
if build_dir.exists():
|
||||
shutil.rmtree(build_dir)
|
||||
|
||||
session.run("sphinx-autobuild", *args)
|
1494
poetry.lock
generated
Normal file
1494
poetry.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
43
pylintrc
43
pylintrc
@ -1,43 +0,0 @@
|
||||
[MASTER]
|
||||
# Use a conservative default here; 2 should speed up most setups and not hurt
|
||||
# any too bad. Override on command line as appropriate.
|
||||
jobs=2
|
||||
persistent=no
|
||||
extension-pkg-whitelist=ciso8601
|
||||
|
||||
[BASIC]
|
||||
good-names=id,i,j,k
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
# Reasons disabled:
|
||||
# format - handled by black
|
||||
# duplicate-code - unavoidable
|
||||
# too-many-* - are not enforced for the sake of readability
|
||||
# too-few-* - same as too-many-*
|
||||
# inconsistent-return-statements - doesn't handle raise
|
||||
# unnecessary-pass - readability for functions which only contain pass
|
||||
# useless-object-inheritance - should be removed while droping Python 2
|
||||
# wrong-import-order - isort guards this
|
||||
disable=
|
||||
format,
|
||||
duplicate-code,
|
||||
inconsistent-return-statements,
|
||||
too-few-public-methods,
|
||||
too-many-ancestors,
|
||||
too-many-arguments,
|
||||
too-many-branches,
|
||||
too-many-instance-attributes,
|
||||
too-many-lines,
|
||||
too-many-locals,
|
||||
too-many-public-methods,
|
||||
too-many-return-statements,
|
||||
too-many-statements,
|
||||
too-many-boolean-expressions,
|
||||
unnecessary-pass,
|
||||
useless-object-inheritance,
|
||||
|
||||
[FORMAT]
|
||||
expected-line-ending-format=LF
|
||||
|
||||
[EXCEPTIONS]
|
||||
overgeneral-exceptions=PyiCloudException
|
@ -1,21 +1,76 @@
|
||||
[tool.black]
|
||||
line-length = 88
|
||||
target-version = ["py27", "py33", "py34", "py35", "py36", "py37", "py38"]
|
||||
exclude = '''
|
||||
[tool.poetry]
|
||||
name = "python-synology"
|
||||
version = "1.0.0"
|
||||
description = "Python API for communication with Synology DSM"
|
||||
authors = ["Quentin POLLET (Quentame)", "FG van Zeelst (ProtoThis)"]
|
||||
license = "MIT"
|
||||
readme = "README.rst"
|
||||
homepage = "https://github.com/ProtoThis/python-synology"
|
||||
repository = "https://github.com/ProtoThis/python-synology"
|
||||
documentation = "https://python-synology.readthedocs.io"
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
]
|
||||
keywords=["synology-dsm", "synology"]
|
||||
packages = [
|
||||
{ include = "synology_dsm", from = "src" },
|
||||
]
|
||||
|
||||
(
|
||||
/(
|
||||
\.eggs
|
||||
| \.git
|
||||
| \.hg
|
||||
| \.mypy_cache
|
||||
| \.tox
|
||||
| \.venv
|
||||
| _build
|
||||
| buck-out
|
||||
| build
|
||||
| dist
|
||||
)/
|
||||
| exceptions.py
|
||||
)
|
||||
'''
|
||||
[tool.poetry.urls]
|
||||
Changelog = "https://github.com/ProtoThis/python-synology/releases"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.7.0"
|
||||
requests = "^2.24.0"
|
||||
urllib3 = "^1.25.10"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = "^6.1.1"
|
||||
coverage = {extras = ["toml"], version = "^5.3"}
|
||||
safety = "^1.9.0"
|
||||
mypy = "^0.782"
|
||||
typeguard = "^2.9.1"
|
||||
xdoctest = {extras = ["colors"], version = "^0.15.0"}
|
||||
sphinx = "^3.2.1"
|
||||
sphinx-autobuild = "^2020.9.1"
|
||||
pre-commit = "^2.7.1"
|
||||
flake8 = "^3.8.4"
|
||||
black = "^20.8b1"
|
||||
flake8-bandit = "^2.1.2"
|
||||
flake8-bugbear = "^20.1.4"
|
||||
flake8-docstrings = "^1.5.0"
|
||||
flake8-rst-docstrings = "^0.0.14"
|
||||
pep8-naming = "^0.11.1"
|
||||
darglint = "^1.5.5"
|
||||
reorder-python-imports = "^2.3.5"
|
||||
pre-commit-hooks = "^3.2.0"
|
||||
sphinx-rtd-theme = "^0.5.0"
|
||||
Pygments = "^2.7.1"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
python-synology = "synology_dsm.__main__:main"
|
||||
|
||||
[tool.coverage.paths]
|
||||
source = ["src", "*/site-packages"]
|
||||
|
||||
[tool.coverage.run]
|
||||
branch = true
|
||||
source = ["synology_dsm"]
|
||||
|
||||
[tool.coverage.report]
|
||||
show_missing = true
|
||||
fail_under = 80
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry>=0.12"]
|
||||
build-backend = "poetry.masonry.api"
|
||||
|
@ -1,3 +0,0 @@
|
||||
requests>=2.24.0
|
||||
# Constrain urllib3 to ensure we deal with CVE-2019-11236 & CVE-2019-11324
|
||||
urllib3>=1.24.3
|
@ -1,2 +0,0 @@
|
||||
-r requirements.txt
|
||||
-r requirements_test.txt
|
@ -1,4 +0,0 @@
|
||||
pytest
|
||||
pylint>=2.6.0
|
||||
pylint-strict-informational==0.1
|
||||
black==20.8b1
|
@ -1,3 +0,0 @@
|
||||
[tool:pytest]
|
||||
testpaths = tests
|
||||
norecursedirs=.git .tox build lib
|
48
setup.py
48
setup.py
@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""Synology DSM setup."""
|
||||
|
||||
# NOTE(ProtoThis) Guidelines for Major.Minor.Micro
|
||||
# - Major means an API contract change
|
||||
# - Minor means API bugfix or new functionality
|
||||
# - Micro means change of any kind (unless significant enough for a minor/major).
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
REPO_URL = "https://github.com/ProtoThis/python-synology"
|
||||
VERSION = "1.0.0"
|
||||
|
||||
with open("requirements.txt") as f:
|
||||
required = f.read().splitlines()
|
||||
|
||||
with open("README.rst", encoding="utf-8") as f:
|
||||
long_description = f.read()
|
||||
|
||||
setup(
|
||||
name="python-synology",
|
||||
version=VERSION,
|
||||
url=REPO_URL,
|
||||
download_url=REPO_URL + "/tarball/" + VERSION,
|
||||
description="Python API for communication with Synology DSM",
|
||||
long_description=long_description,
|
||||
author="Quentin POLLET (Quentame) & FG van Zeelst (ProtoThis)",
|
||||
packages=find_packages("src"),
|
||||
package_dir={"": "src"},
|
||||
install_requires=required,
|
||||
python_requires=">=3.6",
|
||||
license="MIT",
|
||||
classifiers=[
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
],
|
||||
keywords=["synology-dsm", "synology"],
|
||||
)
|
@ -1,5 +1,4 @@
|
||||
"""DSM Storage data."""
|
||||
|
||||
from synology_dsm.helpers import SynoFormatHelper
|
||||
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
import urllib
|
||||
|
||||
from .camera import SynoCamera
|
||||
from .const import MOTION_DETECTION_BY_SURVEILLANCE, MOTION_DETECTION_DISABLED
|
||||
from .const import MOTION_DETECTION_BY_SURVEILLANCE
|
||||
from .const import MOTION_DETECTION_DISABLED
|
||||
|
||||
|
||||
class SynoSurveillanceStation:
|
||||
|
@ -1,5 +1,6 @@
|
||||
"""SurveillanceStation camera."""
|
||||
from .const import RECORDING_STATUS, MOTION_DETECTION_DISABLED
|
||||
from .const import MOTION_DETECTION_DISABLED
|
||||
from .const import RECORDING_STATUS
|
||||
|
||||
|
||||
class SynoCamera:
|
||||
|
@ -1,5 +1,4 @@
|
||||
"""Library constants."""
|
||||
|
||||
# APIs
|
||||
API_INFO = "SYNO.API.Info"
|
||||
API_AUTH = "SYNO.API.Auth"
|
||||
|
@ -1,8 +1,17 @@
|
||||
"""Library exceptions."""
|
||||
from .const import API_AUTH, ERROR_AUTH, ERROR_COMMON, ERROR_DOWNLOAD_SEARCH, ERROR_DOWNLOAD_TASK, ERROR_FILE, ERROR_SURVEILLANCE, ERROR_VIRTUALIZATION
|
||||
from .const import API_AUTH
|
||||
from .const import ERROR_AUTH
|
||||
from .const import ERROR_COMMON
|
||||
from .const import ERROR_DOWNLOAD_SEARCH
|
||||
from .const import ERROR_DOWNLOAD_TASK
|
||||
from .const import ERROR_FILE
|
||||
from .const import ERROR_SURVEILLANCE
|
||||
from .const import ERROR_VIRTUALIZATION
|
||||
|
||||
|
||||
class SynologyDSMException(Exception):
|
||||
"""Generic Synology DSM exception."""
|
||||
|
||||
def __init__(self, api, code, details=None):
|
||||
reason = ERROR_COMMON.get(code)
|
||||
if api and not reason:
|
||||
@ -25,9 +34,11 @@ class SynologyDSMException(Exception):
|
||||
error_message = {"api": api, "code": code, "reason": reason, "details": details}
|
||||
super().__init__(error_message)
|
||||
|
||||
|
||||
# Request
|
||||
class SynologyDSMRequestException(SynologyDSMException):
|
||||
"""Request exception."""
|
||||
|
||||
def __init__(self, exception):
|
||||
ex_class = exception.__class__.__name__
|
||||
ex_reason = exception.args[0]
|
||||
@ -35,26 +46,33 @@ class SynologyDSMRequestException(SynologyDSMException):
|
||||
ex_reason = exception.args[0].reason
|
||||
super().__init__(None, -1, f"{ex_class} = {ex_reason}")
|
||||
|
||||
|
||||
# API
|
||||
class SynologyDSMAPINotExistsException(SynologyDSMException):
|
||||
"""API not exists exception."""
|
||||
|
||||
def __init__(self, api):
|
||||
super().__init__(api, -2, f"API {api} does not exists")
|
||||
|
||||
|
||||
class SynologyDSMAPIErrorException(SynologyDSMException):
|
||||
"""API returns an error exception."""
|
||||
|
||||
def __init__(self, api, code, details):
|
||||
super().__init__(api, code, details)
|
||||
|
||||
|
||||
# Login
|
||||
class SynologyDSMLoginFailedException(SynologyDSMException):
|
||||
"""Failed to login exception."""
|
||||
|
||||
def __init__(self, code, details=None):
|
||||
super().__init__(API_AUTH, code, details)
|
||||
|
||||
|
||||
class SynologyDSMLoginInvalidException(SynologyDSMLoginFailedException):
|
||||
"""Invalid password & not admin account exception."""
|
||||
|
||||
def __init__(self, username):
|
||||
message = f"Invalid password or not admin account: {username}"
|
||||
super().__init__(400, message)
|
||||
@ -62,6 +80,7 @@ class SynologyDSMLoginInvalidException(SynologyDSMLoginFailedException):
|
||||
|
||||
class SynologyDSMLoginDisabledAccountException(SynologyDSMLoginFailedException):
|
||||
"""Guest & disabled account exception."""
|
||||
|
||||
def __init__(self, username):
|
||||
message = f"Guest or disabled account: {username}"
|
||||
super().__init__(401, message)
|
||||
@ -69,6 +88,7 @@ class SynologyDSMLoginDisabledAccountException(SynologyDSMLoginFailedException):
|
||||
|
||||
class SynologyDSMLoginPermissionDeniedException(SynologyDSMLoginFailedException):
|
||||
"""No access to login exception."""
|
||||
|
||||
def __init__(self, username):
|
||||
message = f"Permission denied for account: {username}"
|
||||
super().__init__(402, message)
|
||||
@ -76,6 +96,7 @@ class SynologyDSMLoginPermissionDeniedException(SynologyDSMLoginFailedException)
|
||||
|
||||
class SynologyDSMLogin2SARequiredException(SynologyDSMLoginFailedException):
|
||||
"""2SA required to login exception."""
|
||||
|
||||
def __init__(self, username):
|
||||
message = f"Two-step authentication required for account: {username}"
|
||||
super().__init__(403, message)
|
||||
@ -83,6 +104,7 @@ class SynologyDSMLogin2SARequiredException(SynologyDSMLoginFailedException):
|
||||
|
||||
class SynologyDSMLogin2SAFailedException(SynologyDSMLoginFailedException):
|
||||
"""2SA code failed exception."""
|
||||
|
||||
def __init__(self):
|
||||
message = "Two-step authentication failed, retry with a new pass code"
|
||||
super().__init__(404, message)
|
||||
|
@ -1,24 +1,12 @@
|
||||
"""Class to interact with Synology DSM."""
|
||||
import socket
|
||||
from json import JSONDecodeError
|
||||
from urllib.parse import quote
|
||||
import socket
|
||||
|
||||
import urllib3
|
||||
from requests import Session
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
from .exceptions import (
|
||||
SynologyDSMAPIErrorException,
|
||||
SynologyDSMAPINotExistsException,
|
||||
SynologyDSMRequestException,
|
||||
SynologyDSMLoginFailedException,
|
||||
SynologyDSMLoginInvalidException,
|
||||
SynologyDSMLoginDisabledAccountException,
|
||||
SynologyDSMLoginPermissionDeniedException,
|
||||
SynologyDSMLogin2SARequiredException,
|
||||
SynologyDSMLogin2SAFailedException,
|
||||
)
|
||||
|
||||
from .api.core.security import SynoCoreSecurity
|
||||
from .api.core.share import SynoCoreShare
|
||||
from .api.core.system import SynoCoreSystem
|
||||
@ -29,7 +17,17 @@ from .api.dsm.information import SynoDSMInformation
|
||||
from .api.dsm.network import SynoDSMNetwork
|
||||
from .api.storage.storage import SynoStorage
|
||||
from .api.surveillance_station import SynoSurveillanceStation
|
||||
from .const import API_AUTH, API_INFO
|
||||
from .const import API_AUTH
|
||||
from .const import API_INFO
|
||||
from .exceptions import SynologyDSMAPIErrorException
|
||||
from .exceptions import SynologyDSMAPINotExistsException
|
||||
from .exceptions import SynologyDSMLogin2SAFailedException
|
||||
from .exceptions import SynologyDSMLogin2SARequiredException
|
||||
from .exceptions import SynologyDSMLoginDisabledAccountException
|
||||
from .exceptions import SynologyDSMLoginFailedException
|
||||
from .exceptions import SynologyDSMLoginInvalidException
|
||||
from .exceptions import SynologyDSMLoginPermissionDeniedException
|
||||
from .exceptions import SynologyDSMRequestException
|
||||
|
||||
|
||||
class SynologyDSM:
|
||||
@ -204,7 +202,7 @@ class SynologyDSM:
|
||||
method: str,
|
||||
params: dict = None,
|
||||
retry_once: bool = True,
|
||||
**kwargs
|
||||
**kwargs,
|
||||
):
|
||||
"""Handles API request."""
|
||||
# Discover existing APIs
|
||||
|
@ -2,69 +2,67 @@
|
||||
from json import JSONDecodeError
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from requests.exceptions import ConnectionError as ConnError, RequestException, SSLError
|
||||
from requests.exceptions import ConnectionError as ConnError
|
||||
from requests.exceptions import RequestException
|
||||
from requests.exceptions import SSLError
|
||||
|
||||
from .api_data.dsm_5 import DSM_5_API_INFO
|
||||
from .api_data.dsm_5 import DSM_5_AUTH_LOGIN
|
||||
from .api_data.dsm_5 import DSM_5_AUTH_LOGIN_2SA
|
||||
from .api_data.dsm_5 import DSM_5_AUTH_LOGIN_2SA_OTP
|
||||
from .api_data.dsm_5 import DSM_5_CORE_UTILIZATION
|
||||
from .api_data.dsm_5 import DSM_5_DSM_INFORMATION
|
||||
from .api_data.dsm_5 import DSM_5_DSM_NETWORK
|
||||
from .api_data.dsm_5 import DSM_5_STORAGE_STORAGE_DS410J_RAID5_4DISKS_1VOL
|
||||
from .api_data.dsm_6 import DSM_6_API_INFO
|
||||
from .api_data.dsm_6 import DSM_6_API_INFO_SURVEILLANCE_STATION
|
||||
from .api_data.dsm_6 import DSM_6_AUTH_LOGIN
|
||||
from .api_data.dsm_6 import DSM_6_AUTH_LOGIN_2SA
|
||||
from .api_data.dsm_6 import DSM_6_AUTH_LOGIN_2SA_OTP
|
||||
from .api_data.dsm_6 import DSM_6_CORE_SECURITY
|
||||
from .api_data.dsm_6 import DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE
|
||||
from .api_data.dsm_6 import DSM_6_CORE_SHARE
|
||||
from .api_data.dsm_6 import DSM_6_CORE_SYSTEM_DS918_PLUS
|
||||
from .api_data.dsm_6 import DSM_6_CORE_UPGRADE
|
||||
from .api_data.dsm_6 import DSM_6_CORE_UTILIZATION
|
||||
from .api_data.dsm_6 import DSM_6_CORE_UTILIZATION_ERROR_1055
|
||||
from .api_data.dsm_6 import DSM_6_DOWNLOAD_STATION_INFO_CONFIG
|
||||
from .api_data.dsm_6 import DSM_6_DOWNLOAD_STATION_INFO_INFO
|
||||
from .api_data.dsm_6 import DSM_6_DOWNLOAD_STATION_STAT_INFO
|
||||
from .api_data.dsm_6 import DSM_6_DOWNLOAD_STATION_TASK_LIST
|
||||
from .api_data.dsm_6 import DSM_6_DSM_INFORMATION
|
||||
from .api_data.dsm_6 import DSM_6_DSM_NETWORK
|
||||
from .api_data.dsm_6 import (
|
||||
DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION,
|
||||
)
|
||||
from .api_data.dsm_6 import DSM_6_STORAGE_STORAGE_DS1819_PLUS_SHR2_8DISKS_1VOL
|
||||
from .api_data.dsm_6 import DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS
|
||||
from .api_data.dsm_6 import DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL
|
||||
from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MD_PARAM_SAVE
|
||||
from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MOTION_ENUM
|
||||
from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_CAMERA_GET_LIVE_VIEW_PATH
|
||||
from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_CAMERA_LIST
|
||||
from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_HOME_MODE_GET_INFO
|
||||
from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_HOME_MODE_SWITCH
|
||||
from .const import DEVICE_TOKEN
|
||||
from .const import ERROR_AUTH_INVALID_CREDENTIALS
|
||||
from .const import ERROR_AUTH_MAX_TRIES
|
||||
from .const import ERROR_AUTH_OTP_AUTHENTICATE_FAILED
|
||||
from .const import ERROR_INSUFFICIENT_USER_PRIVILEGE
|
||||
from synology_dsm import SynologyDSM
|
||||
from synology_dsm.exceptions import SynologyDSMRequestException
|
||||
from synology_dsm.api.core.security import SynoCoreSecurity
|
||||
from synology_dsm.api.core.share import SynoCoreShare
|
||||
from synology_dsm.api.core.system import SynoCoreSystem
|
||||
from synology_dsm.api.core.utilization import SynoCoreUtilization
|
||||
from synology_dsm.api.core.upgrade import SynoCoreUpgrade
|
||||
from synology_dsm.api.core.utilization import SynoCoreUtilization
|
||||
from synology_dsm.api.download_station import SynoDownloadStation
|
||||
from synology_dsm.api.dsm.information import SynoDSMInformation
|
||||
from synology_dsm.api.dsm.network import SynoDSMNetwork
|
||||
from synology_dsm.api.download_station import SynoDownloadStation
|
||||
from synology_dsm.api.storage.storage import SynoStorage
|
||||
from synology_dsm.api.surveillance_station import SynoSurveillanceStation
|
||||
from synology_dsm.const import API_AUTH, API_INFO
|
||||
|
||||
from .const import (
|
||||
ERROR_INSUFFICIENT_USER_PRIVILEGE,
|
||||
ERROR_AUTH_INVALID_CREDENTIALS,
|
||||
ERROR_AUTH_MAX_TRIES,
|
||||
ERROR_AUTH_OTP_AUTHENTICATE_FAILED,
|
||||
DEVICE_TOKEN,
|
||||
)
|
||||
from .api_data.dsm_6 import (
|
||||
DSM_6_API_INFO,
|
||||
DSM_6_AUTH_LOGIN,
|
||||
DSM_6_AUTH_LOGIN_2SA,
|
||||
DSM_6_AUTH_LOGIN_2SA_OTP,
|
||||
DSM_6_DSM_INFORMATION,
|
||||
DSM_6_DSM_NETWORK,
|
||||
DSM_6_CORE_UTILIZATION,
|
||||
DSM_6_CORE_UTILIZATION_ERROR_1055,
|
||||
DSM_6_CORE_SECURITY,
|
||||
DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE,
|
||||
DSM_6_CORE_SYSTEM_DS918_PLUS,
|
||||
DSM_6_CORE_UPGRADE,
|
||||
DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS,
|
||||
DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL,
|
||||
DSM_6_STORAGE_STORAGE_DS1819_PLUS_SHR2_8DISKS_1VOL,
|
||||
DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION,
|
||||
DSM_6_CORE_SHARE,
|
||||
DSM_6_API_INFO_SURVEILLANCE_STATION,
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MOTION_ENUM,
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_GET_LIVE_VIEW_PATH,
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MD_PARAM_SAVE,
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_LIST,
|
||||
DSM_6_SURVEILLANCE_STATION_HOME_MODE_GET_INFO,
|
||||
DSM_6_SURVEILLANCE_STATION_HOME_MODE_SWITCH,
|
||||
DSM_6_DOWNLOAD_STATION_INFO_INFO,
|
||||
DSM_6_DOWNLOAD_STATION_INFO_CONFIG,
|
||||
DSM_6_DOWNLOAD_STATION_STAT_INFO,
|
||||
DSM_6_DOWNLOAD_STATION_TASK_LIST,
|
||||
)
|
||||
from .api_data.dsm_5 import (
|
||||
DSM_5_API_INFO,
|
||||
DSM_5_AUTH_LOGIN,
|
||||
DSM_5_AUTH_LOGIN_2SA,
|
||||
DSM_5_AUTH_LOGIN_2SA_OTP,
|
||||
DSM_5_DSM_NETWORK,
|
||||
DSM_5_DSM_INFORMATION,
|
||||
DSM_5_CORE_UTILIZATION,
|
||||
DSM_5_STORAGE_STORAGE_DS410J_RAID5_4DISKS_1VOL,
|
||||
)
|
||||
from synology_dsm.const import API_AUTH
|
||||
from synology_dsm.const import API_INFO
|
||||
from synology_dsm.exceptions import SynologyDSMRequestException
|
||||
|
||||
API_SWITCHER = {
|
||||
5: {
|
||||
|
@ -1,10 +1,8 @@
|
||||
"""DSM 5 datas."""
|
||||
from .const_5_api_auth import DSM_5_AUTH_LOGIN
|
||||
from .const_5_api_auth import DSM_5_AUTH_LOGIN_2SA
|
||||
from .const_5_api_auth import DSM_5_AUTH_LOGIN_2SA_OTP
|
||||
from .const_5_api_info import DSM_5_API_INFO
|
||||
from .const_5_api_auth import (
|
||||
DSM_5_AUTH_LOGIN,
|
||||
DSM_5_AUTH_LOGIN_2SA,
|
||||
DSM_5_AUTH_LOGIN_2SA_OTP,
|
||||
)
|
||||
from .core.const_5_core_utilization import DSM_5_CORE_UTILIZATION
|
||||
from .dsm.const_5_dsm_info import DSM_5_DSM_INFORMATION
|
||||
from .dsm.const_5_dsm_network import DSM_5_DSM_NETWORK
|
||||
|
@ -1,9 +1,7 @@
|
||||
"""DSM 5 SYNO.API.Auth data."""
|
||||
from tests.const import (
|
||||
SESSION_ID,
|
||||
DEVICE_TOKEN,
|
||||
ERROR_AUTH_OTP_NOT_SPECIFIED,
|
||||
)
|
||||
from tests.const import DEVICE_TOKEN
|
||||
from tests.const import ERROR_AUTH_OTP_NOT_SPECIFIED
|
||||
from tests.const import SESSION_ID
|
||||
|
||||
# No synotoken for an unknown reason
|
||||
DSM_5_AUTH_LOGIN = {
|
||||
|
@ -1,26 +1,21 @@
|
||||
"""DSM 6 datas."""
|
||||
from .const_6_api_auth import DSM_6_AUTH_LOGIN
|
||||
from .const_6_api_auth import DSM_6_AUTH_LOGIN_2SA
|
||||
from .const_6_api_auth import DSM_6_AUTH_LOGIN_2SA_OTP
|
||||
from .const_6_api_info import DSM_6_API_INFO
|
||||
from .const_6_api_auth import (
|
||||
DSM_6_AUTH_LOGIN,
|
||||
DSM_6_AUTH_LOGIN_2SA,
|
||||
DSM_6_AUTH_LOGIN_2SA_OTP,
|
||||
)
|
||||
from .core.const_6_core_utilization import (
|
||||
DSM_6_CORE_UTILIZATION,
|
||||
DSM_6_CORE_UTILIZATION_ERROR_1055,
|
||||
)
|
||||
from .core.const_6_core_security import (
|
||||
DSM_6_CORE_SECURITY,
|
||||
DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE,
|
||||
)
|
||||
from .core.const_6_core_system import (
|
||||
DSM_6_CORE_SYSTEM_DS918_PLUS,
|
||||
DSM_6_CORE_SYSTEM_DS218_PLAY,
|
||||
)
|
||||
from .core.const_6_core_security import DSM_6_CORE_SECURITY
|
||||
from .core.const_6_core_security import DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE
|
||||
from .core.const_6_core_share import DSM_6_CORE_SHARE
|
||||
from .core.const_6_core_system import DSM_6_CORE_SYSTEM_DS218_PLAY
|
||||
from .core.const_6_core_system import DSM_6_CORE_SYSTEM_DS918_PLUS
|
||||
from .core.const_6_core_upgrade import DSM_6_CORE_UPGRADE
|
||||
from .core.const_6_core_utilization import DSM_6_CORE_UTILIZATION
|
||||
from .core.const_6_core_utilization import DSM_6_CORE_UTILIZATION_ERROR_1055
|
||||
from .download_station.const_6_download_station_info import (
|
||||
DSM_6_DOWNLOAD_STATION_INFO_CONFIG,
|
||||
)
|
||||
from .download_station.const_6_download_station_info import (
|
||||
DSM_6_DOWNLOAD_STATION_INFO_INFO,
|
||||
DSM_6_DOWNLOAD_STATION_INFO_CONFIG,
|
||||
)
|
||||
from .download_station.const_6_download_station_stat import (
|
||||
DSM_6_DOWNLOAD_STATION_STAT_INFO,
|
||||
@ -31,22 +26,35 @@ from .download_station.const_6_download_station_task import (
|
||||
from .dsm.const_6_dsm_info import DSM_6_DSM_INFORMATION
|
||||
from .dsm.const_6_dsm_network import DSM_6_DSM_NETWORK
|
||||
from .storage.const_6_storage_storage import (
|
||||
DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS,
|
||||
DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL,
|
||||
DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION,
|
||||
)
|
||||
from .storage.const_6_storage_storage import (
|
||||
DSM_6_STORAGE_STORAGE_DS1819_PLUS_SHR2_8DISKS_1VOL,
|
||||
)
|
||||
from .storage.const_6_storage_storage import (
|
||||
DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS,
|
||||
)
|
||||
from .storage.const_6_storage_storage import (
|
||||
DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL,
|
||||
)
|
||||
from .surveillance_station.const_6_api_info import (
|
||||
DSM_6_API_INFO as DSM_6_API_INFO_SURVEILLANCE_STATION,
|
||||
)
|
||||
from .surveillance_station.const_6_surveillance_station_camera import (
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_LIST,
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_GET_LIVE_VIEW_PATH,
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MOTION_ENUM,
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MD_PARAM_SAVE,
|
||||
)
|
||||
from .core.const_6_core_share import DSM_6_CORE_SHARE
|
||||
from .surveillance_station.const_6_surveillance_station_camera import (
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MOTION_ENUM,
|
||||
)
|
||||
from .surveillance_station.const_6_surveillance_station_camera import (
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_GET_LIVE_VIEW_PATH,
|
||||
)
|
||||
from .surveillance_station.const_6_surveillance_station_camera import (
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_LIST,
|
||||
)
|
||||
from .surveillance_station.const_6_surveillance_station_home_mode import (
|
||||
DSM_6_SURVEILLANCE_STATION_HOME_MODE_GET_INFO,
|
||||
)
|
||||
from .surveillance_station.const_6_surveillance_station_home_mode import (
|
||||
DSM_6_SURVEILLANCE_STATION_HOME_MODE_SWITCH,
|
||||
)
|
||||
|
@ -1,10 +1,8 @@
|
||||
"""DSM 6 SYNO.API.Auth data."""
|
||||
from tests.const import (
|
||||
SESSION_ID,
|
||||
DEVICE_TOKEN,
|
||||
SYNO_TOKEN,
|
||||
ERROR_AUTH_OTP_NOT_SPECIFIED,
|
||||
)
|
||||
from tests.const import DEVICE_TOKEN
|
||||
from tests.const import ERROR_AUTH_OTP_NOT_SPECIFIED
|
||||
from tests.const import SESSION_ID
|
||||
from tests.const import SYNO_TOKEN
|
||||
|
||||
|
||||
DSM_6_AUTH_LOGIN = {
|
||||
|
@ -1,5 +1,4 @@
|
||||
"""Test constants."""
|
||||
|
||||
# API test data are localized in
|
||||
# `tests/api_data/dsm_[dsm_major_version]`
|
||||
# Data constant names should be like :
|
||||
|
@ -1,33 +1,32 @@
|
||||
"""Synology DSM tests."""
|
||||
from unittest import TestCase
|
||||
|
||||
import pytest
|
||||
|
||||
from . import SynologyDSMMock
|
||||
from . import USER_MAX_TRY
|
||||
from . import VALID_HOST
|
||||
from . import VALID_HTTPS
|
||||
from . import VALID_OTP
|
||||
from . import VALID_PASSWORD
|
||||
from . import VALID_PORT
|
||||
from . import VALID_USER
|
||||
from . import VALID_USER_2SA
|
||||
from . import VALID_VERIFY_SSL
|
||||
from .const import DEVICE_TOKEN
|
||||
from .const import SESSION_ID
|
||||
from .const import SYNO_TOKEN
|
||||
from synology_dsm.api.core.security import SynoCoreSecurity
|
||||
from synology_dsm.api.dsm.information import SynoDSMInformation
|
||||
from synology_dsm.exceptions import (
|
||||
SynologyDSMRequestException,
|
||||
SynologyDSMAPINotExistsException,
|
||||
SynologyDSMAPIErrorException,
|
||||
SynologyDSMLoginInvalidException,
|
||||
SynologyDSMLogin2SARequiredException,
|
||||
SynologyDSMLogin2SAFailedException,
|
||||
SynologyDSMLoginFailedException,
|
||||
)
|
||||
from synology_dsm.const import API_AUTH, API_INFO
|
||||
|
||||
from . import (
|
||||
SynologyDSMMock,
|
||||
VALID_HOST,
|
||||
VALID_PORT,
|
||||
VALID_HTTPS,
|
||||
VALID_VERIFY_SSL,
|
||||
VALID_OTP,
|
||||
VALID_PASSWORD,
|
||||
VALID_USER,
|
||||
VALID_USER_2SA,
|
||||
USER_MAX_TRY,
|
||||
)
|
||||
from .const import SESSION_ID, DEVICE_TOKEN, SYNO_TOKEN
|
||||
from synology_dsm.const import API_AUTH
|
||||
from synology_dsm.const import API_INFO
|
||||
from synology_dsm.exceptions import SynologyDSMAPIErrorException
|
||||
from synology_dsm.exceptions import SynologyDSMAPINotExistsException
|
||||
from synology_dsm.exceptions import SynologyDSMLogin2SAFailedException
|
||||
from synology_dsm.exceptions import SynologyDSMLogin2SARequiredException
|
||||
from synology_dsm.exceptions import SynologyDSMLoginFailedException
|
||||
from synology_dsm.exceptions import SynologyDSMLoginInvalidException
|
||||
from synology_dsm.exceptions import SynologyDSMRequestException
|
||||
|
||||
# pylint: disable=no-self-use,protected-access
|
||||
|
||||
|
@ -1,28 +1,25 @@
|
||||
"""Synology DSM tests."""
|
||||
from unittest import TestCase
|
||||
|
||||
from synology_dsm.exceptions import (
|
||||
SynologyDSMRequestException,
|
||||
SynologyDSMAPINotExistsException,
|
||||
SynologyDSMAPIErrorException,
|
||||
SynologyDSMLoginInvalidException,
|
||||
SynologyDSMLogin2SARequiredException,
|
||||
SynologyDSMLogin2SAFailedException,
|
||||
)
|
||||
from synology_dsm.const import API_AUTH, API_INFO
|
||||
|
||||
from . import (
|
||||
SynologyDSMMock,
|
||||
VALID_HOST,
|
||||
VALID_PORT,
|
||||
VALID_HTTPS,
|
||||
VALID_VERIFY_SSL,
|
||||
VALID_OTP,
|
||||
VALID_PASSWORD,
|
||||
VALID_USER,
|
||||
VALID_USER_2SA,
|
||||
)
|
||||
from .const import SESSION_ID, DEVICE_TOKEN
|
||||
from . import SynologyDSMMock
|
||||
from . import VALID_HOST
|
||||
from . import VALID_HTTPS
|
||||
from . import VALID_OTP
|
||||
from . import VALID_PASSWORD
|
||||
from . import VALID_PORT
|
||||
from . import VALID_USER
|
||||
from . import VALID_USER_2SA
|
||||
from . import VALID_VERIFY_SSL
|
||||
from .const import DEVICE_TOKEN
|
||||
from .const import SESSION_ID
|
||||
from synology_dsm.const import API_AUTH
|
||||
from synology_dsm.const import API_INFO
|
||||
from synology_dsm.exceptions import SynologyDSMAPIErrorException
|
||||
from synology_dsm.exceptions import SynologyDSMAPINotExistsException
|
||||
from synology_dsm.exceptions import SynologyDSMLogin2SAFailedException
|
||||
from synology_dsm.exceptions import SynologyDSMLogin2SARequiredException
|
||||
from synology_dsm.exceptions import SynologyDSMLoginInvalidException
|
||||
from synology_dsm.exceptions import SynologyDSMRequestException
|
||||
|
||||
# pylint: disable=no-self-use,protected-access,anomalous-backslash-in-string
|
||||
class TestSynologyDSM(TestCase):
|
||||
|
Reference in New Issue
Block a user