Skip to content

Commit

Permalink
moved type decorators to separate module, added boundable decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
maxfischer2781 committed Jul 29, 2018
1 parent aee0306 commit 119c5cb
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 42 deletions.
1 change: 1 addition & 0 deletions graphi/types/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# pull in submodules in correct order to avoid import cycle
from . import decorator as _decorator
from . import undirected as _undirected
from . import adjacency_graph as _adjacency_graph
3 changes: 2 additions & 1 deletion graphi/types/adjacency_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
from .. import edge


from .undirected import undirectable
from .decorator import boundable, undirectable


@boundable
@undirectable
class AdjacencyGraph(abc.Graph):
r"""
Expand Down
67 changes: 67 additions & 0 deletions graphi/types/decorator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from .. import abc


def boundable(graph_class):
assert issubclass(graph_class, abc.Graph), 'only subclasses of Graph can be bounded'
__new__ = graph_class.__new__

@staticmethod
def __new_graph__(cls, *args, **kwargs):
value_bound = kwargs.pop('value_bound', None)
super_new = __new__
if super_new is object.__new__:
self = super_new(cls)
else:
self = super_new(cls, *args, **kwargs)
if value_bound is not None: # replicates type.__call__
if isinstance(self, cls):
self.__init__(*args, **kwargs)
return Bounded(self, value_bound=value_bound)
else:
return self

graph_class.__new__ = __new_graph__
return graph_class


def undirectable(graph_class):
"""
Make an implementation of :py:class:`~.abc.Graph` undirectable by passing ``undirected=True`` to it
.. code:: python
@undirectable
class SomeGraph(abc.Graph):
...
directed_graph = SomeGraph()
undirected_graph = SomeGraph(undirected=True)
This provides an implementation agnostic interface to ensure all edges are undirected.
For any :term:`nodes <node>` ``a`` and ``b``, ``graph[a:b] == graph[b:a]`` always holds and
``graph.edges()`` produces only one of ``a:b`` or ``b:a``.
"""
assert issubclass(graph_class, abc.Graph), 'only subclasses of Graph can be undirected'
__new__ = graph_class.__new__

@staticmethod
def __new_graph__(cls, *args, **kwargs):
undirected = kwargs.pop('undirected', False)
super_new = __new__
if super_new is object.__new__:
self = super_new(cls)
else:
self = super_new(cls, *args, **kwargs)
if undirected: # replicates type.__call__
if isinstance(self, cls):
self.__init__(*args, **kwargs)
return Undirected(self)
else:
return self

graph_class.__new__ = __new_graph__
return graph_class


from .undirected import Undirected
from .bounded import Bounded
41 changes: 0 additions & 41 deletions graphi/types/undirected.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,6 @@

from .. import abc
from .. import edge


def undirectable(graph_class):
"""
Make an implementation of :py:class:`~.abc.Graph` undirectable by passing ``undirected=True`` to it
.. code:: python
@undirectable
class SomeGraph(abc.Graph):
...
directed_graph = SomeGraph()
undirected_graph = SomeGraph(undirected=True)
This provides an implementation agnostic interface to ensure all edges are undirected.
For any :term:`nodes <node>` ``a`` and ``b``, ``graph[a:b] == graph[b:a]`` always holds and
``graph.edges()`` produces only one of ``a:b`` or ``b:a``.
"""
assert issubclass(graph_class, abc.Graph), 'only subclasses of Graph can be undirected'

@staticmethod
def __new_graph__(cls, *args, **kwargs):
undirected = kwargs.pop('undirected', False)
super_new = super(graph_class, cls).__new__
if super_new is object.__new__:
self = super_new(cls)
else:
self = super_new(cls, *args, **kwargs)
if undirected: # replicates type.__call__
if isinstance(self, cls):
self.__init__(*args, **kwargs)
return Undirected(self)
else:
return self

graph_class.__new__ = __new_graph__
return graph_class


# import here to avoid cycle
from .adjacency_graph import AdjacencyGraph


Expand Down

0 comments on commit 119c5cb

Please sign in to comment.