/usr/share/pyshared/igraph/drawing/baseclasses.py is in python-igraph 0.6.5-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | """
Abstract base classes for the drawing routines.
"""
from igraph.compat import property
from igraph.drawing.utils import BoundingBox
from math import pi
#####################################################################
# pylint: disable-msg=R0903
# R0903: too few public methods
class AbstractDrawer(object):
"""Abstract class that serves as a base class for anything that
draws an igraph object."""
def draw(self, *args, **kwds):
"""Abstract method, must be implemented in derived classes."""
raise NotImplementedError("abstract class")
#####################################################################
# pylint: disable-msg=R0903
# R0903: too few public methods
class AbstractCairoDrawer(AbstractDrawer):
"""Abstract class that serves as a base class for anything that
draws on a Cairo context within a given bounding box.
A subclass of L{AbstractCairoDrawer} is guaranteed to have an
attribute named C{context} that represents the Cairo context
to draw on, and an attribute named C{bbox} for the L{BoundingBox}
of the drawing area.
"""
def __init__(self, context, bbox):
"""Constructs the drawer and associates it to the given
Cairo context and the given L{BoundingBox}.
@param context: the context on which we will draw
@param bbox: the bounding box within which we will draw.
Can be anything accepted by the constructor
of L{BoundingBox} (i.e., a 2-tuple, a 4-tuple
or a L{BoundingBox} object).
"""
self.context = context
self._bbox = None
self.bbox = bbox
@property
def bbox(self):
"""The bounding box of the drawing area where this drawer will
draw."""
return self._bbox
@bbox.setter
def bbox(self, bbox):
"""Sets the bounding box of the drawing area where this drawer
will draw."""
if not isinstance(bbox, BoundingBox):
self._bbox = BoundingBox(bbox)
else:
self._bbox = bbox
def draw(self, *args, **kwds):
"""Abstract method, must be implemented in derived classes."""
raise NotImplementedError("abstract class")
def _mark_point(self, x, y, color=0, size=4):
"""Marks the given point with a small circle on the canvas.
Used primarily for debugging purposes.
@param x: the X coordinate of the point to mark
@param y: the Y coordinate of the point to mark
@param color: the color of the marker. It can be a
3-tuple (RGB components, alpha=0.5), a 4-tuple
(RGBA components) or an index where zero means red, 1 means
green, 2 means blue and so on.
@param size: the diameter of the marker.
"""
if isinstance(color, int):
colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0),
(0, 1, 1), (1, 0, 1)]
color = colors[color % len(colors)]
if len(color) == 3:
color += (0.5, )
ctx = self.context
ctx.save()
ctx.set_source_rgba(*color)
ctx.arc(x, y, size / 2.0, 0, 2*pi)
ctx.fill()
ctx.restore()
#####################################################################
class AbstractXMLRPCDrawer(AbstractDrawer):
"""Abstract drawer that uses a remote service via XML-RPC
to draw something on a remote display.
"""
def __init__(self, url, service=None):
"""Constructs an abstract drawer using the XML-RPC service
at the given URL.
@param url: the URL where the XML-RPC calls for the service should
be addressed to.
@param service: the name of the service at the XML-RPC address. If
C{None}, requests will be directed to the server proxy object
constructed by C{xmlrpclib.ServerProxy}; if not C{None}, the
given attribute will be looked up in the server proxy object.
"""
import xmlrpclib
url = self._resolve_hostname(url)
self.server = xmlrpclib.ServerProxy(url)
if service is None:
self.service = self.server
else:
self.service = getattr(self.server, service)
@staticmethod
def _resolve_hostname(url):
"""Parses the given URL, resolves the hostname to an IP address
and returns a new URL with the resolved IP address. This speeds
up things big time on Mac OS X where an IP lookup would be
performed for every XML-RPC call otherwise."""
from urlparse import urlparse, urlunparse
import re
url_parts = urlparse(url)
hostname = url_parts.netloc
if re.match("[0-9.:]+$", hostname):
# the hostname is already an IP address, possibly with a port
return url
from socket import gethostbyname
if ":" in hostname:
hostname = hostname[0:hostname.index(":")]
hostname = gethostbyname(hostname)
if url_parts.port is not None:
hostname = "%s:%d" % (hostname, url_parts.port)
url_parts = list(url_parts)
url_parts[1] = hostname
return urlunparse(url_parts)
|