forked from python-attrs/attrs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Docs aren't there yet
- Loading branch information
0 parents
commit 9560908
Showing
27 changed files
with
1,847 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.tox | ||
.coverage | ||
*.pyc | ||
*.egg-info | ||
docs/_build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
language: python | ||
python: 2.7 | ||
env: | ||
- TOX_ENV=py26 | ||
- TOX_ENV=py27 | ||
- TOX_ENV=py33 | ||
- TOX_ENV=py34 | ||
- TOX_ENV=pypy | ||
- TOX_ENV=docs | ||
- TOX_ENV=flake8 | ||
- TOX_ENV=manifest | ||
|
||
install: | ||
- pip install tox coveralls | ||
|
||
script: | ||
- tox --hashseed 0 -e $TOX_ENV | ||
|
||
after_success: | ||
- coveralls | ||
|
||
notifications: | ||
email: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Authors | ||
------- | ||
|
||
``attrs`` is written and maintained by `Hynek Schlawack <https://hynek.me/>`_. | ||
|
||
The development is kindly supported by `Variomedia AG <https://www.variomedia.de/>`_. | ||
|
||
It’s the spiritual successor of `characteristic <https://characteristic.readthedocs.org/>`_ and aspires to fix some of it clunkiness and unfortunate decisions. Both were inspired by Twisted’s `FancyEqMixin <https://twistedmatrix.com/documents/current/api/twisted.python.util.FancyEqMixin.html>`_ but both are implemented using class decorators because `sub-classing is bad for you <https://www.youtube.com/watch?v=3MNVP9-hglc>`_, m’kay? | ||
|
||
|
||
The following folks helped forming ``attrs`` into what it is now: | ||
|
||
- `Glyph <https://github.com/glyph>`_ | ||
|
||
Of course ``characteristic``\ ’s `hall of fame <https://characteristic.readthedocs.org/en/stable/license.html>`_ applies as well since they share a lot of code. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
How To Contribute | ||
================= | ||
|
||
Every open source project lives from the generous help by contributors that sacrifice their time and ``attrs`` is no different. | ||
|
||
To make participation as pleasant as possible, this project adheres to the `Code of Conduct`_ by the Python Software Foundation. | ||
|
||
Here are a few guidelines to get you started: | ||
|
||
- Add yourself to the AUTHORS.rst_ file in an alphabetical fashion. | ||
Every contribution is valuable and shall be credited. | ||
- If your change is noteworthy, add an entry to the changelog_. | ||
- No contribution is too small; please submit as many fixes for typos and grammar bloopers as you can! | ||
- Don’t *ever* break backward compatibility. | ||
If it ever *has* to happen for higher reasons, ``attrs`` will follow the proven procedures_ of the Twisted project. | ||
- *Always* add tests and docs for your code. | ||
This is a hard rule; patches with missing tests or documentation won’t be merged. | ||
If a feature is not tested or documented, it doesn’t exist. | ||
- Obey `PEP 8`_ and `PEP 257`_. | ||
- Write `good commit messages`_. | ||
|
||
.. note:: | ||
If you have something great but aren’t sure whether it adheres -- or even can adhere -- to the rules above: **please submit a pull request anyway**! | ||
|
||
In the best case, we can mold it into something, in the worst case the pull request gets politely closed. | ||
There’s absolutely nothing to fear. | ||
|
||
Thank you for considering to contribute to ``attrs``! | ||
If you have any question or concerns, feel free to reach out to me. | ||
|
||
|
||
.. _`PEP 8`: http://legacy.python.org/dev/peps/pep-0008/ | ||
.. _`PEP 257`: http://legacy.python.org/dev/peps/pep-0257/ | ||
.. _`good commit messages`: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html | ||
.. _`Code of Conduct`: https://www.python.org/psf/codeofconduct/ | ||
.. _changelog: https://github.com/hynek/attrs/blob/master/docs/changelog.rst | ||
.. _AUTHORS.rst: https://github.com/hynek/attrs/blob/master/AUTHORS.rst | ||
.. _procedures: http://twistedmatrix.com/trac/wiki/CompatibilityPolicy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2014 Hynek Schlawack | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
include *.rst *.txt LICENSE tox.ini .travis.yml docs/Makefile .coveragerc | ||
recursive-include tests *.py | ||
recursive-include docs *.rst | ||
recursive-include docs *.py | ||
prune docs/_build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
============================================= | ||
attrs: Python attributes without boilerplate. | ||
============================================= | ||
|
||
.. image:: https://pypip.in/version/attrs/badge.svg | ||
:target: https://pypi.python.org/pypi/attrs/ | ||
:alt: Latest Version | ||
|
||
.. image:: https://travis-ci.org/hynek/attrs.svg | ||
:target: https://travis-ci.org/hynek/attrs | ||
:alt: CI status | ||
|
||
.. image:: https://coveralls.io/repos/hynek/attrs/badge.png?branch=master | ||
:target: https://coveralls.io/r/hynek/attrs?branch=master | ||
:alt: Current coverage | ||
|
||
.. begin | ||
``attrs`` is an `MIT <http://choosealicense.com/licenses/mit/>`_-licensed Python package with class decorators that ease the chores of implementing the most common attribute-related object protocols: | ||
|
||
.. code-block:: pycon | ||
>>> import attr | ||
>>> @attr.s | ||
... class C(object): | ||
... x = attr.a(default_value=42) | ||
... y = attr.a(default_factory=list) | ||
>>> i = C(x=1, y=2) | ||
>>> i | ||
<C(x=1, y=2)> | ||
>>> i == C(1, 2) | ||
True | ||
>>> i != C(2, 1) | ||
True | ||
>>> attr.to_dict(i) | ||
{'y': 2, 'x': 1} | ||
>>> C() | ||
<C(x=42, y=[])> | ||
You just specify the attributes to work with and ``attrs`` gives you: | ||
|
||
- a nice human-readable ``__repr__``, | ||
- a complete set of comparison methods, | ||
- and an initializer | ||
|
||
*without* writing dull boilerplate code again and again. | ||
|
||
This gives you the power to use actual classes with actual types in your code instead of confusing ``tuple``\ s or confusingly behaving ``namedtuple``\ s. | ||
|
||
So put down that type-less data structures and welcome some class into your life! | ||
|
||
``attrs``\ ’s documentation lives at `Read the Docs <https://attrs.readthedocs.org/>`_, the code on `GitHub <https://github.com/hynek/attrs>`_. | ||
It’s rigorously tested on Python 2.6, 2.7, 3.3+, and PyPy. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from __future__ import absolute_import, division, print_function | ||
|
||
from ._funcs import ( | ||
ls, | ||
to_dict, | ||
) | ||
from ._make import ( | ||
_make_attr as a, | ||
s, | ||
) | ||
|
||
__version__ = "0.0.0.dev0" | ||
__author__ = "Hynek Schlawack" | ||
__license__ = "MIT" | ||
__copyright__ = "Copyright 2015 Hynek Schlawack" | ||
|
||
|
||
__all__ = [ | ||
"a", "s", "ls", "to_dict", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from __future__ import absolute_import, division, print_function | ||
|
||
import hashlib | ||
import linecache | ||
import sys | ||
|
||
|
||
def _attrs_to_tuple(obj, attrs): | ||
""" | ||
Create a tuple of all values of *obj*'s *attrs*. | ||
""" | ||
return tuple(getattr(obj, a) for a in attrs) | ||
|
||
|
||
def _add_hash(cl, attrs=None): | ||
if attrs is None: | ||
attrs = [a.name for a in cl.__attrs_attrs__] | ||
|
||
def hash_(self): | ||
""" | ||
Automatically created by attrs. | ||
""" | ||
return hash(_attrs_to_tuple(self, attrs)) | ||
|
||
cl.__hash__ = hash_ | ||
return cl | ||
|
||
|
||
def _add_cmp(cl, attrs=None): | ||
if attrs is None: | ||
attrs = [a.name for a in cl.__attrs_attrs__] | ||
|
||
def attrs_to_tuple(obj): | ||
""" | ||
Save us some typing. | ||
""" | ||
return _attrs_to_tuple(obj, attrs) | ||
|
||
def eq(self, other): | ||
""" | ||
Automatically created by attrs. | ||
""" | ||
if isinstance(other, self.__class__): | ||
return attrs_to_tuple(self) == attrs_to_tuple(other) | ||
else: | ||
return NotImplemented | ||
|
||
def ne(self, other): | ||
""" | ||
Automatically created by attrs. | ||
""" | ||
result = eq(self, other) | ||
if result is NotImplemented: | ||
return NotImplemented | ||
else: | ||
return not result | ||
|
||
def lt(self, other): | ||
""" | ||
Automatically created by attrs. | ||
""" | ||
if isinstance(other, self.__class__): | ||
return attrs_to_tuple(self) < attrs_to_tuple(other) | ||
else: | ||
return NotImplemented | ||
|
||
def le(self, other): | ||
""" | ||
Automatically created by attrs. | ||
""" | ||
if isinstance(other, self.__class__): | ||
return attrs_to_tuple(self) <= attrs_to_tuple(other) | ||
else: | ||
return NotImplemented | ||
|
||
def gt(self, other): | ||
""" | ||
Automatically created by attrs. | ||
""" | ||
if isinstance(other, self.__class__): | ||
return attrs_to_tuple(self) > attrs_to_tuple(other) | ||
else: | ||
return NotImplemented | ||
|
||
def ge(self, other): | ||
""" | ||
Automatically created by attrs. | ||
""" | ||
if isinstance(other, self.__class__): | ||
return attrs_to_tuple(self) >= attrs_to_tuple(other) | ||
else: | ||
return NotImplemented | ||
|
||
cl.__eq__ = eq | ||
cl.__ne__ = ne | ||
cl.__lt__ = lt | ||
cl.__le__ = le | ||
cl.__gt__ = gt | ||
cl.__ge__ = ge | ||
|
||
return cl | ||
|
||
|
||
def _add_repr(cl, attrs=None): | ||
if attrs is None: | ||
attrs = [a.name for a in cl.__attrs_attrs__] | ||
|
||
def repr_(self): | ||
""" | ||
Automatically created by attrs. | ||
""" | ||
return "<{0}({1})>".format( | ||
self.__class__.__name__, | ||
", ".join(a + "=" + repr(getattr(self, a)) for a in attrs) | ||
) | ||
cl.__repr__ = repr_ | ||
return cl | ||
|
||
|
||
# I'm sorry. :( | ||
if sys.version_info[0] == 2: | ||
def exec_(code, locals_, globals_): | ||
exec("exec code in locals_, globals_") | ||
else: # pragma: no cover | ||
def exec_(code, locals_, globals_): | ||
exec(code, locals_, globals_) | ||
|
||
|
||
class _Nothing(object): | ||
""" | ||
Sentinel class to indicate the lack of a value when ``None`` is ambiguous. | ||
""" | ||
def __repr__(self): | ||
return "NOTHING" | ||
|
||
|
||
NOTHING = _Nothing() | ||
""" | ||
Sentinel to indicate the lack of a value when ``None`` is ambiguous. | ||
""" | ||
|
||
|
||
def _add_init(cl): | ||
attrs = cl.__attrs_attrs__ | ||
|
||
# We cache the generated init methods for the same kinds of attributes. | ||
sha1 = hashlib.sha1() | ||
sha1.update(repr(attrs).encode("utf-8")) | ||
unique_filename = "<attrs generated init {0}>".format( | ||
sha1.hexdigest() | ||
) | ||
|
||
script = _attrs_to_script(attrs) | ||
locs = {} | ||
bytecode = compile(script, unique_filename, "exec") | ||
attr_dict = dict((a.name, a) for a in attrs) | ||
exec_(bytecode, {"NOTHING": NOTHING, "attr_dict": attr_dict}, locs) | ||
init = locs["__init__"] | ||
|
||
# In order of debuggers like PDB being able to step through the code, | ||
# we add a fake linecache entry. | ||
linecache.cache[unique_filename] = ( | ||
len(script), | ||
None, | ||
script.splitlines(True), | ||
unique_filename | ||
) | ||
cl.__init__ = init | ||
return cl | ||
|
||
|
||
def _attrs_to_script(attrs): | ||
""" | ||
Return a valid Python script of an initializer for *attrs*. | ||
""" | ||
lines = [] | ||
args = [] | ||
for a in attrs: | ||
if a.default_value is not NOTHING: | ||
args.append("{name}={default!r}".format(name=a.name, | ||
default=a.default_value)) | ||
lines.append("self.{name} = {name}".format(name=a.name)) | ||
elif a.default_factory is not NOTHING: | ||
args.append("{name}=NOTHING".format(name=a.name)) | ||
lines.extend("""\ | ||
if {name} is not NOTHING: | ||
self.{name} = {name} | ||
else: | ||
self.{name} = attr_dict["{name}"].default_factory()""" | ||
.format(name=a.name) | ||
.split("\n")) | ||
else: | ||
args.append(a.name) | ||
lines.append("self.{name} = {name}".format(name=a.name)) | ||
|
||
return """\ | ||
def __init__(self, {args}): | ||
''' | ||
Attribute initializer automatically created by attrs. | ||
''' | ||
{setters} | ||
""".format( | ||
args=", ".join(args), | ||
setters="\n ".join(lines), | ||
) |
Oops, something went wrong.