Skip to content

Commit

Permalink
Release 0.4.0 (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
lycantropos committed Apr 8, 2021
1 parent c0c62eb commit ec27b43
Show file tree
Hide file tree
Showing 26 changed files with 280 additions and 205 deletions.
27 changes: 14 additions & 13 deletions .azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,32 +109,33 @@ steps:
inputs:
versionSpec: '$(python.version)'
architecture: '$(python.architecture)'
- script: python -m doctest README.md
displayName: 'Run doctests'
- script: python -m pip install --upgrade pip setuptools
- bash: python -m pip install --upgrade pip setuptools
displayName: 'Install packaging tools'
- script: python -m pip install -r requirements-tests.txt
- bash: python -m pip install --upgrade coverage codecov
displayName: 'Install coverage dependencies'
- bash: coverage run -m doctest README.md
displayName: 'Run doctests'
- bash: python -m pip install -r requirements-tests.txt
displayName: 'Install tests dependencies'
- script: pytest
- bash: coverage run --append -m pytest
displayName: 'Run tests'
- script: python -m pip install --upgrade codecov
condition: succeeded()
displayName: 'Install coverage dependencies'
- script: python -m codecov -f coverage.xml -X gcov
- bash: coverage xml
displayName: 'Collect coverage'
- bash: python -m codecov -f coverage.xml -X gcov --build "$AGENT_JOBNAME"
condition: succeeded()
displayName: 'Upload coverage'
env:
CODECOV_TOKEN: $(CODECOV_TOKEN)
- script: python -m pip install --upgrade wheel
- bash: python -m pip install --upgrade wheel
condition: and(succeeded(), eq(variables['python.version'], '3.5'), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))
displayName: 'Install build dependencies'
- script: python setup.py sdist bdist_wheel
- bash: python setup.py sdist bdist_wheel
condition: and(succeeded(), eq(variables['python.version'], '3.5'), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))
displayName: 'Build'
- script: python -m pip install --upgrade twine
- bash: python -m pip install --upgrade twine
condition: and(succeeded(), eq(variables['python.version'], '3.5'), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))
displayName: 'Install deploy dependencies'
- script: twine upload --skip-existing dist/*
- bash: twine upload --skip-existing dist/*
condition: and(succeeded(), eq(variables['python.version'], '3.5'), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))
displayName: 'Deploy'
env:
Expand Down
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.3.1
current_version = 0.4.0
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(-(?P<release>.*))?
serialize =
Expand Down
2 changes: 2 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[run]
source = reprit
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@ venv*/

### JetBrains
.idea/

### MacOS
.DS_Store
21 changes: 12 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
ARG PYTHON_IMAGE
ARG PYTHON_IMAGE_VERSION
ARG IMAGE_NAME
ARG IMAGE_VERSION

FROM ${PYTHON_IMAGE}:${PYTHON_IMAGE_VERSION}
FROM ${IMAGE_NAME}:${IMAGE_VERSION}

RUN pip install --upgrade pip setuptools

WORKDIR /opt/reprit

COPY reprit/ reprit/
COPY tests/ tests/
COPY README.md .
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY requirements-tests.txt .
COPY setup.py .
COPY pytest.ini .
RUN pip install -r requirements-tests.txt

RUN pip install --force-reinstall -r requirements-tests.txt
COPY README.md .
COPY pytest.ini .
COPY setup.py .
COPY reprit reprit
COPY tests tests
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ reprit
[![](https://img.shields.io/github/license/lycantropos/reprit.svg)](https://github.com/lycantropos/reprit/blob/master/LICENSE "License")
[![](https://badge.fury.io/py/reprit.svg)](https://badge.fury.io/py/reprit "PyPI")

In what follows `python` is an alias for `python3.5` or `pypy3.5` or any later
version (`python3.6` and `pypy3.6` and so on).
In what follows `python` is an alias for `python3.5` or `pypy3.5`
or any later version (`python3.6`, `pypy3.6` and so on).

Installation
------------

Install the latest `pip` & `setuptools` packages versions:
Install the latest `pip` & `setuptools` packages versions
```bash
python -m pip install --upgrade pip setuptools
```

### User

Download and install the latest stable version from `PyPI` repository:
Download and install the latest stable version from `PyPI` repository
```bash
python -m pip install --upgrade reprit
```
Expand All @@ -33,7 +33,7 @@ git clone https://github.com/lycantropos/reprit.git
cd reprit
```

Install:
Install
```bash
python setup.py install
```
Expand Down Expand Up @@ -144,12 +144,12 @@ This will set version to `major.minor.patch`.

### Running tests

Install dependencies:
Install dependencies
```bash
python -m pip install --force-reinstall -r requirements-tests.txt
python -m pip install -r requirements-tests.txt
```

Plain:
Plain
```bash
pytest
```
Expand Down
37 changes: 19 additions & 18 deletions docker-compose.cpython.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
version: '3'

services:
reprit-cpython:
build:
context: .
args:
- PYTHON_IMAGE=${CPYTHON_IMAGE_NAME}
- PYTHON_IMAGE_VERSION=${CPYTHON_IMAGE_VERSION}
image: lycantropos/reprit-cpython:0.3.1
volumes:
- ./reprit/:/opt/reprit/reprit/
- ./tests/:/opt/reprit/tests/
- ./README.md:/opt/reprit/README.md
- ./requirements-tests.txt:/opt/reprit/requirements-tests.txt
- ./setup.py:/opt/reprit/setup.py
- ./pytest.ini:/opt/reprit/pytest.ini
entrypoint: pytest
version: '3'

services:
reprit-cpython:
build:
context: .
args:
- IMAGE_NAME=${CPYTHON_IMAGE_NAME}
- IMAGE_VERSION=${CPYTHON_IMAGE_VERSION}
image: lycantropos/reprit-cpython:0.4.0
volumes:
- ./pytest.ini:/opt/reprit/pytest.ini
- ./README.md:/opt/reprit/README.md
- ./reprit:/opt/reprit/reprit
- ./requirements-tests.txt:/opt/reprit/requirements-tests.txt
- ./requirements.txt:/opt/reprit/requirements.txt
- ./setup.py:/opt/reprit/setup.py
- ./tests:/opt/reprit/tests
entrypoint: pytest
37 changes: 19 additions & 18 deletions docker-compose.pypy.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
version: '3'

services:
reprit-pypy:
build:
context: .
args:
- PYTHON_IMAGE=${PYPY_IMAGE_NAME}
- PYTHON_IMAGE_VERSION=${PYPY_IMAGE_VERSION}
image: lycantropos/reprit-pypy:0.3.1
volumes:
- ./reprit/:/opt/reprit/reprit/
- ./tests/:/opt/reprit/tests/
- ./README.md:/opt/reprit/README.md
- ./requirements-tests.txt:/opt/reprit/requirements-tests.txt
- ./setup.py:/opt/reprit/setup.py
- ./pytest.ini:/opt/reprit/pytest.ini
entrypoint: pytest
version: '3'

services:
reprit-pypy:
build:
context: .
args:
- IMAGE_NAME=${PYPY_IMAGE_NAME}
- IMAGE_VERSION=${PYPY_IMAGE_VERSION}
image: lycantropos/reprit-pypy:0.4.0
volumes:
- ./pytest.ini:/opt/reprit/pytest.ini
- ./README.md:/opt/reprit/README.md
- ./reprit:/opt/reprit/reprit
- ./requirements-tests.txt:/opt/reprit/requirements-tests.txt
- ./requirements.txt:/opt/reprit/requirements.txt
- ./setup.py:/opt/reprit/setup.py
- ./tests:/opt/reprit/tests
entrypoint: pytest
5 changes: 0 additions & 5 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
[pytest]
addopts = --verbose
-vv
-s
--doctest-modules
--hypothesis-profile=default
--cov-report term
--cov-report xml
--cov=reprit
2 changes: 1 addition & 1 deletion reprit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Auto __repr__ method generation."""

__version__ = '0.3.1'
__version__ = '0.4.0'
46 changes: 23 additions & 23 deletions reprit/base.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
from collections import (OrderedDict,
abc)
from inspect import (_ParameterKind,
signature)
from typing import (Iterable,
Union)
signature as _signature)
from types import MethodType as _MethodType
from typing import (Iterable as _Iterable,
Union as _Union)

from . import seekers
from .hints import (Constructor,
Domain,
FieldSeeker,
Initializer,
Map)
from . import seekers as _seekers
from .core.hints import (Constructor as _Constructor,
Domain as _Domain,
Initializer as _Initializer,
Map as _Map)
from .hints import FieldSeeker as _FieldSeeker


def generate_repr(method: Union[Constructor, Initializer],
def generate_repr(method: _Union[_Constructor, _Initializer],
*,
field_seeker: FieldSeeker = seekers.simple,
field_seeker: _FieldSeeker = _seekers.simple,
prefer_keyword: bool = False,
with_module_name: bool = False) -> Map[Domain, str]:
with_module_name: bool = False) -> _Map[_Domain, str]:
"""
Generates ``__repr__`` method based on constructor/initializer parameters.
Expand Down Expand Up @@ -83,7 +84,6 @@ def generate_repr(method: Union[Constructor, Initializer],
>>> class Object:
... def __init__(self, value):
... self.value = value
... @property
... def serialized(self):
... return json.dumps(self.value)
... @classmethod
Expand All @@ -106,21 +106,21 @@ def to_class_name(cls: type) -> str:
if isinstance(method, (classmethod, staticmethod))
else method)
method_name = unwrapped_method.__name__
parameters = OrderedDict(signature(unwrapped_method).parameters)
parameters = OrderedDict(_signature(unwrapped_method).parameters)

if method_name in ('__init__', '__new__'):
# remove `cls`/`self`
parameters.popitem(0)

def __repr__(self: Domain) -> str:
def __repr__(self: _Domain) -> str:
return (to_class_name(type(self))
+ '(' + ', '.join(to_arguments_strings(self)) + ')')
else:
if isinstance(method, classmethod):
# remove `cls`
parameters.popitem(0)

def __repr__(self: Domain) -> str:
def __repr__(self: _Domain) -> str:
return (to_class_name(type(self)) + '.' + method_name
+ '(' + ', '.join(to_arguments_strings(self)) + ')')

Expand All @@ -132,12 +132,14 @@ def __repr__(self: Domain) -> str:
to_positional_argument_string = repr
to_keyword_argument_string = '{}={!r}'.format

def to_arguments_strings(object_: Domain) -> Iterable[str]:
def to_arguments_strings(object_: _Domain) -> _Iterable[str]:
variadic_positional_unset = (
variadic_positional is None
or not field_seeker(object_, variadic_positional.name))
for parameter_name, parameter in parameters.items():
field = field_seeker(object_, parameter_name)
if isinstance(field, _MethodType) and field.__self__ is object_:
field = field()
if parameter.kind is _ParameterKind.POSITIONAL_ONLY:
yield to_positional_argument_string(field)
elif parameter.kind is _ParameterKind.POSITIONAL_OR_KEYWORD:
Expand All @@ -146,12 +148,10 @@ def to_arguments_strings(object_: Domain) -> Iterable[str]:
else:
yield to_positional_argument_string(field)
elif parameter.kind is _ParameterKind.VAR_POSITIONAL:
if isinstance(field, abc.Iterator):
# we don't want to exhaust iterator
yield '...'
else:
yield from map(to_positional_argument_string,
field() if callable(field) else field)
yield from ((to_positional_argument_string(field),)
# we don't want to exhaust iterator
if isinstance(field, abc.Iterator)
else map(to_positional_argument_string, field))
elif parameter.kind is _ParameterKind.KEYWORD_ONLY:
yield to_keyword_argument_string(parameter_name, field)
else:
Expand Down
Empty file added reprit/core/__init__.py
Empty file.
8 changes: 8 additions & 0 deletions reprit/core/hints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from typing import (Callable,
TypeVar)

Domain = TypeVar('Domain')
Range = TypeVar('Range')
Map = Callable[[Domain], Range]
Constructor = Callable[..., Domain]
Initializer = Callable[..., None]
File renamed without changes.
13 changes: 4 additions & 9 deletions reprit/hints.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
from typing import (Any,
Callable,
TypeVar)
Callable)

Domain = TypeVar('Domain')
Range = TypeVar('Range')
Map = Callable[[Domain], Range]
Operator = Map[Domain, Domain]
Constructor = Callable[..., Domain]
Initializer = Callable[..., None]
FieldSeeker = Callable[[Domain, str], Any]
from .core.hints import Domain as _Domain

FieldSeeker = Callable[[_Domain, str], Any]
12 changes: 6 additions & 6 deletions reprit/seekers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Any
from typing import Any as _Any

from .hints import Domain
from .utils import group_by
from .core.hints import Domain as _Domain
from .core.utils import group_by as _group_by

simple = getattr

Expand All @@ -14,7 +14,7 @@
# do not confuse with "mangled" ones, ``__value`` in our case)
# and both
# (like in case with parameter ``id_`` and field ``_id``)
def complex_(object_: Domain, parameter_name: str) -> Any:
def complex_(object_: _Domain, parameter_name: str) -> _Any:
try:
return getattr(object_, parameter_name)
except AttributeError as original_error:
Expand All @@ -25,8 +25,8 @@ def grouping_key(name: str) -> int:
return abs(len(name) - len(parameter_name))

candidates = filter(is_candidate, dir(object_))
key, group = min(group_by(candidates,
key=grouping_key))
key, group = min(_group_by(candidates,
key=grouping_key))
try:
field_name, = group
except ValueError:
Expand Down
5 changes: 2 additions & 3 deletions requirements-tests.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
hypothesis>=5.33.0
pytest>=6.1.1
pytest-cov>=2.10.1
pytest>=6.1.2
hypothesis>=5.33.2

0 comments on commit ec27b43

Please sign in to comment.