Skip to content

Commit

Permalink
Nano-Utils 0.4.1 (#9)
Browse files Browse the repository at this point in the history
* Minor documentation fixes.
* Added the ``ignore_if()`` decorator.
  • Loading branch information
BvB93 authored Jun 6, 2020
1 parent 6f8decb commit 132576c
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 54 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file.
This project adheres to `Semantic Versioning <http://semver.org/>`_.


0.4.1
*****
* Minor documentation fixes.
* Added the ``ignore_if()`` decorator.


0.4.0
*****
* Added the ``AbstractFileContainer`` class and ``file_to_context()`` function.
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@


################
Nano-Utils 0.4.0
Nano-Utils 0.4.1
################
Utility functions used throughout the various nlesc-nano repositories.

Expand Down
5 changes: 5 additions & 0 deletions docs/0_documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ API
5_numpy.rst
6_set_attr.rst
7_file_container.rst

.. toctree::
:hidden:

_6_set_attr.rst
5 changes: 5 additions & 0 deletions docs/6_set_attr.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
nanoutils.set_attr
==================
.. automodule:: nanoutils.set_attr


Notes
-----
See `link <_6_set_attr.html>`_ for a more extensive (magic) method description.
7 changes: 7 additions & 0 deletions docs/_6_set_attr.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
nanoutils.SetAttr
=================
.. autoclass:: nanoutils.SetAttr
:noindex:
:members:
:private-members:
:special-members:
5 changes: 2 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,14 @@

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'


# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
html_theme_options = {'includehidden': False}


# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory.
Expand Down
2 changes: 1 addition & 1 deletion nanoutils/__version__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""The **Nano-Utils** version."""

__version__ = '0.4.0'
__version__ = '0.4.1'
32 changes: 19 additions & 13 deletions nanoutils/file_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def file_to_context(file, **kwargs): # noqa: E302
r"""Take a path- or file-like object and return an appropiate context manager.
Passing a path-like object will supply it to :func:`open`,
while passing a file-like object will pass it to :class:`contextlib.nullcontext`.
while passing a file-like object will pass it to :func:`contextlib.nullcontext`.
Examples
--------
Expand All @@ -98,7 +98,7 @@ def file_to_context(file, **kwargs): # noqa: E302
Parameters
----------
file : :class:`str`, :class:`bytes`, :class:`os.PathLike` or :class:`io.IOBase`
file : :class:`str`, :class:`bytes`, :class:`os.PathLike` or :class:`~typing.IO`
A `path- <https://docs.python.org/3/glossary.html#term-path-like-object>`_ or
`file-like <https://docs.python.org/3/glossary.html#term-file-object>`_ object.
**kwargs : :data:`~typing.Any`
Expand All @@ -107,7 +107,7 @@ def file_to_context(file, **kwargs): # noqa: E302
Returns
-------
:func:`open` or :class:`~contextlib.nullcontext`
:class:`ContextManager[IO]<typing.ContextManager>`
An initialized context manager.
Entering the context manager will return a file-like object.
Expand Down Expand Up @@ -178,15 +178,15 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
@final
@classmethod
def read(cls: Type[_ST], file: Union[PathType, IO],
decoding: Optional[str] = None, **kwargs: Any) -> _ST:
bytes_decoding: Optional[str] = None, **kwargs: Any) -> _ST:
r"""Construct a new instance from this object's class by reading the content of **file**.
Parameters
----------
file : :class:`str`, :class:`bytes`, :class:`os.PathLike` or :class:`io.IOBase`
file : :class:`str`, :class:`bytes`, :class:`os.PathLike` or :class:`~typing.IO`
A `path- <https://docs.python.org/3/glossary.html#term-path-like-object>`_ or
`file-like <https://docs.python.org/3/glossary.html#term-file-object>`_ object.
decoding : :class:`str`, optional
bytes_decoding : :class:`str`, optional
The type of encoding to use when reading from **file**
when it will be/is be opened in :class:`bytes` mode.
This value should be left empty otherwise.
Expand All @@ -199,7 +199,10 @@ def read(cls: Type[_ST], file: Union[PathType, IO],
context_manager = file_to_context(file, **kwargs)

with context_manager as f:
decoder = _null_func if decoding is None else partial(decode, decoding)
if bytes_decoding is None:
decoder: Callable[[str], Union[str, bytes]] = _null_func
else:
decoder = partial(decode, encoding=bytes_decoding)
cls_dict = cls._read(f, decoder) # type: ignore

ret = cls(**cls_dict)
Expand Down Expand Up @@ -232,27 +235,27 @@ def _read(cls, file_obj: IO[AnyStr], decoder: Callable[[AnyStr], str]) -> Dict[s
raise NotImplementedError('Trying to call an abstract method')

def _read_postprocess(self) -> None:
r"""Construct a new instance from this object's class by reading the content of **file**.
r"""Post process new instances created by :meth:`~AbstractFileContainer.read`.
See Also
--------
:meth:`AbstractFileContainer.read`
The main method for reading files.
Construct a new instance from this object's class by reading the content of **file**.
"""
pass

@final
def write(self, file: Union[PathType, IO],
decoding: Optional[str] = None, **kwargs: Any) -> None:
bytes_encoding: Optional[str] = None, **kwargs: Any) -> None:
r"""Write the content of this instance to **file**.
Parameters
----------
file : :class:`str`, :class:`bytes`, :class:`os.PathLike` or :class:`io.IOBase`
file : :class:`str`, :class:`bytes`, :class:`os.PathLike` or :class:`~typing.IO`
A `path- <https://docs.python.org/3/glossary.html#term-path-like-object>`_ or
`file-like <https://docs.python.org/3/glossary.html#term-file-object>`_ object.
decoding : :class:`str`, optional
bytes_encoding : :class:`str`, optional
The type of encoding to use when writing to **file**
when it will be/is be opened in :class:`bytes` mode.
This value should be left empty otherwise.
Expand All @@ -265,7 +268,10 @@ def write(self, file: Union[PathType, IO],
context_manager = file_to_context(file, **kwargs)

with context_manager as f:
encoder = _null_func if decoding is None else partial(encode, encoding=decoding)
if bytes_encoding is None:
encoder: Callable[[str], Union[str, bytes]] = _null_func
else:
encoder = partial(encode, encoding=bytes_encoding)
self._write(f, encoder) # type: ignore

@abstractmethod
Expand Down
4 changes: 2 additions & 2 deletions nanoutils/numpy_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def array_combinations(array: ArrayLike, r: int = 2, axis: int = -1) -> ndarray:
-------
:class:`numpy.ndarray`, shape :math:`(k, \dotsc, r)`
A :math:`n+1` dimensional array with all **ar** combinations (of length ``r``)
along axis -1.
along **axis**.
:math:`k` represents the number of combinations: :math:`k = \dfrac{m! / r!}{(m-r)!}`.
""" # noqa: E501
Expand Down Expand Up @@ -213,7 +213,7 @@ def fill_diagonal_blocks(array: ndarray, i: int, j: int, val: float = nan) -> No
The size of the diagonal blocks along axis -2.
j : :class:`int`
The size of the diagonal blocks along axis -1.
fill_value : :class:`float`
val : :class:`float`
Value to be written on the diagonal.
Its type must be compatible with that of the array **a**.
Expand Down
35 changes: 31 additions & 4 deletions nanoutils/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,23 @@ def __repr__(self) -> str:
"""Implement :code:`str(self)` and :code:`repr(self)`."""
return f'{self.__class__.__name__}({self.value!r}, call={self.call!r})'

def validate(self, data: object) -> _T:
"""Validate the passed **data**."""
def validate(self, *args: object, **kwargs: object) -> _T:
r"""Validate the passed **data**.
Parameters
----------
\*args/\**kwargs
Variadic (keyword) arguments to ensure signature compatibility.
Supplied values will not be used.
Returns
-------
:class:`object`
Return :attr:`Default.value`.
The to-be returned value will be called if
it is a callable and :attr:`Default.call` is :data:`True`.
"""
if self.call and callable(self.value):
return self.value()
else:
Expand Down Expand Up @@ -214,7 +229,19 @@ def __repr__(self) -> str:
return f'{self.__class__.__name__}(msg={self._msg!r})'

def format(self, obj: object) -> str: # type: ignore
"""Return a formatted version of :attr:`Formatter._msg`."""
r"""Return a formatted version of :attr:`Formatter._msg`.
Parameters
----------
obj : :class:`object`
The to-be formatted object.
Returns
-------
:class:`str`
A formatted string.
"""
try:
name = self._msg.split("'", maxsplit=2)[1]
except IndexError:
Expand Down Expand Up @@ -255,7 +282,7 @@ def isinstance_factory(class_or_tuple: _ClassOrTuple) -> Callable[[object], bool
>>> func(1) # isinstance(1, int)
True
>>> func(1.0) # isinstance(1, float)
>>> func(1.0) # isinstance(1.0, int)
False
Parameters
Expand Down
13 changes: 8 additions & 5 deletions nanoutils/set_attr.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,15 @@ def __init__(self, obj: _T1, name: str, value: _T2) -> None:
Parameters
----------
obj : :class:`T1<typing.TypeVar>`
obj : :class:`object`
The to-be modified object.
See :attr:`SetAttr.obj`.
name : :class:`str`
The name of the to-be modified attribute.
value : :class:`T2<typing.TypeVar>`
See :attr:`SetAttr.name`.
value : :class:`object`
The value to-be assigned to the **name** attribute of **obj**.
See :attr:`SetAttr.value`.
:rtype: :data:`None`
Expand All @@ -107,19 +110,19 @@ def __init__(self, obj: _T1, name: str, value: _T2) -> None:

@reprlib.recursive_repr()
def __repr__(self) -> str:
"""Implement :func:`str(self)<str>` and :func:`repr(self)<repr>`."""
"""Implement :class:`str(self)<str>` and :func:`repr(self)<repr>`."""
obj = object.__repr__(self.obj)
value = reprlib.repr(self.value)
return f'{self.__class__.__name__}(obj={obj}, name={self.name!r}, value={value})'

def __eq__(self, value: object) -> bool:
"""Implement :func:`self == value<object.__eq__>`."""
"""Implement :meth:`self == value<object.__eq__>`."""
if type(self) is not type(value):
return False
return self.obj is value.obj and self.name == value.name and self.value == value.value # type: ignore # noqa: E501

def __reduce__(self) -> NoReturn:
"""A Helper function for :mod:`pickle`.
"""A helper for :mod:`pickle`.
Warnings
--------
Expand Down
12 changes: 0 additions & 12 deletions nanoutils/typing_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,6 @@
An annotation for `path-like <https://docs.python.org/3/glossary.html#term-path-like-object>`_ objects.
.. data:: OpenTextMode
:value: typing.Literal['r', 'r+', '+r', 'rt', 'tr', 'rt+', ...]
A Literal with accepted values for opening path-like objects in :class:`str` mode.
See https://github.com/python/typeshed/blob/master/stdlib/3/io.pyi.
.. data:: OpenBinaryMode
:value: typing.Literal['rb+', 'r+b', '+rb', 'br+', 'b+r', '+br', ...]
A Literal with accepted values for opening path-like objects in :class:`bytes` mode.
See https://github.com/python/typeshed/blob/master/stdlib/3/io.pyi.
""" # noqa: E501

import os
Expand Down
Loading

0 comments on commit 132576c

Please sign in to comment.