Skip to content

Commit

Permalink
Mypy stubs and general maintenance (#202)
Browse files Browse the repository at this point in the history
* Adding testing for Python 3.10-dev
* Changing to use tomli instead of toml by default as it is faster and toml 1.0.0 compatible
* Fixing #189 by adding mappings for mypy
  • Loading branch information
cdgriffith authored Aug 1, 2021
1 parent b61d165 commit 2183dbc
Show file tree
Hide file tree
Showing 23 changed files with 365 additions and 34 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9, pypy3]
python-version: [3.6, 3.7, 3.8, 3.9, 3.10-dev, pypy3]

steps:
- uses: actions/checkout@v2
Expand All @@ -63,4 +63,3 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
pytest --cov=box test/
34 changes: 26 additions & 8 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.5.0
rev: v4.0.1
hooks:
- id: mixed-line-ending
- id: trailing-whitespace
# Identify invalid files
- id: check-ast
- id: check-yaml
- id: check-json
- id: check-toml
# git checks
- id: check-merge-conflict
- id: check-added-large-files
exclude: ^test/data/.+
- id: detect-private-key
- id: check-case-conflict
# Python checks
- id: check-docstring-first
- id: debug-statements
- id: requirements-txt-fixer
- id: fix-encoding-pragma
- id: check-byte-order-marker
- id: debug-statements
- id: check-yaml
- id: fix-byte-order-marker
# General quality checks
- id: mixed-line-ending
args: [--fix=lf]
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
- id: check-executables-have-shebangs
- id: end-of-file-fixer
exclude: ^test/data/.+
- repo: https://github.com/ambv/black
rev: stable
rev: 21.7b0
hooks:
- id: black
args: [--config=.black.toml]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v0.770'
rev: 'v0.910'
hooks:
- id: mypy
additional_dependencies: [ruamel.yaml,toml,msgpack]
2 changes: 1 addition & 1 deletion AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ Suggestions and bug reporting:
- Marcelo Huerta (richieadler)
- Tim Schwenke (trallnag)
- Marcos Dione (mdione-cloudian)
- Varun Madiath (vamega)
- Varun Madiath (vamega)
8 changes: 6 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
Changelog
=========

Version 5.3.1
Version 5.4.0
-------------

* Fixing #189 mappings for mypy
* Adding py.typed for mypy support (thanks to Dominic)
* Adding testing for Python 3.10-dev
* Changing to use tomli instead of toml by default as it is faster and toml 1.0.0 compatible
* Fixing #189 by adding mappings for mypy


Version 5.3.0
-------------
Expand Down
1 change: 0 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
include LICENSE
include AUTHORS.rst
include CHANGES.rst

include box/py.typed
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,4 @@ MIT License, Copyright (c) 2017-2020 Chris Griffith. See LICENSE_ file.
.. _`Wrapt Documentation`: https://wrapt.readthedocs.io/en/latest
.. _reusables: https://github.com/cdgriffith/reusables#reusables
.. _created: https://github.com/cdgriffith/Reusables/commit/df20de4db74371c2fedf1578096f3e29c93ccdf3#diff-e9a0f470ef3e8afb4384dc2824943048R51
.. _LICENSE: https://github.com/cdgriffith/Box/blob/master/LICENSE
.. _LICENSE: https://github.com/cdgriffith/Box/blob/master/LICENSE
2 changes: 1 addition & 1 deletion box/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-

__author__ = "Chris Griffith"
__version__ = "5.3.1"
__version__ = "5.4.0"

from box.box import Box
from box.box_list import BoxList
Expand Down
11 changes: 8 additions & 3 deletions box/box.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@
import re
import string
import warnings
from collections.abc import Callable, Iterable, Mapping
from keyword import kwlist
from os import PathLike
from typing import Any, Dict, Generator, List, Tuple, Union

try:
from typing import Callable, Iterable, Mapping
except ImportError:
from collections.abc import Callable, Iterable, Mapping

import box
from box.converters import (
BOX_PARAMETERS,
Expand Down Expand Up @@ -51,6 +55,7 @@ def _exception_cause(e):
"""
return e.__cause__ if isinstance(e, (BoxKeyError, BoxValueError)) else e


def _camel_killer(attr):
"""
CamelKiller, qu'est-ce que c'est?
Expand Down Expand Up @@ -427,7 +432,7 @@ def __recast(self, item, value):
else:
return recast(value)
except ValueError as err:
raise BoxValueError(f'Cannot convert {value} to {recast}') from _exception_cause(err)
raise BoxValueError(f"Cannot convert {value} to {recast}") from _exception_cause(err)
return value

def __convert_and_store(self, item, value):
Expand Down Expand Up @@ -663,7 +668,7 @@ def convert_and_set(k, v):
return
if isinstance(v, list) and not intact_type:
v = box.BoxList(v, **self.__box_config())
merge_type = kwargs.get('box_merge_lists')
merge_type = kwargs.get("box_merge_lists")
if merge_type == "extend" and k in self and isinstance(self[k], list):
self[k].extend(v)
return
Expand Down
115 changes: 115 additions & 0 deletions box/box.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
from collections.abc import Mapping
from os import PathLike
from typing import Any, Dict, Generator, List, Optional, Tuple, Union

class Box(dict):
def __new__(
cls: Any,
*args: Any,
default_box: bool = ...,
default_box_attr: Any = ...,
default_box_none_transform: bool = ...,
frozen_box: bool = ...,
camel_killer_box: bool = ...,
conversion_box: bool = ...,
modify_tuples_box: bool = ...,
box_safe_prefix: str = ...,
box_duplicates: str = ...,
box_intact_types: Union[Tuple, List] = ...,
box_recast: Dict = ...,
box_dots: bool = ...,
box_class: Union[Dict, Box] = ...,
**kwargs: Any,
) -> Any: ...
def __init__(
self,
*args: Any,
default_box: bool = ...,
default_box_attr: Any = ...,
default_box_none_transform: bool = ...,
frozen_box: bool = ...,
camel_killer_box: bool = ...,
conversion_box: bool = ...,
modify_tuples_box: bool = ...,
box_safe_prefix: str = ...,
box_duplicates: str = ...,
box_intact_types: Union[Tuple, List] = ...,
box_recast: Dict = ...,
box_dots: bool = ...,
box_class: Union[Dict, Box] = ...,
**kwargs: Any,
) -> None: ...
def __add__(self, other: Mapping[Any, Any]) -> Any: ...
def __radd__(self, other: Mapping[Any, Any]) -> Any: ...
def __iadd__(self, other: Mapping[Any, Any]) -> Any: ...
def __or__(self, other: Mapping[Any, Any]) -> Any: ...
def __ror__(self, other: Mapping[Any, Any]) -> Any: ...
def __ior__(self, other: Mapping[Any, Any]) -> Any: ...
def __sub__(self, other: Mapping[Any, Any]) -> Any: ...
def __hash__(self) -> Any: ... # type: ignore[override]
def __dir__(self): ...
def keys(self, dotted: Union[bool] = ...) -> Any: ...
def items(self, dotted: Union[bool] = ...) -> Any: ...
def get(self, key: Any, default: Any = ...): ...
def copy(self) -> Box: ...
def __copy__(self) -> Box: ...
def __deepcopy__(self, memodict: Any = ...) -> Box: ...
def __getitem__(self, item: Any, _ignore_default: bool = ...): ...
def __getattr__(self, item: Any): ...
def __setitem__(self, key: Any, value: Any): ...
def __setattr__(self, key: Any, value: Any): ...
def __delitem__(self, key: Any): ...
def __delattr__(self, item: Any) -> None: ...
def pop(self, key: Any, *args: Any): ...
def clear(self) -> None: ...
def popitem(self): ...
def __iter__(self) -> Generator: ...
def __reversed__(self) -> Generator: ...
def to_dict(self) -> Dict: ...
def update(self, __m: Optional[Any] = ..., **kwargs: Any) -> None: ...
def merge_update(self, __m: Optional[Any] = ..., **kwargs: Any) -> None: ...
def setdefault(self, item: Any, default: Optional[Any] = ...): ...
def to_json(
self, filename: Union[str, PathLike] = ..., encoding: str = ..., errors: str = ..., **json_kwargs: Any
) -> Any: ...
@classmethod
def from_json(
cls: Any,
json_string: str = ...,
filename: Union[str, PathLike] = ...,
encoding: str = ...,
errors: str = ...,
**kwargs: Any,
) -> Box: ...
def to_yaml(
self,
filename: Union[str, PathLike] = ...,
default_flow_style: bool = ...,
encoding: str = ...,
errors: str = ...,
**yaml_kwargs: Any,
) -> Any: ...
@classmethod
def from_yaml(
cls: Any,
yaml_string: str = ...,
filename: Union[str, PathLike] = ...,
encoding: str = ...,
errors: str = ...,
**kwargs: Any,
) -> Box: ...
def to_toml(self, filename: Union[str, PathLike] = ..., encoding: str = ..., errors: str = ...) -> Any: ...
@classmethod
def from_toml(
cls: Any,
toml_string: str = ...,
filename: Union[str, PathLike] = ...,
encoding: str = ...,
errors: str = ...,
**kwargs: Any,
) -> Box: ...
def to_msgpack(self, filename: Union[str, PathLike] = ..., **kwargs: Any) -> Any: ...
@classmethod
def from_msgpack(
cls: Any, msgpack_bytes: bytes = ..., filename: Union[str, PathLike] = ..., **kwargs: Any
) -> Box: ...
85 changes: 85 additions & 0 deletions box/box_list.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import box
from box.converters import (
BOX_PARAMETERS as BOX_PARAMETERS,
msgpack_available as msgpack_available,
toml_available as toml_available,
yaml_available as yaml_available,
)
from box.exceptions import BoxError as BoxError, BoxTypeError as BoxTypeError
from os import PathLike as PathLike
from typing import Any, Iterable, Optional, Type, Union

class BoxList(list):
def __new__(cls, *args: Any, **kwargs: Any): ...
box_options: Any = ...
box_org_ref: Any = ...
def __init__(self, iterable: Iterable = ..., box_class: Type[box.Box] = ..., **box_options: Any) -> None: ...
def __getitem__(self, item: Any): ...
def __delitem__(self, key: Any): ...
def __setitem__(self, key: Any, value: Any): ...
def append(self, p_object: Any) -> None: ...
def extend(self, iterable: Any) -> None: ...
def insert(self, index: Any, p_object: Any) -> None: ...
def __copy__(self): ...
def __deepcopy__(self, memo: Optional[Any] = ...): ...
def __hash__(self) -> Any: ... # type: ignore[override]
def to_list(self): ...
def to_json(
self,
filename: Union[str, PathLike] = ...,
encoding: str = ...,
errors: str = ...,
multiline: bool = ...,
**json_kwargs: Any,
) -> Any: ...
@classmethod
def from_json(
cls: Any,
json_string: str = ...,
filename: Union[str, PathLike] = ...,
encoding: str = ...,
errors: str = ...,
multiline: bool = ...,
**kwargs: Any,
) -> Any: ...
def to_yaml(
self,
filename: Union[str, PathLike] = ...,
default_flow_style: bool = ...,
encoding: str = ...,
errors: str = ...,
**yaml_kwargs: Any,
) -> Any: ...
@classmethod
def from_yaml(
cls: Any,
yaml_string: str = ...,
filename: Union[str, PathLike] = ...,
encoding: str = ...,
errors: str = ...,
**kwargs: Any,
) -> Any: ...
def to_toml(
self, filename: Union[str, PathLike] = ..., key_name: str = ..., encoding: str = ..., errors: str = ...
) -> Any: ...
@classmethod
def from_toml(
cls: Any,
toml_string: str = ...,
filename: Union[str, PathLike] = ...,
key_name: str = ...,
encoding: str = ...,
errors: str = ...,
**kwargs: Any,
) -> Any: ...
def to_msgpack(self, filename: Union[str, PathLike] = ..., **kwargs: Any) -> Any: ...
@classmethod
def from_msgpack(
cls: Any, msgpack_bytes: bytes = ..., filename: Union[str, PathLike] = ..., **kwargs: Any
) -> Any: ...
def to_csv(self, filename: Union[str, PathLike] = ..., encoding: str = ..., errors: str = ...) -> Any: ...
@classmethod
def from_csv(
cls: Any, csv_string: str = ..., filename: Union[str, PathLike] = ..., encoding: str = ..., errors: str = ...
) -> Any: ...
def _dotted_helper(self) -> Any: ...
2 changes: 1 addition & 1 deletion box/config_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def float(self, item, default=None):
raise err
return float(item)

def list(self, item, default=None, spliter=",", strip=True, mod=None):
def list(self, item, default=None, spliter: str = ",", strip=True, mod=None):
"""
Return value of key as a list
Expand Down
15 changes: 15 additions & 0 deletions box/config_box.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from box.box import Box as Box
from typing import Any, Optional

class ConfigBox(Box):
def __getattr__(self, item: Any): ...
def __dir__(self): ...
def bool(self, item: Any, default: Optional[Any] = ...): ...
def int(self, item: Any, default: Optional[Any] = ...): ...
def float(self, item: Any, default: Optional[Any] = ...): ...
def list(self, item: Any, default: Optional[Any] = ..., spliter: str = ..., strip: bool = ..., mod: Optional[Any] = ...): ... # type: ignore
def getboolean(self, item: Any, default: Optional[Any] = ...): ...
def getint(self, item: Any, default: Optional[Any] = ...): ...
def getfloat(self, item: Any, default: Optional[Any] = ...): ...
def copy(self): ...
def __copy__(self): ...
Loading

0 comments on commit 2183dbc

Please sign in to comment.