diff --git a/docs/api.rst b/docs/api.rst index 1553300..877cded 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -31,7 +31,7 @@ ZFS .. autofunction:: simplezfs.zfs.get_zfs -.. autoclass:: simplezfs.ZFS +.. autoclass:: simplezfs.zfs.ZFS :members: ZPool @@ -39,7 +39,7 @@ ZPool .. autofunction:: simplezfs.zpool.get_zpool -.. autoclass:: simplezfs.ZPool +.. autoclass:: simplezfs.zpool.ZPool :members: Implementations diff --git a/docs/conf.py b/docs/conf.py index ba3cb1f..fade3ba 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,7 +2,7 @@ # # This file only contains a selection of the most common options. For a full # list see the documentation: -# http://www.sphinx-doc.org/en/master/config +# https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Path setup -------------------------------------------------------------- @@ -18,7 +18,7 @@ # -- Project information ----------------------------------------------------- project = 'Python-SimpleZFS' -copyright = '2019, Andreas Gonschorek, Stefan Valouch' +copyright = '2019-2020, Andreas Gonschorek, Stefan Valouch' author = 'Andreas Gonschorek, Stefan Valouch' # The full version, including alpha/beta/rc tags @@ -32,6 +32,7 @@ release = '0.0.1' # ones. extensions = [ 'sphinx.ext.autodoc', + 'sphinx.ext.todo', 'sphinx_autodoc_typehints', ] @@ -49,9 +50,15 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +import sphinx_rtd_theme +html_theme = 'sphinx_rtd_theme' # 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'] + +# -- Options for todo extension ---------------------------------------------- + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True diff --git a/docs/configuration.rst b/docs/configuration.rst index b1b3cbf..d1a9452 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -21,12 +21,12 @@ The library makes use of Pythons own `logging` functions. It defines a tree star * ``simplezfs`` (used as a common root only) - * ``simplezfs.zfs`` used by the :class:`~simplezfs.ZFS` parent class + * ``simplezfs.zfs`` used by the :class:`~simplezfs.zfs.ZFS` parent class * ``simplezfs.zfs.cli`` used by :class:`~simplezfs.zfs_cli.ZFSCli` * ``simplezfs.zfs.native`` used by :class:`~simplezfs.zfs_native.ZFSNative` - * ``simplezfs.zpool`` used by the :class:`~simplezfs.ZPool` parent class + * ``simplezfs.zpool`` used by the :class:`~simplezfs.zpool.ZPool` parent class * ``simplezfs.zpool.cli`` used by :class:`~simplezfs.zpool_cli.ZPoolCli` * ``simplezfs.zpool.native`` used by :class:`~simplezfs.zpool_native.ZPoolNative` diff --git a/docs/guide.rst b/docs/guide.rst index 7ebfd90..0016934 100644 --- a/docs/guide.rst +++ b/docs/guide.rst @@ -1,6 +1,6 @@ -################### -Guide to python-zfs -################### +######################### +Guide to python-simplezfs +######################### Overview ******** @@ -12,8 +12,9 @@ collect actions and run them at the end, each action is carried out immediately. There are, however, two implementations of the functionality, using the ``cli`` tools and another one using the `libzfs_core` ``native`` library. We'll focus on the ``cli`` version here. -Most of the functions raise a :class:`:: simplezfs.simplezfs.exceptions.ValidationError` with some helpful text if any of the data turns -out not to be valid. For example, including invalid or reserved strings in the dataset name raises this exception. +Most of the functions raise a :class:`simplezfs.exceptions.ValidationError` with some helpful text if any of the data +turns out not to be valid. For example, including invalid or reserved strings in the dataset name raises this +exception. Let's take a look at the two interfaces **ZFS** and **ZPool**... @@ -25,8 +26,8 @@ Let's take a look at the two interfaces **ZFS** and **ZPool**... The ZFS interface ***************** -The :class:`:: simplezfs.simplezfs.zfs.ZFS` is the interface that corresponds to the ``zfs(8)`` program. It holds very little state, -and it is recommended to get an instance through the function :func:`~zfs.zfs.get_zfs`. It selects the desired +The :class:`simplezfs.zfs.ZFS` is the interface that corresponds to the ``zfs(8)`` program. It holds very little state, +and it is recommended to get an instance through the function :func:`~simplezfs.zfs.get_zfs`. It selects the desired implementation and passes the required parameters. At the very least, it requires the ``api``-parameter, which is a string that selects the actual implementation, either ``cli`` or ``native``. @@ -40,12 +41,12 @@ All our examples use the ``cli`` implementation for simplicity. For the remainder of this guide, we're going to assume that the variable ``zfs`` always holds a -:class:`:: simplezfs.simplezfs.zfs_cli.ZFSCli` object. +:class:`simplezfs.zfs_cli.ZFSCli` object. Viewing data ============ To get an overview over the interface, we'll dive in and inspect our running system. Information is returned in the -form if :class:`:: simplezfs.simplezfs.types.Dataset` instances, which is a named tuple containing a set of fields. For simplicity, +form if :class:`simplezfs.types.Dataset` instances, which is a named tuple containing a set of fields. For simplicity, we'll output only a few of its fields to not clobber the screen, so don't be alarmed if there seems to be information missing: we just omitted the boring parts. @@ -85,15 +86,15 @@ Creating something new There are functions for creating the four different types of datasets with nice interfaces: -* :func:`~zfs.ZFS.create_fileset` for ordinary filesets, the most commonly used parameter is ``mountpoint`` for - telling it where it should be mounted. -* :func:`~zfs.ZFS.create_volume` creates volumes, or ZVols, this features a parameter ``thin`` for creating thin- - provisioned or sparse volumes. -* :func:`~zfs.ZFS.create_snapshot` creates a snapshot on a volume or fileset. -* :func:`~zfs.ZFS.create_bookmark` creates a bookmark (on recent versions of ZFS). +* :func:`~simplezfs.zfs.ZFS.create_fileset` for ordinary filesets, the most commonly used parameter is ``mountpoint`` + for telling it where it should be mounted. +* :func:`~simplezfs.zfs.ZFS.create_volume` creates volumes, or ZVols, this features a parameter ``thin`` for creating + thin-provisioned or sparse volumes. +* :func:`~simplezfs.zfs.ZFS.create_snapshot` creates a snapshot on a volume or fileset. +* :func:`~simplezfs.zfs.ZFS.create_bookmark` creates a bookmark (on recent versions of ZFS). -These essentially call :func:`~zfs.ZFS.create_dataset`, which can be called directly, but its interface is not as -nice as the special purpose create functions. +These essentially call :func:`~simplezfs.zfs.ZFS.create_dataset`, which can be called directly, but its interface is +not as nice as the special purpose create functions. Filesets @@ -187,16 +188,16 @@ overwritten when working with the get and set functions. It is also possible not it to the functions every time. When you want to get or set a metadata property, set ``metadata`` to **True** when calling -:func:`~zfs.ZFS.get_property` or :func:`~zfs.ZFS.set_property`. This will cause it to automatically prepend the -namespace given on instantiation or to prepend the one given in the ``overwrite_metadata_namespace`` when calling the -functions. The name of the property **must not** include the namespace, though it may contain ``:`` characters on its -own, properties of the form ``zfs:is:cool`` are valid afterall. ``:`` characters are never valid in the context of -native properties, and this is the reason why there is a separate switch to turn on metadata properties when using -these functions. +:func:`~simplezfs.zfs.ZFS.get_property` or :func:`~simplezfs.zfs.ZFS.set_property`. This will cause it to automatically +prepend the namespace given on instantiation or to prepend the one given in the ``overwrite_metadata_namespace`` when +calling the functions. The name of the property **must not** include the namespace, though it may contain ``:`` +characters on its own, properties of the form ``zfs:is:cool`` are valid afterall. ``:`` characters are never valid in +the context of native properties, and this is the reason why there is a separate switch to turn on metadata properties +when using these functions. Error handling -------------- -If a property name is not valid or the value exceeds certain bounds, a :class:`:: simplezfs.simplezfs.exceptions.ValidationError` is +If a property name is not valid or the value exceeds certain bounds, a :class:`simplezfs.exceptions.ValidationError` is raised. This includes specifying a namespace in the property name if ``metadata`` is **False**, or exceeding the length allowed for a metadata property (8192 - 1 bytes). @@ -222,8 +223,8 @@ namespace, it looks like this: >>> zfs.get_property('tank/system/root', 'do_backup', metdata=True) Property(key='do_backup', value='true', source='local', namespace='com.company') -If you don't specify a namespace when calling :func:`~zfs.zfs.get_zfs` or if you want to use a different namespace for -one call, specify the desired namespace in ``overwrite_metadata_namespace`` like so: +If you don't specify a namespace when calling :func:`~simplezfs.zfs.get_zfs` or if you want to use a different +namespace for one call, specify the desired namespace in ``overwrite_metadata_namespace`` like so: .. code-block:: pycon @@ -264,10 +265,10 @@ Listing properties The ZPool interface ******************* -The :class:`:: simplezfs.simplezfs.zfs.ZPool` is the interface that corresponds to the ``zpool(8)`` program. It holds very little state, -and it is recommended to get an instance through the function :func:`~simplezfs.zpool.get_zpool`. It selects the desired -implementation and passes the required parameters. At the very least, it requires the ``api``-parameter, which is a -string that selects the actual implementation, either ``cli`` or ``native``. +The :class:`simplezfs.zfs.ZPool` is the interface that corresponds to the ``zpool(8)`` program. It holds very little +state, and it is recommended to get an instance through the function :func:`~simplezfs.zpool.get_zpool`. It selects the +desired implementation and passes the required parameters. At the very least, it requires the ``api``-parameter, which +is a string that selects the actual implementation, either ``cli`` or ``native``. All our examples use the ``cli`` implementation for simplicity. @@ -279,21 +280,21 @@ All our examples use the ``cli`` implementation for simplicity. For the remainder of this guide, we're going to assume that the variable ``zpool`` always holds a -:class:`:: simplezfs.simplezfs.zpool_cli.ZPoolCli` object. +:class:`simplezfs.zpool_cli.ZPoolCli` object. Error handling ************** We kept the most important part for last: handling errors. The module defines its own hierarchy with -:class:`:: simplezfs.simplezfs.exceptions.ZFSError` as toplevel exception. Various specific exceptions are based on ot. When working -with :class:`:: simplezfs.simplezfs.zfs.ZFS`, the three most common ones are: - -* :class:`:: simplezfs.simplezfs.exceptions.ValidationError` which indicates that a name (e.g. dataset name) was invalid. -* :class:`:: simplezfs.simplezfs.exceptions.DatasetNotFound` is, like FileNotFound in standard python, indicating that the dataset the - module was instructed to work on (e.g. get/set properties, destroy) was not present. -* :class:`:: simplezfs.simplezfs.exceptions.PermissionError` is raised when the current users permissions are not sufficient to perform - the requested operation. While some actions can be delegated using ``zfs allow``, linux, for example, doesn't allow - non-root users to mount filesystems, which means that a non-root user may create filesets with a valid mountpoint - property, but it won't be mounted. +:class:`simplezfs.exceptions.ZFSException` as toplevel exception. Various specific exceptions are based on ot. When +working with :class:`simplezfs.zfs.ZFS`, the three most common ones are: + +* :class:`simplezfs.exceptions.ValidationError` which indicates that a name (e.g. dataset name) was invalid. +* :class:`simplezfs.exceptions.DatasetNotFound` is, like FileNotFound in standard python, indicating that the dataset + the module was instructed to work on (e.g. get/set properties, destroy) was not present. +* :class:`simplezfs.exceptions.PermissionError` is raised when the current users permissions are not sufficient to + perform the requested operation. While some actions can be delegated using ``zfs allow``, linux, for example, doesn't + allow non-root users to mount filesystems, which means that a non-root user may create filesets with a valid + mountpoint property, but it won't be mounted. Examples ======== diff --git a/docs/requirements.txt b/docs/requirements.txt index dd45356..0708084 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,3 @@ Sphinx>=2.0 sphinx-autodoc-typehints +sphinx-rtd-theme diff --git a/setup.py b/setup.py index d2411c4..84bceaf 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ - -from setuptools import setup +# -*- coding: utf-8 -*- +from setuptools import setup # type: ignore with open('README.rst', 'r') as fh: long_description = fh.read() @@ -10,28 +10,34 @@ setup( author='Andreas Gonschorek, Stefan Valouch', description='Simple, low-level ZFS API', long_description=long_description, + project_urls={ + 'Documentation': 'https://simplezfs.readthedocs.io/', + 'Source': 'https://github.com/svalouch/python-simplezfs/', + 'Tracker': 'https://github.com/svalouch/python-simplezfs/issues', + }, packages=['simplezfs'], package_data={'simplezfs': ['py.typed']}, package_dir={'': 'src'}, include_package_data=True, zip_safe=False, license='BSD-3-Clause', - url='https://github.com/svalouch/python-simplezfs', platforms='any', python_requires='>=3.6', - install_requires=[ - 'pydantic>=0.32.2', - ], + # install_requires=[ + # ], extras_require={ 'tests': [ + 'flake8', 'mypy', 'pytest', 'pytest-cov', ], 'docs': [ 'Sphinx>=2.0', + 'sphinx-autodoc-typehints', + 'sphinx-rtd-theme', ], }, @@ -41,7 +47,9 @@ setup( 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', ], ) diff --git a/src/simplezfs/zfs.py b/src/simplezfs/zfs.py index 6f3a4c8..fb0856d 100644 --- a/src/simplezfs/zfs.py +++ b/src/simplezfs/zfs.py @@ -28,24 +28,26 @@ log = logging.getLogger('simplezfs.zfs') class ZFS: ''' - ZFS interface class. This API generally covers only the zfs(8) tool, for zpool(8) please see :class:`~ZPool`. + ZFS interface class. This API generally covers only the zfs(8) tool, for zpool(8) please see + :class:`~simplezfs.zpool.ZPool`. **ZFS implementation** There are two ways how the API actually communicates with the ZFS filesystem: - * Using the CLI tools (:class:`~zfs.zfs_cli.ZFSCli`) - * Using the native API (:class:`~zfs.zfs_native.ZFSNative`) + * Using the CLI tools (:class:`~simplezfs.zfs_cli.ZFSCli`) + * Using the native API (:class:`~simplezfs.zfs_native.ZFSNative`) - You can select the API by either creating an instance of one of them or using :func:`~zfs.zfs.get_zfs`. + You can select the API by either creating an instance of one of them or using :func:`~simplezfs.zfs.get_zfs`. **Properties and Metadata** - The functions :func:`set_property`, :func:`get_property` and :func:`get_properties` wrap the ZFS get/set - functionality. To support so-called `user properties`, which are called `metadata` in this API, a default namespace - can be stored using `metadata_namespace` when instantiating the interface or by calling - :func:`set_metadata_namespace` at any time. + The functions :func:`~simplezfs.zfs.ZFS.set_property`, :func:`~simplezfs.zfs.ZFS.get_property` and + :func:`~simplezfs.zfs.ZFS.get_properties` wrap the ZFS get/set functionality. To support so-called + `user properties`, which are called `metadata` in this API, a default namespace can be stored using + `metadata_namespace` when instantiating the interface or by calling + :func:`~simplezfs.zfs.ZFS.set_metadata_namespace` at any time. :note: Not setting a metadata namespace means that one can't set or get metadata properties, unless the overwrite parameter for the get/set functions is used.