def configure(self, target_address, source_address, handler, properties):
        """Assign addresses, properties, etc."""
        self._handler = handler
        self._properties = properties

        dynamic_props = None
        if properties:
            dynamic_props = properties.get("dynamic-node-properties")
            mode = _dist_modes.get(properties.get("distribution-mode"))
            if mode is not None:
                self._pn_link.source.distribution_mode = mode
            mode = _snd_settle_modes.get(properties.get("snd-settle-mode"))
            if mode is not None:
                self._pn_link.snd_settle_mode = mode
            mode = _rcv_settle_modes.get(properties.get("rcv-settle-mode"))
            if mode is not None:
                self._pn_link.rcv_settle_mode = mode

        if target_address is None:
            if not self._pn_link.is_sender:
                raise Exception("Dynamic target not allowed")
            self._pn_link.target.dynamic = True
            if dynamic_props:
                self._pn_link.target.properties.clear()
                self._pn_link.target.properties.put_dict(dynamic_props)
        elif target_address:
            self._pn_link.target.address = target_address

        if source_address is None:
            if not self._pn_link.is_receiver:
                raise Exception("Dynamic source not allowed")
            self._pn_link.source.dynamic = True
            if dynamic_props:
                self._pn_link.source.properties.clear()
                self._pn_link.source.properties.put_dict(dynamic_props)
        elif source_address:
            self._pn_link.source.address = source_address

def
configure
(
self
,
target_address
,
source_address
,
handler
,
properties
)
:
self
.
_handler
=
handler
self
.
_properties
=
properties
dynamic_props
=
if
properties
:
dynamic_props
=
properties
.
get
(
"dynamic-node-properties"
)
mode
=
_dist_modes
.
get
(
properties
.
get
(
"distribution-mode"
)
)
if
mode
is
not
:
self
.
_pn_link
.
source
.
distribution_mode
=
mode
mode
=
_snd_settle_modes
.
get
(
properties
.
get
(
"snd-settle-mode"
)
)
if
mode
is
not
:
self
.
_pn_link
.
snd_settle_mode
=
mode
mode
=
_rcv_settle_modes
.
get
(
properties
.
get
(
"rcv-settle-mode"
)
)
if
mode
is
not
:
self
.
_pn_link
.
rcv_settle_mode
=
mode
if
target_address
is
:
if
not
self
.
_pn_link
.
is_sender
:
raise
Exception
(
"Dynamic target not allowed"
)
self
.
_pn_link
.
target
.
dynamic
=
True
if
dynamic_props
:
self
.
_pn_link
.
target
.
properties
.
clear
(
)
self
.
_pn_link
.
target
.
properties
.
put_dict
(
dynamic_props
)
elif
target_address
:
self
.
_pn_link
.
target
.
address
=
target_address
if
source_address
is
:
if
not
self
.
_pn_link
.
is_receiver
:
raise
Exception
(
"Dynamic source not allowed"
)
self
.
_pn_link
.
source
.
dynamic
=
True
if
dynamic_props
:
self
.
_pn_link
.
source
.
properties
.
clear
(
)
self
.
_pn_link
.
source
.
properties
.
put_dict
(
dynamic_props
)
elif
source_address
:
self
.
_pn_link
.
source
.
address
=
source_address


def source_address(self):
        """Return the authorative source of the link."""
        # If link is a sender, source is determined by the local
        # value, else use the remote.
        if self._pn_link.is_sender:
            return self._pn_link.source.address
        else:
            return self._pn_link.remote_source.address

Return the authorative source of the link .


def target_address(self):
        """Return the authorative target of the link."""
        # If link is a receiver, target is determined by the local
        # value, else use the remote.
        if self._pn_link.is_receiver:
            return self._pn_link.target.address
        else:
            return self._pn_link.remote_target.address

Return the authorative target of the link .


def _session_closed(self):
        """Remote has closed the session used by this link."""
        # if link not already closed:
        if self._endpoint_state & proton.Endpoint.REMOTE_ACTIVE:
            # simulate close received
            self._process_remote_state()
        elif self._endpoint_state & proton.Endpoint.REMOTE_UNINIT:
            # locally created link, will never come up
            self._failed = True
            self._link_failed("Parent session closed.")

Remote has closed the session used by this link .


def new_sender(self, name):
        """Create a new sender link."""
        pn_link = self._pn_session.sender(name)
        return self.request_sender(pn_link)

def new_sender ( self , name ) : pn_link = self . _pn_session . sender ( name ) return self . request_sender ( pn_link )


def request_sender(self, pn_link):
        """Create link from request for a sender."""
        sl = SenderLink(self._connection, pn_link)
        self._links.add(sl)
        return sl

def request_sender ( self , pn_link ) : sl = SenderLink ( self . _connection , pn_link ) self . _links . add ( sl ) return sl


def new_receiver(self, name):
        """Create a new receiver link."""
        pn_link = self._pn_session.receiver(name)
        return self.request_receiver(pn_link)

def new_receiver ( self , name ) : pn_link = self . _pn_session . receiver ( name ) return self . request_receiver ( pn_link )


def request_receiver(self, pn_link):
        """Create link from request for a receiver."""
        rl = ReceiverLink(self._connection, pn_link)
        self._links.add(rl)
        return rl

def request_receiver ( self , pn_link ) : rl = ReceiverLink ( self . _connection , pn_link ) self . _links . add ( rl ) return rl

Create link from request for a receiver .


def link_destroyed(self, link):
        """Link has been destroyed."""
        self._links.discard(link)
        if not self._links:
            # no more links
            LOG.debug("destroying unneeded session")
            self._pn_session.close()
            self._pn_session.free()
            self._pn_session = None
            self._connection = None

def
link_destroyed
(
self
,
link
)
:
self
.
_links
.
discard
(
link
)
if
not
self
.
_links
:
# no more links
LOG
.
debug
(
"destroying unneeded session"
)
self
.
_pn_session
.
close
(
)
self
.
_pn_session
.
free
(
)
self
.
_pn_session
=
self
.
_connection
=


def _ep_need_close(self):
        """Peer has closed its end of the session."""
        LOG.debug("Session %s close requested - closing...",
                  self._name)
        links = self._links.copy()  # may modify _links
        for link in links:
            link._session_closed()

Peer has closed its end of the session .


def _process_endpoint_event(self, event):
        """Called when the Proton Engine generates an endpoint state change
        event.
        """
        state_fsm = Endpoint._FSM[self._state]
        entry = state_fsm.get(event)
        if not entry:
            # protocol error: invalid event for current state
            old_state = self._state
            self._state = Endpoint.STATE_ERROR
            self._ep_error("invalid event=%s in state=%s" %
                           (Endpoint.EVENT_NAMES[event],
                            Endpoint.STATE_NAMES[old_state]))
            return

        self._state = entry[0]
        if entry[1]:
            entry[1](self)

Called when the Proton Engine generates an endpoint state change event .


def extendMarkdown(self, md, md_globals):
        """Modifies inline patterns."""
        mark_tag = SimpleTagPattern(MARK_RE, 'mark')
        md.inlinePatterns.add('mark', mark_tag, '_begin')

def extendMarkdown ( self , md , md_globals ) : mark_tag = SimpleTagPattern ( MARK_RE , 'mark' ) md . inlinePatterns . add ( 'mark' , mark_tag , '_begin' )


def receiver_remote_closed(self, receiver_link, pn_condition):
        """Peer has closed its end of the link."""
        LOG.debug("receiver_remote_closed condition=%s", pn_condition)
        receiver_link.close()
        self.done = True

def
receiver_remote_closed
(
self
,
receiver_link
,
pn_condition
)
:
LOG
.
debug
(
"receiver_remote_closed condition=%s"
,
pn_condition
)
receiver_link
.
close
(
)
self
.
done
=
True


def receiver_failed(self, receiver_link, error):
        """Protocol error occurred."""
        LOG.warn("receiver_failed error=%s", error)
        receiver_link.close()
        self.done = True

def
receiver_failed
(
self
,
receiver_link
,
error
)
:
LOG
.
warn
(
"receiver_failed error=%s"
,
error
)
receiver_link
.
close
(
)
self
.
done
=
True


def get_host_port(server_address):
    """Parse the hostname and port out of the server_address."""
    regex = re.compile(r"^amqp://([a-zA-Z0-9.]+)(:([\d]+))?$")
    x = regex.match(server_address)
    if not x:
        raise Exception("Bad address syntax: %s" % server_address)
    matches = x.groups()
    host = matches[0]
    port = int(matches[2]) if matches[2] else None
    return host, port

def
get_host_port
(
server_address
)
:
regex
=
re
.
compile
(
r"^amqp://([a-zA-Z0-9.]+)(:([\d]+))?$"
)
x
=
regex
.
match
(
server_address
)
if
not
x
:
raise
Exception
(
"Bad address syntax: %s"
%
server_address
)
matches
=
x
.
groups
(
)
host
=
matches
[
0
]
port
=
int
(
matches
[
2
]
)
if
matches
[
2
]
else
return
host
,
port

Parse the hostname and port out of the server_address .


def connect_socket(host, port, blocking=True):
    """Create a TCP connection to the server."""
    addr = socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM)
    if not addr:
        raise Exception("Could not translate address '%s:%s'"
                        % (host, str(port)))
    my_socket = socket.socket(addr[0][0], addr[0][1], addr[0][2])
    if not blocking:
        my_socket.setblocking(0)
    try:
        my_socket.connect(addr[0][4])
    except socket.error as e:
        if e.errno != errno.EINPROGRESS:
            raise
    return my_socket

def
connect_socket
(
host
,
port
,
blocking
=
True
)
:
addr
=
socket
.
getaddrinfo
(
host
,
port
,
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
if
not
addr
:
raise
Exception
(
"Could not translate address '%s:%s'"
%
(
host
,
str
(
port
)
)
)
my_socket
=
socket
.
socket
(
addr
[
0
]
[
0
]
,
addr
[
0
]
[
1
]
,
addr
[
0
]
[
2
]
)
if
not
blocking
:
my_socket
.
setblocking
(
0
)
try
:
my_socket
.
connect
(
addr
[
0
]
[
4
]
)
except
socket
.
error
as
e
:
if
e
.
errno
!=
errno
.
EINPROGRESS
:
raise
return
my_socket


def server_socket(host, port, backlog=10):
    """Create a TCP listening socket for a server."""
    addr = socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM)
    if not addr:
        raise Exception("Could not translate address '%s:%s'"
                        % (host, str(port)))
    my_socket = socket.socket(addr[0][0], addr[0][1], addr[0][2])
    my_socket.setblocking(0)  # 0=non-blocking
    try:
        my_socket.bind(addr[0][4])
        my_socket.listen(backlog)
    except socket.error as e:
        if e.errno != errno.EINPROGRESS:
            raise
    return my_socket

def
server_socket
(
host
,
port
,
backlog
=
10
)
:
addr
=
socket
.
getaddrinfo
(
host
,
port
,
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
if
not
addr
:
raise
Exception
(
"Could not translate address '%s:%s'"
%
(
host
,
str
(
port
)
)
)
my_socket
=
socket
.
socket
(
addr
[
0
]
[
0
]
,
addr
[
0
]
[
1
]
,
addr
[
0
]
[
2
]
)
my_socket
.
setblocking
(
0
)
# 0=non-blocking
try
:
my_socket
.
bind
(
addr
[
0
]
[
4
]
)
my_socket
.
listen
(
backlog
)
except
socket
.
error
as
e
:
if
e
.
errno
!=
errno
.
EINPROGRESS
:
raise
return
my_socket

Create a TCP listening socket for a server .


def need_processing(self):
        """A utility to help determine which connections need
        processing. Returns a triple of lists containing those connections that
        0) need to read from the network, 1) need to write to the network, 2)
        waiting for pending timers to expire.  The timer list is sorted with
        the connection next expiring at index 0.
        """
        readers = []
        writers = []
        timer_heap = []
        for c in iter(self._connections.values()):
            if c.needs_input > 0:
                readers.append(c)
            if c.has_output > 0:
                writers.append(c)
            if c.deadline:
                heapq.heappush(timer_heap, (c.next_tick, c))
        timers = []
        while timer_heap:
            x = heapq.heappop(timer_heap)
            timers.append(x[1])

        return (readers, writers, timers)

def need_processing ( self ) : readers = [ ] writers = [ ] timer_heap = [ ] for c in iter ( self . _connections . values ( ) ) : if c . needs_input > 0 : readers . append ( c ) if c . has_output > 0 : writers . append ( c ) if c . deadline : heapq . heappush ( timer_heap , ( c . next_tick , c ) ) timers = [ ] while timer_heap : x = heapq . heappop ( timer_heap ) timers . append ( x [ 1 ] ) return ( readers , writers , timers )

A utility to help determine which connections need processing . Returns a triple of lists containing those connections that 0 ) need to read from the network 1 ) need to write to the network 2 ) waiting for pending timers to expire . The timer list is sorted with the connection next expiring at index 0 .


def _not_reentrant(func):
        """Decorator that prevents callbacks from calling into methods that are
        not reentrant
        """
        def wrap(self, *args, **kws):
            if self._callback_lock and self._callback_lock.in_callback:
                m = "Connection %s cannot be invoked from a callback!" % func
                raise RuntimeError(m)
            return func(self, *args, **kws)
        return wrap


def process(self, now):
        """Perform connection state processing."""
        if self._pn_connection is None:
            LOG.error("Connection.process() called on destroyed connection!")
            return 0

        # do nothing until the connection has been opened
        if self._pn_connection.state & proton.Endpoint.LOCAL_UNINIT:
            return 0

        if self._pn_sasl and not self._sasl_done:
            # wait until SASL has authenticated
            if (_PROTON_VERSION < (0, 10)):
                if self._pn_sasl.state not in (proton.SASL.STATE_PASS,
                                               proton.SASL.STATE_FAIL):
                    LOG.debug("SASL in progress. State=%s",
                              str(self._pn_sasl.state))
                    if self._handler:
                        with self._callback_lock:
                            self._handler.sasl_step(self, self._pn_sasl)
                    return self._next_deadline

                self._sasl_done = True
                if self._handler:
                    with self._callback_lock:
                        self._handler.sasl_done(self, self._pn_sasl,
                                                self._pn_sasl.outcome)
            else:
                if self._pn_sasl.outcome is not None:
                    self._sasl_done = True
                    if self._handler:
                        with self._callback_lock:
                            self._handler.sasl_done(self, self._pn_sasl,
                                                    self._pn_sasl.outcome)

        # process timer events:
        timer_deadline = self._expire_timers(now)
        transport_deadline = self._pn_transport.tick(now)
        if timer_deadline and transport_deadline:
            self._next_deadline = min(timer_deadline, transport_deadline)
        else:
            self._next_deadline = timer_deadline or transport_deadline

        # process events from proton:
        pn_event = self._pn_collector.peek()
        while pn_event:
            # LOG.debug("pn_event: %s received", pn_event.type)
            if _Link._handle_proton_event(pn_event, self):
                pass
            elif self._handle_proton_event(pn_event):
                pass
            elif _SessionProxy._handle_proton_event(pn_event, self):
                pass
            self._pn_collector.pop()
            pn_event = self._pn_collector.peek()

        # check for connection failure after processing all pending
        # engine events:
        if self._error:
            if self._handler:
                # nag application until connection is destroyed
                self._next_deadline = now
                with self._callback_lock:
                    self._handler.connection_failed(self, self._error)
        elif (self._endpoint_state == self._CLOSED and
              self._read_done and self._write_done):
            # invoke closed callback after endpoint has fully closed and
            # all pending I/O has completed:
            if self._handler:
                with self._callback_lock:
                    self._handler.connection_closed(self)

        return self._next_deadline


def output_data(self):
        """Get a buffer of data that needs to be written to the network.
        """
        c = self.has_output
        if c <= 0:
            return None
        try:
            buf = self._pn_transport.peek(c)
        except Exception as e:
            self._connection_failed(str(e))
            return None
        return buf

def output_data ( self ) : c = self . has_output if c <= 0 : return None try : buf = self . _pn_transport . peek ( c ) except Exception as e : self . _connection_failed ( str ( e ) ) return None return buf

Get a buffer of data that needs to be written to the network .


def create_sender(self, source_address, target_address=None,
                      event_handler=None, name=None, properties=None):
        """Factory method for Sender links."""
        ident = name or str(source_address)
        if ident in self._sender_links:
            raise KeyError("Sender %s already exists!" % ident)

        session = _SessionProxy("session-%s" % ident, self)
        session.open()
        sl = session.new_sender(ident)
        sl.configure(target_address, source_address, event_handler, properties)
        self._sender_links[ident] = sl
        return sl

def
create_sender
(
self
,
source_address
,
target_address
=
,
event_handler
=
,
name
=
,
properties
=
)
:
ident
=
name
or
str
(
source_address
)
if
ident
in
self
.
_sender_links
:
raise
KeyError
(
"Sender %s already exists!"
%
ident
)
session
=
_SessionProxy
(
"session-%s"
%
ident
,
self
)
session
.
open
(
)
sl
=
session
.
new_sender
(
ident
)
sl
.
configure
(
target_address
,
source_address
,
event_handler
,
properties
)
self
.
_sender_links
[
ident
]
=
sl
return
sl


def reject_sender(self, link_handle, pn_condition=None):
        """Rejects the SenderLink, and destroys the handle."""
        link = self._sender_links.get(link_handle)
        if not link:
            raise Exception("Invalid link_handle: %s" % link_handle)
        link.reject(pn_condition)
        # note: normally, link.destroy() cannot be called from a callback,
        # but this link was never made available to the application so this
        # link is only referenced by the connection
        link.destroy()

Rejects the SenderLink and destroys the handle .


def create_receiver(self, target_address, source_address=None,
                        event_handler=None, name=None, properties=None):
        """Factory method for creating Receive links."""
        ident = name or str(target_address)
        if ident in self._receiver_links:
            raise KeyError("Receiver %s already exists!" % ident)

        session = _SessionProxy("session-%s" % ident, self)
        session.open()
        rl = session.new_receiver(ident)
        rl.configure(target_address, source_address, event_handler, properties)
        self._receiver_links[ident] = rl
        return rl

def
create_receiver
(
self
,
target_address
,
source_address
=
,
event_handler
=
,
name
=
,
properties
=
)
:
ident
=
name
or
str
(
target_address
)
if
ident
in
self
.
_receiver_links
:
raise
KeyError
(
"Receiver %s already exists!"
%
ident
)
session
=
_SessionProxy
(
"session-%s"
%
ident
,
self
)
session
.
open
(
)
rl
=
session
.
new_receiver
(
ident
)
rl
.
configure
(
target_address
,
source_address
,
event_handler
,
properties
)
self
.
_receiver_links
[
ident
]
=
rl
return
rl

Factory method for creating Receive links .


def _connection_failed(self, error="Error not specified!"):
        """Clean up after connection failure detected."""
        if not self._error:
            LOG.error("Connection failed: %s", str(error))
            self._error = error

def
_connection_failed
(
self
,
error
=
"Error not specified!"
)
:
if
not
self
.
_error
:
LOG
.
error
(
"Connection failed: %s"
,
str
(
error
)
)
self
.
_error
=
error

Clean up after connection failure detected .


def _ep_active(self):
        """Both ends of the Endpoint have become active."""
        LOG.debug("Connection is up")
        if self._handler:
            with self._callback_lock:
                self._handler.connection_active(self)

def
_ep_active
(
self
)
:
LOG
.
debug
(
"Connection is up"
)
if
self
.
_handler
:
with
self
.
_callback_lock
:
self
.
_handler
.
connection_active
(
self
)

Both ends of the Endpoint have become active .


def _ep_need_close(self):
        """The remote has closed its end of the endpoint."""
        LOG.debug("Connection remotely closed")
        if self._handler:
            cond = self._pn_connection.remote_condition
            with self._callback_lock:
                self._handler.connection_remote_closed(self, cond)

def
_ep_need_close
(
self
)
:
LOG
.
debug
(
"Connection remotely closed"
)
if
self
.
_handler
:
cond
=
self
.
_pn_connection
.
remote_condition
with
self
.
_callback_lock
:
self
.
_handler
.
connection_remote_closed
(
self
,
cond
)

The remote has closed its end of the endpoint .


def _ep_error(self, error):
        """The endpoint state machine failed due to protocol error."""
        super(Connection, self)._ep_error(error)
        self._connection_failed("Protocol error occurred.")

def
_ep_error
(
self
,
error
)
:
super
(
Connection
,
self
)
.
_ep_error
(
error
)
self
.
_connection_failed
(
"Protocol error occurred."
)

The endpoint state machine failed due to protocol error .


def twilio_view(f):
    """This decorator provides several helpful shortcuts for writing Twilio
    views.

        - It ensures that only requests from Twilio are passed through. This
          helps protect you from forged requests.

        - It ensures your view is exempt from CSRF checks via Django's
          @csrf_exempt decorator. This is necessary for any view that accepts
          POST requests from outside the local domain (eg: Twilio's servers).

        - It allows your view to (optionally) return TwiML to pass back to
          Twilio's servers instead of building a ``HttpResponse`` object
          manually.

        - It allows your view to (optionally) return any ``twilio.Verb`` object
          instead of building a ``HttpResponse`` object manually.

    Usage::

        from twilio.twiml import Response

        @twilio_view
        def my_view(request):
            r = Response()
            r.sms("Thanks for the SMS message!")
            return r
    """
    @csrf_exempt
    @wraps(f)
    def decorator(request, *args, **kwargs):
        # Attempt to gather all required information to allow us to check the
        # incoming HTTP request for forgery. If any of this information is not
        # available, then we'll throw a HTTP 403 error (forbidden).

        # Ensure the request method is POST
        if request.method != "POST":
            logger.error("Twilio: Expected POST request", extra={"request": request})
            return HttpResponseNotAllowed(request.method)

        if not getattr(settings, "TWILIO_SKIP_SIGNATURE_VALIDATION"):
            # Validate the request
            try:
                validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)
                url = request.build_absolute_uri()
                # Ensure the original requested url is tested for validation
                # Prevents breakage when processed behind a proxy server
                if "HTTP_X_FORWARDED_SERVER" in request.META:
                    protocol = "https" if request.META["HTTP_X_TWILIO_SSL"] == "Enabled" else "http"
                    url = "{0}://{1}{2}".format(
                        protocol, request.META["HTTP_X_FORWARDED_SERVER"], request.META["REQUEST_URI"]
                    )
                signature = request.META["HTTP_X_TWILIO_SIGNATURE"]
            except (AttributeError, KeyError) as e:
                logger.exception("Twilio: Missing META param", extra={"request": request})
                return HttpResponseForbidden("Missing META param: %s" % e)

            # Now that we have all the required information to perform forgery
            # checks, we'll actually do the forgery check.
            if not validator.validate(url, request.POST, signature):
                logger.error(
                    "Twilio: Invalid url signature %s - %s - %s",
                    url, request.POST, signature, extra={"request": request}
                )
                return HttpResponseForbidden("Invalid signature")

        # Run the wrapped view, and capture the data returned.
        response = f(request, *args, **kwargs)

        # If the view returns a string (or a ``twilio.Verb`` object), we'll
        # assume it is XML TwilML data and pass it back with the appropriate
        # mimetype. We won't check the XML data because that would be too time
        # consuming for every request. Instead, we'll let the errors pass
        # through to be dealt with by the developer.
        if isinstance(response, six.text_type):
            return HttpResponse(response, mimetype="application/xml")
        elif isinstance(response, Verb):
            return HttpResponse(force_text(response), mimetype="application/xml")
        else:
            return response
    return decorator

This decorator provides several helpful shortcuts for writing Twilio views .


def _get_color_string(self):
        """Adobe output string for defining colors"""
        s = ''
        if self.color_type == 'd':
            if self.name is "black":
                s = '%.3f G' % 0
            else:
                s = '%.3f %.3f %.3f RG' % (
                    self.red / 255.0, self.green / 255.0, self.blue / 255.0)
        elif self.color_type == 'f' or self.color_type == 't':
            if self.name is "black":
                s = '%.3f g' % 0
            else:
                s = '%.3f %.3f %.3f rg' % (
                    self.red / 255.0, self.green / 255.0, self.blue / 255.0)
        return s

def
_get_color_string
(
self
)
:
s
=
''
if
self
.
color_type
==
'd'
:
if
self
.
name
is
"black"
:
s
=
'%.3f G'
%
0
else
:
s
=
'%.3f %.3f %.3f RG'
%
(
self
.
red
/
255.0
,
self
.
green
/
255.0
,
self
.
blue
/
255.0
)
elif
self
.
color_type
==
'f'
or
self
.
color_type
==
't'
:
if
self
.
name
is
"black"
:
s
=
'%.3f g'
%
0
else
:
s
=
'%.3f %.3f %.3f rg'
%
(
self
.
red
/
255.0
,
self
.
green
/
255.0
,
self
.
blue
/
255.0
)
return
s


def get_ttf(self):
        """ Given a search path, find file with requested extension """
        font_dict = {}
        families = []
        rootdirlist = string.split(self.search_path, os.pathsep)

        #for rootdir in rootdirlist:
        #    rootdir = os.path.expanduser(rootdir)
        for dirName, subdirList, filelist in itertools.chain.from_iterable(os.walk(path) for path in rootdirlist):
            for item in filelist:
                root, ext = os.path.splitext(item)
                if ext == '.ttf':
                    if root[0].lower() in english:
                        source = os.path.join(dirName, item)
                        name = root.lower().replace('_', ' ')
                        if ' bold' in name:
                            name = name.replace(' bold', '_bold')
                            if ' italic' in name:
                                name = name.replace(' italic', '_italic')
                        elif 'bold' in name:
                            name = name.replace('bold', '_bold')
                            if 'italic' in name:
                                name = name.replace('italic', '_italic')
                        elif ' italic' in name:
                            name = name.replace(' italic', '_italic')
                        elif 'italic' in name:
                            name = name.replace('italic', '_italic')
                        elif 'oblique' in name:
                            name = name.replace('oblique', '_italic')
                        else:
                            families.append(name)
                        font_dict[name] = source
                    else:
                        source = os.path.join(dirName, item)
                        name = root.lower().replace('_', ' ')
                        font_dict[name] = source
                        families.append(name)
        self.font_dict = font_dict
        self.families = families

#    rootdir = os.path.expanduser(rootdir)

Given a search path find file with requested extension


def _set_compression(self, value):
        """ May be used to compress PDF files. Code is more readable
            for testing and inspection if not compressed. Requires a boolean. """
        if isinstance(value, bool):
            self.compression = value
        else:
            raise Exception(
                TypeError, "%s is not a valid option for compression" % value)

May be used to compress PDF files . Code is more readable for testing and inspection if not compressed . Requires a boolean .


def _add_object(self, flag=None):
        """ The flag is a simple integer to force the placement
            of the object into position in the object array.
            Used for overwriting the placeholder objects.

        """
        self.offset = len(self.buffer)
        if flag is None:
            objnum = len(self.objects)
            obj = _PDFObject(objnum, self.offset)
            self.objects.append(obj)
        else:
            objnum = flag
            obj = _PDFObject(objnum, self.offset)
            self.objects[flag] = obj
        self._out(str(objnum) + ' 0 obj')
        return obj

def
_add_object
(
self
,
flag
=
)
:
self
.
offset
=
len
(
self
.
buffer
)
if
flag
is
:
objnum
=
len
(
self
.
objects
)
obj
=
_PDFObject
(
objnum
,
self
.
offset
)
self
.
objects
.
append
(
obj
)
else
:
objnum
=
flag
obj
=
_PDFObject
(
objnum
,
self
.
offset
)
self
.
objects
[
flag
]
=
obj
self
.
_out
(
str
(
objnum
)
+
' 0 obj'
)
return
obj

The flag is a simple integer to force the placement of the object into position in the object array . Used for overwriting the placeholder objects .


def _out(self, stream, page=None):
        """ Stores the pdf code in a buffer. If it is page related,
            provide the page object.

        """
        if page is not None:
            page.buffer += str(stream) + "\n"
        else:
            self.buffer += str(stream) + "\n"

def _out ( self , stream , page = None ) : if page is not None : page . buffer += str ( stream ) + "\n" else : self . buffer += str ( stream ) + "\n"

Stores the pdf code in a buffer . If it is page related provide the page object .


def _put_stream(self, stream):
        """ Creates a PDF text stream sandwich.

        """
        self._out('stream')
        self._out(stream)
        self._out('endstream')

def _put_stream ( self , stream ) : self . _out ( 'stream' ) self . _out ( stream ) self . _out ( 'endstream' )


def _add_page(self, text):
        """ Helper function for PDFText, to have the document
            add a page, and retry adding a large block of
            text that would otherwise have been to long for the
            page.

        """
        save_cursor = self.parent.document.page.cursor.copy()
        save_cursor.x_reset()
        save_cursor.y_reset()
        self.parent.document.add_page()
        self.parent.document.set_cursor(save_cursor)
        self.parent.document.add_text(text)

def _add_page ( self , text ) : save_cursor = self . parent . document . page . cursor . copy ( ) save_cursor . x_reset ( ) save_cursor . y_reset ( ) self . parent . document . add_page ( ) self . parent . document . set_cursor ( save_cursor ) self . parent . document . add_text ( text )

Helper function for PDFText to have the document add a page and retry adding a large block of text that would otherwise have been to long for the page .


def _set_color_scheme(self, draw_color=None, fill_color=None, text_color=None):
        """ Default color object is black letters
            & black lines."""
        if draw_color is None:
            draw_color = PDFColor()
            draw_color._set_type('d')
        if fill_color is None:
            fill_color = PDFColor()
            fill_color._set_type('f')
        if text_color is None:
            text_color = PDFColor()
            text_color._set_type('t')

        self.draw_color = draw_color
        self.fill_color = fill_color
        self.text_color = text_color

def _set_color_scheme ( self , draw_color = None , fill_color = None , text_color = None ) : if draw_color is None : draw_color = PDFColor ( ) draw_color . _set_type ( 'd' ) if fill_color is None : fill_color = PDFColor ( ) fill_color . _set_type ( 'f' ) if text_color is None : text_color = PDFColor ( ) text_color . _set_type ( 't' ) self . draw_color = draw_color self . fill_color = fill_color self . text_color = text_color

Default color object is black letters & black lines .


def _set_default_font(self):
        """ Internal method to set the initial default font. Change
            the font using set_font method."""
        self.font = PDFFont(self.session)
        self.font._set_index()
        self.fonts.append(self.font)
        self.fontkeys.append(self.font.font_key)

def _set_default_font ( self ) : self . font = PDFFont ( self . session ) self . font . _set_index ( ) self . fonts . append ( self . font ) self . fontkeys . append ( self . font . font_key )

Internal method to set the initial default font . Change the font using set_font method .


def add_page(self, page=None):
        """ May generate and add a PDFPage separately, or use this to generate
            a default page."""
        if page is None:
            self.page = PDFPage(self.orientation_default, self.layout_default, self.margins)
        else:
            self.page = page
        self.page._set_index(len(self.pages))
        self.pages.append(self.page)
        currentfont = self.font
        self.set_font(font=currentfont)
        self.session._reset_colors()

def add_page ( self , page = None ) : if page is None : self . page = PDFPage ( self . orientation_default , self . layout_default , self . margins ) else : self . page = page self . page . _set_index ( len ( self . pages ) ) self . pages . append ( self . page ) currentfont = self . font self . set_font ( font = currentfont ) self . session . _reset_colors ( )

May generate and add a PDFPage separately or use this to generate a default page .


def set_font_size(self, size):
        """Convenience method for just changing font size."""
        if self.font.font_size == size:
            pass
        else:
            self.font._set_size(size)

def set_font_size ( self , size ) : if self . font . font_size == size : pass else : self . font . _set_size ( size )

Convenience method for just changing font size .


def add_text(self, text, cursor=None, justification=None):
        """ Input text, short or long. Writes in order, within the defined page boundaries. Sequential add_text commands will print without
            additional whitespace. """
        if cursor is None:
            cursor = self.page.cursor

        text = re.sub("\s\s+" , " ", text)

        if justification is None:
            justification = self.justification

        if '\n' in text:
            text_list = text.split('\n')
            for text in text_list:
                PDFText(self.session, self.page, text, self.font, self.text_color, cursor, justification, self.double_spacing)
                self.add_newline()
        else:
            PDFText(self.session, self.page, text, self.font, self.text_color, cursor, justification, self.double_spacing)

def
add_text
(
self
,
text
,
cursor
=
,
justification
=
)
:
if
cursor
is
:
cursor
=
self
.
page
.
cursor
text
=
re
.
sub
(
"\s\s+"
,
" "
,
text
)
if
justification
is
:
justification
=
self
.
justification
if
'\n'
in
text
:
text_list
=
text
.
split
(
'\n'
)
for
text
in
text_list
:
PDFText
(
self
.
session
,
self
.
page
,
text
,
self
.
font
,
self
.
text_color
,
cursor
,
justification
,
self
.
double_spacing
)
self
.
add_newline
(
)
else
:
PDFText
(
self
.
session
,
self
.
page
,
text
,
self
.
font
,
self
.
text_color
,
cursor
,
justification
,
self
.
double_spacing
)

Input text short or long . Writes in order within the defined page boundaries . Sequential add_text commands will print without additional whitespace .


def add_newline(self, number=1):
        """ Starts over again at the new line. If number is specified,
            it will leave multiple lines."""
        if isinstance(number, int):
            try:
                self.page._add_newline(self.font, number, self.double_spacing)
            except ValueError:
                self.add_page()
        else:
            raise TypeError("Number of newlines must be an integer.")

Starts over again at the new line . If number is specified it will leave multiple lines .


def add_pie_chart(self, data, cursor, width, height, title=None, data_type="raw", fill_colors=None, labels=False, background=None, legend=None):
        """ Data type may be "raw" or "percent" """
        save_draw_color = self.draw_color
        save_fill_color = self.fill_color

        chart = PDFPieChart(self.session, self.page, data, cursor, width, height, title, data_type, fill_colors, labels, background, legend)

        self.set_draw_color(save_draw_color)
        self.set_fill_color(save_fill_color)

def add_pie_chart ( self , data , cursor , width , height , title = None , data_type = "raw" , fill_colors = None , labels = False , background = None , legend = None ) : save_draw_color = self . draw_color save_fill_color = self . fill_color chart = PDFPieChart ( self . session , self . page , data , cursor , width , height , title , data_type , fill_colors , labels , background , legend ) self . set_draw_color ( save_draw_color ) self . set_fill_color ( save_fill_color )


def _output_pages(self):
        """ Called by the PDFLite object to prompt creating
            the page objects."""
        if not self.orientation_changes:
            self._get_orientation_changes()

        # Page
        for page in self.pages:
            obj = self.session._add_object()
            self.session._out('<</Type /Page')
            self.session._out('/Parent 1 0 R')
            if self.orientation_changes:
                self.session._out('/MediaBox [0 0 %.2f %.2f]' % (page.width, page.height))
            self.session._out('/Resources 2 0 R')
            self.session._out('/Group <</Type /Group /S /Transparency /CS /DeviceRGB>>')
            self.session._out('/Contents %s 0 R>>' % (obj.id + 1))
            self.session._out('endobj')

            # Page content
            self.session._add_object()
            if self.session.compression is True:
                textfilter = ' /Filter /FlateDecode '
                page._compress()
            else:
                textfilter = ''
            self.session._out('<<%s/Length %s >>' % (textfilter, len(page.buffer)))
            self.session._put_stream(page.buffer)
            self.session._out('endobj')

Called by the PDFLite object to prompt creating the page objects .


def _get_orientation_changes(self):
        """ Returns a list of the pages that have
            orientation changes."""
        self.orientation_changes = []
        for page in self.pages:
            if page.orientation_change is True:
                self.orientation_changes.append(page.index)
            else:
                pass
        return self.orientation_changes

def _get_orientation_changes ( self ) : self . orientation_changes = [ ] for page in self . pages : if page . orientation_change is True : self . orientation_changes . append ( page . index ) else : pass return self . orientation_changes

Returns a list of the pages that have orientation changes .


def _output_fonts(self):
        """ Called by the PDFLite object to prompt creating
            the font objects."""
        self.session._save_object_number()
        self._output_encoding_diffs()
        self._output_font_files()

        for font in self.fonts:
            obj = self.session._add_object()
            font._set_number(obj.id)
            font._output()

def _output_fonts ( self ) : self . session . _save_object_number ( ) self . _output_encoding_diffs ( ) self . _output_font_files ( ) for font in self . fonts : obj = self . session . _add_object ( ) font . _set_number ( obj . id ) font . _output ( )

Called by the PDFLite object to prompt creating the font objects .


def _output_images(self):
        """ Creates reference images, that can be
            drawn throughout the document."""
        for image in self.images:
            obj = self.session._add_object()
            image._set_number(obj.id)
            image._output()

def _output_images ( self ) : for image in self . images : obj = self . session . _add_object ( ) image . _set_number ( obj . id ) image . _output ( )

Creates reference images that can be drawn throughout the document .


def _output(self):
        """ Prompts the creating of image objects.

        """
        self.session._out('<</Type /XObject')
        self.session._out('/Subtype /Image')
        self.session._out('/Width %s' % self.width)
        self.session._out('/Height %s' % self.height)

        if self.colorspace is 'Indexed':
            self.session._out('/ColorSpace [/Indexed /DeviceRGB %s %s 0 R' %
                              (self.pal, self.number + 1))
        else:
            self.session._out('/ColorSpace /%s' % self.colorspace)
            if self.colorspace is 'DeviceCMYK':
                self.session._out('/Decode [1 0 1 0 1 0 1 0]')

        self.session._out('/BitsPerComponent %s' % self.bits_per_component)

        if self.filter:
            self.session._out('/Filter /%s' % self.filter)
        if self.decode:
            self.session._out('/DecodeParms << %s >>' % self.decode)
        if self.transparent:
            self.session._out('/Mask [%s]' % self.transparent_string)
        if self.soft_mask:
            self.session._out('/SMask %s 0 R' % (self.number + 1))
        self.session._out('/Length %s >>' % self.size)
        self.session._put_stream(self.image_data)
        self.session._out('endobj')

        if self.colorspace is 'Indexed':
            self.session._out('<<%s /Length %s >>' % (self.palette_filter, self.palette_length))
            self.session._put_stream(self.palette)
            self.session._out('endobj')

        if isinstance(self.soft_mask, PDFImage):
            obj = self.session._add_object()
            self.soft_mask._set_number(obj.id)
            self.soft_mask._output()


def transform(self, a, b, c, d, e, f):
        """ Adjust the current transformation state of the current graphics state
        matrix. Not recommended for the faint of heart.
        """
        a0, b0, c0, d0, e0, f0 = self._currentMatrix
        self._currentMatrix = (a0 * a + c0 * b, b0 * a + d0 * b,
                               a0 * c + c0 * d, b0 * c + d0 * d,
                               a0 * e + c0 * f + e0, b0 * e + d0 * f + f0)
        a1, b1, c1, d1, e1, f1 = self._currentMatrix
        self.session._out('%.2f %.2f %.2f %.2f %.2f %.2f cm' % (a1, b1, c1, d1, e1, f1), self.page)

def
transform
(
self
,
a
,
b
,
c
,
d
,
e
,
f
)
:
a0
,
b0
,
c0
,
d0
,
e0
,
f0
=
self
.
_currentMatrix
self
.
_currentMatrix
=
(
a0
*
a
+
c0
*
b
,
b0
*
a
+
d0
*
b
,
a0
*
c
+
c0
*
d
,
b0
*
c
+
d0
*
d
,
a0
*
e
+
c0
*
f
+
e0
,
b0
*
e
+
d0
*
f
+
f0
)
a1
,
b1
,
c1
,
d1
,
e1
,
f1
=
self
.
_currentMatrix
self
.
session
.
_out
(
'%.2f %.2f %.2f %.2f %.2f %.2f cm'
%
(
a1
,
b1
,
c1
,
d1
,
e1
,
f1
)
,
self
.
page
)

Adjust the current transformation state of the current graphics state matrix . Not recommended for the faint of heart .


def absolute_position(self, x, y):
        """return the absolute position of x,y in user space w.r.t. default user space"""
        (a, b, c, d, e, f) = self._currentMatrix
        xp = a * x + c * y + e
        yp = b * x + d * y + f
        return xp, yp

def absolute_position ( self , x , y ) : ( a , b , c , d , e , f ) = self . _currentMatrix xp = a * x + c * y + e yp = b * x + d * y + f return xp , yp

return the absolute position of x y in user space w . r . t . default user space


def _set_style(self, style=None):
        """ Style should be a string, containing the letters 'B' for bold,
        'U' for underline, or 'I' for italic, or should be '', for no style.
        Symbol will not be underlined. The underline style can further be
        modified by specifying the underline thickness and position.

        """
        if style is None:
            self.style = ''
            self.underline = False
        # No syling for symbol
        elif self.family == ('symbol' or 'zapfdingbats'):
            self.style = ''
            self.underline = False

        self.style = style.upper()
            # SetUnderline

        if 'U' in self.style or self.style == 'U':
            self.underline = True
        else:
            self.underline = False

def
_set_style
(
self
,
style
=
)
:
if
style
is
:
self
.
style
=
''
self
.
underline
=
False
# No syling for symbol
elif
self
.
family
==
(
'symbol'
or
'zapfdingbats'
)
:
self
.
style
=
''
self
.
underline
=
False
self
.
style
=
style
.
upper
(
)
# SetUnderline
if
'U'
in
self
.
style
or
self
.
style
==
'U'
:
self
.
underline
=
True
else
:
self
.
underline
=
False

Style should be a string containing the letters B for bold U for underline or I for italic or should be for no style . Symbol will not be underlined . The underline style can further be modified by specifying the underline thickness and position .


def rotatePoint(self, pointX, pointY):
        """
        Rotates a point relative to the mesh origin by the angle specified in the angle property.
        Uses the angle formed between the segment linking the point of interest to the origin and
        the parallel intersecting the origin. This angle is called beta in the code.
        """
        if(self.angle == 0 or self.angle == None):
            return(pointX, pointY)

        # 1. Compute the segment length
        length = math.sqrt((pointX - self.xll) ** 2 + (pointY - self.yll) ** 2)

        # 2. Compute beta
        beta = math.acos((pointX - self.xll) / length)
        if(pointY < self.yll):
            beta = math.pi * 2 - beta

        # 3. Compute offsets
        offsetX = math.cos(beta) * length - math.cos(self._angle_rd + beta) * length
        offsetY = math.sin(self._angle_rd + beta) * length - math.sin(beta) * length
        return (pointX - offsetX, pointY + offsetY)

def
rotatePoint
(
self
,
pointX
,
pointY
)
:
if
(
self
.
angle
==
0
or
self
.
angle
==
)
:
return
(
pointX
,
pointY
)
# 1. Compute the segment length
length
=
math
.
sqrt
(
(
pointX
self
.
xll
)
**
2
+
(
pointY
self
.
yll
)
**
2
)
# 2. Compute beta
beta
=
math
.
acos
(
(
pointX
self
.
xll
)
/
length
)
if
(
pointY
<
self
.
yll
)
:
beta
=
math
.
pi
*
2
beta
# 3. Compute offsets
offsetX
=
math
.
cos
(
beta
)
*
length
math
.
cos
(
self
.
_angle_rd
+
beta
)
*
length
offsetY
=
math
.
sin
(
self
.
_angle_rd
+
beta
)
*
length
math
.
sin
(
beta
)
*
length
return
(
pointX
offsetX
,
pointY
+
offsetY
)

Rotates a point relative to the mesh origin by the angle specified in the angle property . Uses the angle formed between the segment linking the point of interest to the origin and the parallel intersecting the origin . This angle is called beta in the code .


def set_information(self, title=None, subject=None, author=None, keywords=None, creator=None):
        """ Convenience function to add property info, can set any attribute and leave the others blank, it won't over-write
            previously set items. """
        info_dict = {"title": title, "subject": subject,
                     "author": author, "keywords": keywords,
                     "creator": creator}

        for att, value in info_dict.iteritems():
            if hasattr(self, att):
                if value:
                    setattr(self, att, value)
            else:
                setattr(self, att, None)

def set_information ( self , title = None , subject = None , author = None , keywords = None , creator = None ) : info_dict = { "title" : title , "subject" : subject , "author" : author , "keywords" : keywords , "creator" : creator } for att , value in info_dict . iteritems ( ) : if hasattr ( self , att ) : if value : setattr ( self , att , value ) else : setattr ( self , att , None )

Convenience function to add property info can set any attribute and leave the others blank it won t over - write previously set items .


def set_display_mode(self, zoom='fullpage', layout='continuous'):
        """ Set the default viewing options. """
        self.zoom_options = ["fullpage", "fullwidth", "real", "default"]
        self.layout_options = ["single", "continuous", "two", "default"]

        if zoom in self.zoom_options or (isinstance(zoom, int) and 0 < zoom <= 100):
            self.zoom_mode = zoom
        else:
            raise Exception('Incorrect zoom display mode: ' + zoom)

        if layout in self.layout_options:
            self.layout_mode = layout
        else:
            raise Exception('Incorrect layout display mode: ' + layout)

def
set_display_mode
(
self
,
zoom
=
'fullpage'
,
layout
=
'continuous'
)
:
self
.
zoom_options
=
[
"fullpage"
,
"fullwidth"
,
"real"
,
"default"
]
self
.
layout_options
=
[
"single"
,
"continuous"
,
"two"
,
"default"
]
if
zoom
in
self
.
zoom_options
or
(
isinstance
(
zoom
,
int
)
and
0
<
zoom
<=
100
)
:
self
.
zoom_mode
=
zoom
else
:
raise
Exception
(
'Incorrect zoom display mode: '
+
zoom
)
if
layout
in
self
.
layout_options
:
self
.
layout_mode
=
layout
else
:
raise
Exception
(
'Incorrect layout display mode: '
+
layout
)


def close(self):
        """ Prompt the objects to output pdf code, and save to file. """
        self.document._set_page_numbers()
        # Places header, pages, page content first.
        self._put_header()
        self._put_pages()
        self._put_resources()
        # Information object
        self._put_information()
        # Catalog object
        self._put_catalog()
        # Cross-reference object
        #self._put_cross_reference()
        # Trailer object
        self._put_trailer()

        if hasattr(self.destination, "write"):
            output = self._output_to_io()
        elif self.destination == 'string':
            output = self._output_to_string()
        else:
            self._output_to_file()
            output = None
        return output

Prompt the objects to output pdf code and save to file .


def _put_header(self):
        """ Standard first line in a PDF. """
        self.session._out('%%PDF-%s' % self.pdf_version)
        if self.session.compression:
            self.session.buffer += '%' + chr(235) + chr(236) + chr(237) + chr(238) + "\n"

def _put_header ( self ) : self . session . _out ( '%%PDF-%s' % self . pdf_version ) if self . session . compression : self . session . buffer += '%' + chr ( 235 ) + chr ( 236 ) + chr ( 237 ) + chr ( 238 ) + "\n"


def _put_pages(self):
        """ First, the Document object does the heavy-lifting for the
            individual page objects and content.

            Then, the overall "Pages" object is generated.

        """
        self.document._get_orientation_changes()
        self.document._output_pages()

        # Pages Object, provides reference to page objects (Kids list).
        self.session._add_object(1)
        self.session._out('<</Type /Pages')
        kids = '/Kids ['
        for i in xrange(0, len(self.document.pages)):
            kids += str(3 + 2 * i) + ' 0 R '
        self.session._out(kids + ']')
        self.session._out('/Count %s' % len(self.document.pages))

        # Overall size of the default PDF page
        self.session._out('/MediaBox [0 0 %.2f %.2f]' %
                          (self.document.page.width,
                           self.document.page.height))
        self.session._out('>>')
        self.session._out('endobj')

First the Document object does the heavy - lifting for the individual page objects and content . Then the overall Pages object is generated .


def _put_resource_dict(self):
        """ Creates PDF reference to resource objects.

        """
        self.session._add_object(2)
        self.session._out('<<')
        self.session._out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]')
        self.session._out('/Font <<')
        for font in self.document.fonts:
            self.session._out('/F%s %s 0 R' % (font.index, font.number))
        self.session._out('>>')
        if self.document.images:
            self.session._out('/XObject <<')
            for image in self.document.images:
                self.session._out('/I%s %s 0 R' % (image.index, image.number))
            self.session._out('>>')
        self.session._out('>>')
        self.session._out('endobj')

Creates PDF reference to resource objects .


def _put_information(self):
        """PDF Information object."""
        self.session._add_object()
        self.session._out('<<')
        self.session._out('/Producer ' + self._text_to_string(
            'PDFLite, https://github.com/katerina7479'))
        if self.title:
            self.session._out('/Title ' + self._text_to_string(self.title))
        if self.subject:
            self.session._out('/Subject ' + self._text_to_string(self.subject))
        if self.author:
            self.session._out('/Author ' + self._text_to_string(self.author))
        if self.keywords:
            self.session._out('/Keywords ' +
                              self._text_to_string(self.keywords))
        if self.creator:
            self.session._out('/Creator ' + self._text_to_string(self.creator))
        self.session._out('/CreationDate ' + self._text_to_string(
            'D:' + datetime.now().strftime('%Y%m%d%H%M%S')))
        self.session._out('>>')
        self.session._out('endobj')


def _put_catalog(self):
        """Catalog object."""
        self.session._add_object()
        self.session._out('<<')

        self.session._out('/Type /Catalog')
        self.session._out('/Pages 1 0 R')
        if self.zoom_mode == 'fullpage':
            self.session._out('/OpenAction [3 0 R /Fit]')
        elif self.zoom_mode == 'fullwidth':
            self.session._out('/OpenAction [3 0 R /FitH null]')
        elif self.zoom_mode == 'real':
            self.session._out('/OpenAction [3 0 R /XYZ null null 1]')
        elif not isinstance(self.zoom_mode, basestring):
            self.session._out(
                '/OpenAction [3 0 R /XYZ null null ' +
                (self.zoom_mode / 100) + ']')

        if self.layout_mode == 'single':
            self.session._out('/PageLayout /SinglePage')
        elif self.layout_mode == 'continuous':
            self.session._out('/PageLayout /OneColumn')
        elif self.layout_mode == 'two':
            self.session._out('/PageLayout /TwoColumnLeft')
        self.session._out('>>')
        self.session._out('endobj')

def
_put_catalog
(
self
)
:
self
.
session
.
_add_object
(
)
self
.
session
.
_out
(
'<<'
)
self
.
session
.
_out
(
'/Type /Catalog'
)
self
.
session
.
_out
(
'/Pages 1 0 R'
)
if
self
.
zoom_mode
==
'fullpage'
:
self
.
session
.
_out
(
'/OpenAction [3 0 R /Fit]'
)
elif
self
.
zoom_mode
==
'fullwidth'
:
self
.
session
.
_out
(
'/OpenAction [3 0 R /FitH null]'
)
elif
self
.
zoom_mode
==
'real'
:
self
.
session
.
_out
(
'/OpenAction [3 0 R /XYZ null null 1]'
)
elif
not
isinstance
(
self
.
zoom_mode
,
basestring
)
:
self
.
session
.
_out
(
'/OpenAction [3 0 R /XYZ null null '
+
(
self
.
zoom_mode
/
100
)
+
']'
)
if
self
.
layout_mode
==
'single'
:
self
.
session
.
_out
(
'/PageLayout /SinglePage'
)
elif
self
.
layout_mode
==
'continuous'
:
self
.
session
.
_out
(
'/PageLayout /OneColumn'
)
elif
self
.
layout_mode
==
'two'
:
self
.
session
.
_out
(
'/PageLayout /TwoColumnLeft'
)
self
.
session
.
_out
(
'>>'
)
self
.
session
.
_out
(
'endobj'
)


def _put_trailer(self):
        """ Final Trailer calculations, and end-of-file
            reference.

        """
        startxref = len(self.session.buffer)

        self._put_cross_reference()

        md5 = hashlib.md5()
        md5.update(datetime.now().strftime('%Y%m%d%H%M%S'))
        try:
            md5.update(self.filepath)
        except TypeError:
            pass
        if self.title:
            md5.update(self.title)
        if self.subject:
            md5.update(self.subject)
        if self.author:
            md5.update(self.author)
        if self.keywords:
            md5.update(self.keywords)
        if self.creator:
            md5.update(self.creator)

        objnum = len(self.session.objects)
        self.session._out('trailer')
        self.session._out('<<')
        self.session._out('/Size %s' % objnum)
        self.session._out('/Root %s 0 R' % (objnum - 1))
        self.session._out('/Info %s 0 R' % (objnum - 2))
        self.session._out('/ID [ <%s> <%s>]' % (md5.hexdigest(),md5.hexdigest()))
        self.session._out('>>')
        self.session._out('startxref')
        self.session._out(startxref)
        self.session._out('%%EOF')

def
_put_trailer
(
self
)
:
startxref
=
len
(
self
.
session
.
buffer
)
self
.
_put_cross_reference
(
)
md5
=
hashlib
.
md5
(
)
md5
.
update
(
datetime
.
now
(
)
.
strftime
(
'%Y%m%d%H%M%S'
)
)
try
:
md5
.
update
(
self
.
filepath
)
except
TypeError
:
pass
if
self
.
title
:
md5
.
update
(
self
.
title
)
if
self
.
subject
:
md5
.
update
(
self
.
subject
)
if
self
.
author
:
md5
.
update
(
self
.
author
)
if
self
.
keywords
:
md5
.
update
(
self
.
keywords
)
if
self
.
creator
:
md5
.
update
(
self
.
creator
)
objnum
=
len
(
self
.
session
.
objects
)
self
.
session
.
_out
(
'trailer'
)
self
.
session
.
_out
(
'<<'
)
self
.
session
.
_out
(
'/Size %s'
%
objnum
)
self
.
session
.
_out
(
'/Root %s 0 R'
%
(
objnum
1
)
)
self
.
session
.
_out
(
'/Info %s 0 R'
%
(
objnum
2
)
)
self
.
session
.
_out
(
'/ID [ <%s> <%s>]'
%
(
md5
.
hexdigest
(
)
,
md5
.
hexdigest
(
)
)
)
self
.
session
.
_out
(
'>>'
)
self
.
session
.
_out
(
'startxref'
)
self
.
session
.
_out
(
startxref
)
self
.
session
.
_out
(
'%%EOF'
)

Final Trailer calculations and end - of - file reference .


def floyd(seqs, f=None, start=None, key=lambda x: x):
    """Floyd's Cycle Detector.

    See help(cycle_detector) for more context.

    Args:

      *args: Two iterators issueing the exact same sequence:
      -or-
      f, start: Function and starting state for finite state machine

    Yields:

      Values yielded by sequence_a if it terminates, undefined if a
      cycle is found.

    Raises:

      CycleFound if exception is found; if called with f and `start`,
      the parametres `first` and `period` will be defined indicating
      the offset of start of the cycle and the cycle's period.
    """

    tortise, hare = seqs

    yield hare.next()
    tortise_value = tortise.next()
    hare_value = hare.next()
    while hare_value != tortise_value:
        yield hare_value
        yield hare.next()
        hare_value = hare.next()
        tortise_value = tortise.next()

    if f is None:
        raise CycleDetected()

    hare_value = f(hare_value)
    first = 0
    tortise_value = start
    while key(tortise_value) != key(hare_value):
        tortise_value = f(tortise_value)
        hare_value = f(hare_value)
        first += 1

    period = 1
    hare_value = f(tortise_value)
    while key(tortise_value) != key(hare_value):
        hare_value = f(hare_value)
        period += 1

    raise CycleDetected(period=period, first=first)

def floyd ( seqs , f = None , start = None , key = lambda x : x ) : tortise , hare = seqs yield hare . next ( ) tortise_value = tortise . next ( ) hare_value = hare . next ( ) while hare_value != tortise_value : yield hare_value yield hare . next ( ) hare_value = hare . next ( ) tortise_value = tortise . next ( ) if f is None : raise CycleDetected ( ) hare_value = f ( hare_value ) first = 0 tortise_value = start while key ( tortise_value ) != key ( hare_value ) : tortise_value = f ( tortise_value ) hare_value = f ( hare_value ) first += 1 period = 1 hare_value = f ( tortise_value ) while key ( tortise_value ) != key ( hare_value ) : hare_value = f ( hare_value ) period += 1 raise CycleDetected ( period = period , first = first )


def naive(seqs, f=None, start=None, key=lambda x: x):
    """Naive cycle detector

    See help(cycle_detector) for more context.

    Args:

      sequence: A sequence to detect cyles in.

      f, start: Function and starting state for finite state machine

    Yields:

      Values yielded by sequence_a if it terminates, undefined if a
      cycle is found.

    Raises:

      CycleFound if exception is found.  Will always generate a first
      and period value no matter which of the `seqs` or `f` interface
      is used.
    """
    history = {}
    for step, value in enumerate(seqs[0]):
        keyed = key(value)
        yield value
        if keyed in history:
            raise CycleDetected(
                first=history[keyed], period=step - history[keyed])
        history[keyed] = step

def naive ( seqs , f = None , start = None , key = lambda x : x ) : history = { } for step , value in enumerate ( seqs [ 0 ] ) : keyed = key ( value ) yield value if keyed in history : raise CycleDetected ( first = history [ keyed ] , period = step - history [ keyed ] ) history [ keyed ] = step


def gosper(seqs, f=None, start=None, key=lambda x: x):
    """Gosper's cycle detector

    See help(cycle_detector) for more context.

    Args:

      sequence: A sequence to detect cyles in.

      f, start: Function and starting state for finite state machine

    Yields:

      Values yielded by sequence_a if it terminates, undefined if a
      cycle is found.

    Raises:

      CycleFound if exception is found.  Unlike Floyd and Brent's,
      Gosper's can only detect period of a cycle.  It cannot
      compute the first position
    """

    tab = []
    for c, value in enumerate(seqs[0], start=1):
        yield value
        try:
            e = tab.index(key(value))
            raise CycleDetected(
                period=c - ((((c >> e) - 1) | 1) << e))
        except ValueError:
            try:
                tab[(c ^ (c - 1)).bit_length() - 1] = key(value)
            except IndexError:
                tab.append(value)

def gosper ( seqs , f = None , start = None , key = lambda x : x ) : tab = [ ] for c , value in enumerate ( seqs [ 0 ] , start = 1 ) : yield value try : e = tab . index ( key ( value ) ) raise CycleDetected ( period = c - ( ( ( ( c >> e ) - 1 ) | 1 ) << e ) ) except ValueError : try : tab [ ( c ^ ( c - 1 ) ) . bit_length ( ) - 1 ] = key ( value ) except IndexError : tab . append ( value )


def brent(seqs, f=None, start=None, key=lambda x: x):
    """Brent's Cycle Detector.

    See help(cycle_detector) for more context.

    Args:

      *args: Two iterators issueing the exact same sequence:
      -or-
      f, start: Function and starting state for finite state machine

    Yields:

      Values yielded by sequence_a if it terminates, undefined if a
      cycle is found.

    Raises:

      CycleFound if exception is found; if called with f and `start`,
      the parametres `first` and `period` will be defined indicating
      the offset of start of the cycle and the cycle's period.
    """

    power = period = 1
    tortise, hare = seqs

    yield hare.next()
    tortise_value = tortise.next()
    hare_value = hare.next()
    while key(tortise_value) != key(hare_value):
        yield hare_value
        if power == period:
            power *= 2
            period = 0
            if f:
                tortise = f_generator(f, hare_value)
                tortise_value = tortise.next()
            else:
                while tortise_value != hare_value:
                    tortise_value = tortise.next()
        hare_value = hare.next()
        period += 1

    if f is None:
        raise CycleDetected()

    first = 0
    tortise_value = hare_value = start
    for _ in xrange(period):
        hare_value = f(hare_value)

    while key(tortise_value) != key(hare_value):
        tortise_value = f(tortise_value)
        hare_value = f(hare_value)
        first += 1
    raise CycleDetected(period=period, first=first)

def brent ( seqs , f = None , start = None , key = lambda x : x ) : power = period = 1 tortise , hare = seqs yield hare . next ( ) tortise_value = tortise . next ( ) hare_value = hare . next ( ) while key ( tortise_value ) != key ( hare_value ) : yield hare_value if power == period : power *= 2 period = 0 if f : tortise = f_generator ( f , hare_value ) tortise_value = tortise . next ( ) else : while tortise_value != hare_value : tortise_value = tortise . next ( ) hare_value = hare . next ( ) period += 1 if f is None : raise CycleDetected ( ) first = 0 tortise_value = hare_value = start for _ in xrange ( period ) : hare_value = f ( hare_value ) while key ( tortise_value ) != key ( hare_value ) : tortise_value = f ( tortise_value ) hare_value = f ( hare_value ) first += 1 raise CycleDetected ( period = period , first = first )


def x_fit(self, test_length):
        """ Test to see if the line can has enough space for the given length. """
        if (self.x + test_length) >= self.xmax:
            return False
        else:
            return True

def x_fit ( self , test_length ) : if ( self . x + test_length ) >= self . xmax : return False else : return True

Test to see if the line can has enough space for the given length .


def y_fit(self, test_length):
        """ Test to see if the page has enough space for the given text height. """
        if (self.y + test_length) >= self.ymax:
            return False
        else:
            return True

def y_fit ( self , test_length ) : if ( self . y + test_length ) >= self . ymax : return False else : return True

Test to see if the page has enough space for the given text height .


def x_is_greater_than(self, test_ordinate):
        """ Comparison for x coordinate"""
        self._is_coordinate(test_ordinate)
        if self.x > test_ordinate.x:
            return True
        else:
            return False

def x_is_greater_than ( self , test_ordinate ) : self . _is_coordinate ( test_ordinate ) if self . x > test_ordinate . x : return True else : return False


def y_is_greater_than(self, test_ordinate):
        """Comparison for y coordinate"""
        self._is_coordinate(test_ordinate)
        if self.y > test_ordinate.y:
            return True
        else:
            return False

def y_is_greater_than ( self , test_ordinate ) : self . _is_coordinate ( test_ordinate ) if self . y > test_ordinate . y : return True else : return False


def copy(self):
        """ Create a copy, and return it."""
        new_cursor = self.__class__(self.x, self.y)
        new_cursor.set_bounds(self.xmin, self.ymin, self.xmax, self.ymax, self.ymaxmax)
        new_cursor.set_deltas(self.dx, self.dy)
        return new_cursor

def copy ( self ) : new_cursor = self . __class__ ( self . x , self . y ) new_cursor . set_bounds ( self . xmin , self . ymin , self . xmax , self . ymax , self . ymaxmax ) new_cursor . set_deltas ( self . dx , self . dy ) return new_cursor


def x_plus(self, dx=None):
        """ Mutable x addition. Defaults to set delta value. """
        if dx is None:
            self.x += self.dx
        else:
            self.x = self.x + dx

def x_plus ( self , dx = None ) : if dx is None : self . x += self . dx else : self . x = self . x + dx

Mutable x addition . Defaults to set delta value .


def y_plus(self, dy=None):
        """ Mutable y addition. Defaults to set delta value. """
        if dy is None:
            self.y += self.dy
        else:
            self.y = self.y + dy

def y_plus ( self , dy = None ) : if dy is None : self . y += self . dy else : self . y = self . y + dy

Mutable y addition . Defaults to set delta value .


def _draw(self):
        """ Don't use this, use document.draw_table """
        self._compile()
        self.rows[0]._advance_first_row()
        self._set_borders()
        self._draw_fill()
        self._draw_borders()
        self._draw_text()
        self._set_final_cursor()

def _draw ( self ) : self . _compile ( ) self . rows [ 0 ] . _advance_first_row ( ) self . _set_borders ( ) self . _draw_fill ( ) self . _draw_borders ( ) self . _draw_text ( ) self . _set_final_cursor ( )

Don t use this use document . draw_table


def create(self, name, description=None, color=None):
        """
        Creates a new label and returns the response

        :param name: The label name
        :type name: str

        :param description: An optional description for the label. The name is
            used if no description is provided.
        :type description: str

        :param color: The hex color for the label (ex: 'ff0000' for red). If no
            color is provided, a random one will be assigned.
        :type color: str

        :returns: The response of your post
        :rtype: dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        data = {
            'name': name,
            'title': name,
            'description': description or name,
            'appearance': {
                'color': color or random_color()
            }
        }
        # Yes, it's confusing. the `/tags/` endpoint is used for labels
        return self._post(
            request=ApiActions.CREATE.value,
            uri=ApiUri.TAGS.value,
            params=data
        )


def list(self):
        """
        Get all current labels

        :return: The Logentries API response
        :rtype: list of dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        return self._post(
            request='list',
            uri=ApiUri.TAGS.value,
        ).get('tags')

def list ( self ) : return self . _post ( request = 'list' , uri = ApiUri . TAGS . value , ) . get ( 'tags' )


def get(self, name):
        """
        Get labels by name

        :param name: The label name, it must be an exact match.
        :type name: str

        :return: A list of matching labels. An empty list is returned if there are
            not any matches
        :rtype: list of dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        labels = self.list()
        return [
            label
            for label
            in labels
            if name == label.get('name')
        ]

def get ( self , name ) : labels = self . list ( ) return [ label for label in labels if name == label . get ( 'name' ) ]


def update(self, label):
        """
        Update a Label

        :param label: The data to update. Must include keys:

            * id (str)
            * appearance (dict)
            * description (str)
            * name (str)
            * title (str)
        :type label: dict

        Example:

        .. code-block:: python

            Labels().update(
                label={
                    'id': 'd9d4596e-49e4-4135-b3b3-847f9e7c1f43',
                    'appearance': {'color': '278abe'},
                    'name': 'My Sandbox',
                    'description': 'My Sandbox',
                    'title': 'My Sandbox',
                }
            )

        :return:
        :rtype: dict
        """
        data = {
            'id': label['id'],
            'name': label['name'],
            'appearance': label['appearance'],
            'description': label['description'],
            'title': label['title'],
        }
        return self._post(
            request=ApiActions.UPDATE.value,
            uri=ApiUri.TAGS.value,
            params=data
        )

def update ( self , label ) : data = { 'id' : label [ 'id' ] , 'name' : label [ 'name' ] , 'appearance' : label [ 'appearance' ] , 'description' : label [ 'description' ] , 'title' : label [ 'title' ] , } return self . _post ( request = ApiActions . UPDATE . value , uri = ApiUri . TAGS . value , params = data )


def delete(self, id):
        """
        Delete the specified label

        :param id: the label's ID
        :type id: str

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        return self._post(
            request=ApiActions.DELETE.value,
            uri=ApiUri.TAGS.value,
            params={'id': id}
        )

def delete ( self , id ) : return self . _post ( request = ApiActions . DELETE . value , uri = ApiUri . TAGS . value , params = { 'id' : id } )


def create(self, label_id):
        """
        Create a new tag

        :param label_id: The Label ID (the 'sn' key of the create label response)
        :type label_id: str

        :returns: The response of your post
        :rtype: dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        data = {
            'type': 'tagit',
            'rate_count': 0,
            'rate_range': 'day',
            'limit_count': 0,
            'limit_range': 'day',
            'schedule': [],
            'enabled': True,
            'args': {
                'sn': label_id,
                'tag_sn': label_id
            }
        }
        # Yes, it's confusing. the `/actions/` endpoint is used for tags, while
        # the /tags/ endpoint is used for labels.
        return self._post(
            request=ApiActions.CREATE.value,
            uri=ApiUri.ACTIONS.value,
            params=data
        )


def list(self):
        """
        Get all current tags

        :return: All tags
        :rtype: list of dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        return list(
            filter(
                lambda x: x.get('type') == 'tagit',  # pragma: no cover
                self._post(
                    request=ApiActions.LIST.value,
                    uri=ApiUri.ACTIONS.value,
                ).get('actions')
            )
        )

def
list
(
self
)
:
return
list
(
filter
(
lambda
x
:
x
.
get
(
'type'
)
==
'tagit'
,
# pragma: no cover
self
.
_post
(
request
=
ApiActions
.
LIST
.
value
,
uri
=
ApiUri
.
ACTIONS
.
value
,
)
.
get
(
'actions'
)
)
)


def get(self, label_sn):
        """
        Get tags by a label's sn key

        :param label_sn: A corresponding label's ``sn`` key.
        :type label_sn: str or int

        :return: A list of matching tags. An empty list is returned if there are
            not any matches
        :rtype: list of dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        tags = self.list()
        return [
            tag
            for tag
            in tags
            if str(label_sn) in tag.get('args', {}).values()
        ]

def get ( self , label_sn ) : tags = self . list ( ) return [ tag for tag in tags if str ( label_sn ) in tag . get ( 'args' , { } ) . values ( ) ]


def create(self, name, regexes, tag_ids, logs=None):
        """
        Create a hook

        :param name: The hook's name (should be the same as the tag)
        :type name: str

        :param regexes: The list of regular expressions that Logentries expects.
            Ex: `['user_agent = /curl\/[\d.]*/']` Would match where the
            user-agent is curl.
        :type regexes: list of str

        :param tag_id: The ids of the tags to associate the hook with.
            (The 'id' key of the create tag response)
        :type tag_id: list of str

        :param logs: The logs to add the hook to. Comes from the 'key'
            key in the log dict.
        :type logs: list of str

        :returns: The response of your post
        :rtype: dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        data = {
            'name': name,
            'triggers': regexes,
            'sources': logs or [],
            'groups': [],
            'actions': tag_ids
        }
        return self._post(
            request=ApiActions.CREATE.value,
            uri=ApiUri.HOOKS.value,
            params=data
        )

def create ( self , name , regexes , tag_ids , logs = None ) : data = { 'name' : name , 'triggers' : regexes , 'sources' : logs or [ ] , 'groups' : [ ] , 'actions' : tag_ids } return self . _post ( request = ApiActions . CREATE . value , uri = ApiUri . HOOKS . value , params = data )


def list(self):
        """
        Get all current hooks

        :return: All hooks
        :rtype: list of dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        return self._post(
            request=ApiActions.LIST.value,
            uri=ApiUri.HOOKS.value,
        ).get('hooks')

def list ( self ) : return self . _post ( request = ApiActions . LIST . value , uri = ApiUri . HOOKS . value , ) . get ( 'hooks' )


def update(self, hook):
        """
        Update a hook

        :param hook: The data to update. Must include keys:

            * id (str)
            * name (str)
            * triggers (list of str)
            * sources (list of str)
            * groups (list of str)
            * actions (list of str)
        :type hook: dict

        Example:

        .. code-block:: python

            Hooks().update(
                hook={
                    'id': 'd9d4596e-49e4-4135-b3b3-847f9e7c1f43',
                    'name': 'My Sandbox',
                    'triggers': [
                        'host = you.example.com'
                    ],
                    'sources': [
                        '4d42c719-4005-4929-aa4a-994da4b95040'
                    ],
                    'groups': [],
                    'actions': [
                        '9f6adf69-37b9-4a4b-88fb-c3fc4c781a11',
                        'ddc36d71-33cb-4f4f-be1b-8591814b1946'
                    ],
                }
            )

        :return:
        :rtype: dict
        """
        data = {
            'id': hook['id'],
            'name': hook['name'],
            'triggers': hook['triggers'],
            'sources': hook['sources'],
            'groups': hook['groups'],
            'actions': hook['actions'],
        }
        return self._post(
            request=ApiActions.UPDATE.value,
            uri=ApiUri.HOOKS.value,
            params=data
        )

def update ( self , hook ) : data = { 'id' : hook [ 'id' ] , 'name' : hook [ 'name' ] , 'triggers' : hook [ 'triggers' ] , 'sources' : hook [ 'sources' ] , 'groups' : hook [ 'groups' ] , 'actions' : hook [ 'actions' ] , } return self . _post ( request = ApiActions . UPDATE . value , uri = ApiUri . HOOKS . value , params = data )


def create(self,
               alert_config,
               occurrence_frequency_count=None,
               occurrence_frequency_unit=None,
               alert_frequency_count=None,
               alert_frequency_unit=None):
        """
        Create a new alert

        :param alert_config: A list of AlertConfig classes (Ex:
            ``[EmailAlertConfig('me@mydomain.com')]``)
        :type alert_config: list of
            :class:`PagerDutyAlertConfig<logentries_api.alerts.PagerDutyAlertConfig>`,
            :class:`WebHookAlertConfig<logentries_api.alerts.WebHookAlertConfig>`,
            :class:`EmailAlertConfig<logentries_api.alerts.EmailAlertConfig>`,
            :class:`SlackAlertConfig<logentries_api.alerts.SlackAlertConfig>`, or
            :class:`HipChatAlertConfig<logentries_api.alerts.HipChatAlertConfig>`

        :param occurrence_frequency_count: How many times per
            ``alert_frequency_unit`` for a match before issuing an alert.
            Defaults to 1
        :type occurrence_frequency_count: int

        :param occurrence_frequency_unit: The time period to monitor for sending
            an alert. Must be 'day', or 'hour'. Defaults to 'hour'
        :type occurrence_frequency_unit: str

        :param alert_frequency_count: How many times per
            ``alert_frequency_unit`` to issue an alert. Defaults to 1
        :type alert_frequency_count: int

        :param alert_frequency_unit: How often to regulate sending alerts.
            Must be 'day', or 'hour'. Defaults to 'hour'
        :type alert_frequency_unit: str

        :returns: The response of your post
        :rtype: dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        data = {
            'rate_count': occurrence_frequency_count or 1,
            'rate_range': occurrence_frequency_unit or 'hour',
            'limit_count': alert_frequency_count or 1,
            'limit_range': alert_frequency_unit or 'hour',
            'schedule': [],
            'enabled': True,
        }
        data.update(alert_config.args())

        # Yes, it's confusing. the `/actions/` endpoint is used for alerts, while
        # the /tags/ endpoint is used for labels.
        return self._post(
            request=ApiActions.CREATE.value,
            uri=ApiUri.ACTIONS.value,
            params=data
        )


def get(self, alert_type, alert_args=None):
        """
        Get alerts that match the alert type and args.

        :param alert_type: The type of the alert. Must be one of 'pagerduty',
            'mailto', 'webhook', 'slack', or 'hipchat'
        :type alert_type: str

        :param alert_args: The args for the alert. The provided args must be a
            subset of the actual alert args. If no args are provided, all
            alerts matching the ``alert_type`` are returned. For example:
            ``.get('mailto', alert_args={'direct': 'me@mydomain.com'})`` or
            ``.get('slack', {'url': 'https://hooks.slack.com/services...'})``

        :return: A list of matching alerts. An empty list is returned if there
            are not any matches
        :rtype: list of dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        alert_args = alert_args or {}

        alerts = self.list()
        return [
            alert
            for alert
            in alerts
            if alert.get('type') == alert_type
            and dict_is_subset(alert_args, alert.get('args'))
        ]

def get ( self , alert_type , alert_args = None ) : alert_args = alert_args or { } alerts = self . list ( ) return [ alert for alert in alerts if alert . get ( 'type' ) == alert_type and dict_is_subset ( alert_args , alert . get ( 'args' ) ) ]

Get alerts that match the alert type and args .


def update(self, alert):
        """
        Update an alert

        :param alert: The data to update. Must include keys:

            * id (str)
            * rate_count (int)
            * rate_range (str): 'day' or 'hour'
            * limit_count (int)
            * limit_range (str): 'day' or 'hour'
            * type (str)
            * schedule (list)
            * args (dict)
        :type alert: dict

        Example:

        .. code-block:: python

            Alert().update(
                alert={
                    'id': 'd9d4596e-49e4-4135-b3b3-847f9e7c1f43',
                    'args': {'direct': 'you@example.com'},
                    'rate_count': 1,
                    'rate_range': 'hour',
                    'limit_count': 1,
                    'limit_range': 'hour',
                    'schedule': [],
                    'enabled': True,
                    'type': 'mailto',
                }
            )

        :return:
        :rtype: dict
        """
        data = {
            'id': alert['id'],
            'args': alert['args'],
            'rate_count': alert['rate_count'],
            'rate_range': alert['rate_range'],
            'limit_count': alert['limit_count'],
            'limit_range': alert['limit_range'],
            'schedule': alert['schedule'],
            'enabled': alert['enabled'],
            'type': alert['type'],
        }

        return self._post(
            request=ApiActions.UPDATE.value,
            uri=ApiUri.ACTIONS.value,
            params=data
        )

def update ( self , alert ) : data = { 'id' : alert [ 'id' ] , 'args' : alert [ 'args' ] , 'rate_count' : alert [ 'rate_count' ] , 'rate_range' : alert [ 'rate_range' ] , 'limit_count' : alert [ 'limit_count' ] , 'limit_range' : alert [ 'limit_range' ] , 'schedule' : alert [ 'schedule' ] , 'enabled' : alert [ 'enabled' ] , 'type' : alert [ 'type' ] , } return self . _post ( request = ApiActions . UPDATE . value , uri = ApiUri . ACTIONS . value , params = data )


def setup(app):
    """
    Initialize this Sphinx extension
    """
    app.setup_extension('sphinx.ext.todo')
    app.setup_extension('sphinx.ext.mathjax')

    app.setup_extension("sphinx.ext.intersphinx")
    app.config.intersphinx_mapping.update({
        'https://docs.python.org/': None
        })
    app.config.intersphinx_mapping.update({
        sage_doc_url + doc + "/": None
        for doc in sage_documents
        })
    app.config.intersphinx_mapping.update({
        sage_doc_url + "reference/" + module: None
        for module in sage_modules
        })

    app.setup_extension("sphinx.ext.extlinks")
    app.config.extlinks.update({
        'python': ('https://docs.python.org/release/'+pythonversion+'/%s', ''),
        # Sage trac ticket shortcuts. For example, :trac:`7549` .
        'trac': ('https://trac.sagemath.org/%s', 'trac ticket #'),
        'wikipedia': ('https://en.wikipedia.org/wiki/%s', 'Wikipedia article '),
        'arxiv': ('http://arxiv.org/abs/%s', 'Arxiv '),
        'oeis': ('https://oeis.org/%s', 'OEIS sequence '),
        'doi': ('https://dx.doi.org/%s', 'doi:'),
        'pari': ('http://pari.math.u-bordeaux.fr/dochtml/help/%s', 'pari:'),
        'mathscinet': ('http://www.ams.org/mathscinet-getitem?mr=%s', 'MathSciNet ')
        })

    app.config.html_theme = 'sage'


def themes_path():
    """
    Retrieve the location of the themes directory from the location of this package

    This is taken from Sphinx's theme documentation
    """
    package_dir = os.path.abspath(os.path.dirname(__file__))
    return os.path.join(package_dir, 'themes')

def themes_path ( ) : package_dir = os . path . abspath ( os . path . dirname ( __file__ ) ) return os . path . join ( package_dir , 'themes' )


def _post(self, request, uri, params=None):
        """
        A wrapper for posting things.

        :param request: The request type. Must be one of the
            :class:`ApiActions<logentries_api.base.ApiActions>`
        :type request: str

        :param uri: The API endpoint to hit. Must be one of
            :class:`ApiUri<logentries_api.base.ApiUri>`
        :type uri: str

        :param params: A dictionary of supplemental kw args
        :type params: dict

        :returns: The response of your post
        :rtype: dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        request_data = {
            'acl': self.account_key,
            'account': self.account_key,
            'request': request,
        }

        request_data.update(params or {})

        response = requests.post(
            url='https://api.logentries.com/v2/{}'.format(uri),
            headers=self.headers,
            data=json.dumps(request_data)
        )

        if not response.ok:
            raise ServerException(
                '{}: {}'.format(response.status_code, response.text))
        return response.json()

def
_post
(
self
,
request
,
uri
,
params
=
)
:
request_data
=
{
'acl'
:
self
.
account_key
,
'account'
:
self
.
account_key
,
'request'
:
request
,
}
request_data
.
update
(
params
or
{
}
)
response
=
requests
.
post
(
url
=
'https://api.logentries.com/v2/{}'
.
format
(
uri
)
,
headers
=
self
.
headers
,
data
=
json
.
dumps
(
request_data
)
)
if
not
response
.
ok
:
raise
ServerException
(
'{}: {}'
.
format
(
response
.
status_code
,
response
.
text
)
)
return
response
.
json
(
)


def list(self):
        """
        Get all log sets

        :return: Returns a dictionary where the key is the hostname or log set,
            and the value is a list of the log keys
        :rtype: dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        response = requests.get(self.base_url)

        if not response.ok:
            raise ServerException(
                '{}: {}'.format(response.status_code, response.text))

        return {
            host.get('name'): [
                log.get('key')
                for log
                in host.get('logs')]
            for host
            in response.json().get('list')
        }

def
list
(
self
)
:
response
=
requests
.
get
(
self
.
base_url
)
if
not
response
.
ok
:
raise
ServerException
(
'{}: {}'
.
format
(
response
.
status_code
,
response
.
text
)
)
return
{
host
.
get
(
'name'
)
:
[
log
.
get
(
'key'
)
for
log
in
host
.
get
(
'logs'
)
]
for
host
in
response
.
json
(
)
.
get
(
'list'
)
}


def get(self, log_set):
        """
        Get a specific log or log set

        :param log_set: The log set or log to get. Ex: `.get(log_set='app')` or
            `.get(log_set='app/log')`
        :type log_set: str

        :returns: The response of your log set or log
        :rtype: dict

        :raises: This will raise a
            :class:`ServerException<logentries_api.exceptions.ServerException>`
            if there is an error from Logentries
        """
        response = requests.get(self.base_url + log_set.rstrip('/'))

        if not response.ok:
            raise ServerException(
                '{}: {}'.format(response.status_code, response.text))
        return response.json()

def
get
(
self
,
log_set
)
:
response
=
requests
.
get
(
self
.
base_url
+
log_set
.
rstrip
(
'/'
)
)
if
not
response
.
ok
:
raise
ServerException
(
'{}: {}'
.
format
(
response
.
status_code
,
response
.
text
)
)
return
response
.
json
(
)


def find_attacker_slider(dest_list, occ_bb, piece_bb, target_bb, pos,
                             domain):
    """ Find a slider attacker

    Parameters
    ----------
    dest_list : list
        To store the results.
    occ_bb : int, bitboard
        Occupancy bitboard.
    piece_bb : int, bitboard
        Bitboard with the position of the attacker piece.
    target_bb : int, bitboard
        Occupancy bitboard without any of the sliders in question.
    pos : int
        Target position.
    pos_map : function
        Mapping between a board position and its position in a single
        rotated/translated rank produced with domain_trans.
    domain_trans : function
        Transformation from a rank/file/diagonal/anti-diagonal containing pos
        to a single rank
    pos_inv_map : function
        Inverse of pos_map
    """
    pos_map, domain_trans, pos_inv_map = domain
    r = reach[pos_map(pos)][domain_trans(target_bb, pos)]
    m = r & domain_trans(piece_bb, pos)
    while m:
        r = m&-m
        rpos = r.bit_length()-1
        if not (ray[rpos][pos_map(pos)] & domain_trans(occ_bb, pos)):
            dest_list.append(pos_inv_map(rpos, pos))
        m ^= r

def find_attacker_slider ( dest_list , occ_bb , piece_bb , target_bb , pos , domain ) : pos_map , domain_trans , pos_inv_map = domain r = reach [ pos_map ( pos ) ] [ domain_trans ( target_bb , pos ) ] m = r & domain_trans ( piece_bb , pos ) while m : r = m & - m rpos = r . bit_length ( ) - 1 if not ( ray [ rpos ] [ pos_map ( pos ) ] & domain_trans ( occ_bb , pos ) ) : dest_list . append ( pos_inv_map ( rpos , pos ) ) m ^= r


def duration(self):
        '''
        The approximate transit duration for the general case of an eccentric orbit

        '''
        ecc = self.ecc if not np.isnan(self.ecc) else np.sqrt(self.ecw**2 + self.esw**2)
        esw = self.esw if not np.isnan(self.esw) else ecc * np.sin(self.w)
        aRs = ((G * self.rhos * (1. + self.MpMs) *
              (self.per * DAYSEC)**2.) / (3. * np.pi))**(1./3.)
        inc = np.arccos(self.bcirc/aRs)
        becc = self.bcirc * (1 - ecc**2)/(1 - esw)
        tdur = self.per / 2. / np.pi * np.arcsin(((1. + self.RpRs)**2 -
               becc**2)**0.5 / (np.sin(inc) * aRs))
        tdur *= np.sqrt(1. - ecc**2.)/(1. - esw)
        return tdur

def duration ( self ) : ecc = self . ecc if not np . isnan ( self . ecc ) else np . sqrt ( self . ecw ** 2 + self . esw ** 2 ) esw = self . esw if not np . isnan ( self . esw ) else ecc * np . sin ( self . w ) aRs = ( ( G * self . rhos * ( 1. + self . MpMs ) * ( self . per * DAYSEC ) ** 2. ) / ( 3. * np . pi ) ) ** ( 1. / 3. ) inc = np . arccos ( self . bcirc / aRs ) becc = self . bcirc * ( 1 - ecc ** 2 ) / ( 1 - esw ) tdur = self . per / 2. / np . pi * np . arcsin ( ( ( 1. + self . RpRs ) ** 2 - becc ** 2 ) ** 0.5 / ( np . sin ( inc ) * aRs ) ) tdur *= np . sqrt ( 1. - ecc ** 2. ) / ( 1. - esw ) return tdur


def update(self, **kwargs):
    '''
    Update the transit keyword arguments

    '''

    if kwargs.get('verify_kwargs', True):
      valid = [y[0] for x in [TRANSIT, LIMBDARK, SETTINGS] for y in x._fields_]       # List of valid kwargs
      valid += ['b', 'times']                                                         # These are special!
      for k in kwargs.keys():
        if k not in valid:
          raise Exception("Invalid kwarg '%s'." % k)

    if ('q1' in kwargs.keys()) and ('q2' in kwargs.keys()):
      kwargs.update({'ldmodel': KIPPING})
    elif ('c1' in kwargs.keys()) and ('c2' in kwargs.keys()) and \
         ('c3' in kwargs.keys()) and ('c4' in kwargs.keys()):
      kwargs.update({'ldmodel': NONLINEAR})

    self.limbdark.update(**kwargs)
    self.transit.update(**kwargs)
    self.settings.update(**kwargs)

def
update
(
self
,
*
*
kwargs
)
:
if
kwargs
.
get
(
'verify_kwargs'
,
True
)
:
valid
=
[
y
[
0
]
for
x
in
[
TRANSIT
,
LIMBDARK
,
SETTINGS
]
for
y
in
x
.
_fields_
]
# List of valid kwargs
valid
+=
[
'b'
,
'times'
]
# These are special!
for
k
in
kwargs
.
keys
(
)
:
if
k
not
in
valid
:
raise
Exception
(
"Invalid kwarg '%s'."
%
k
)
if
(
'q1'
in
kwargs
.
keys
(
)
)
and
(
'q2'
in
kwargs
.
keys
(
)
)
:
kwargs
.
update
(
{
'ldmodel'
:
KIPPING
}
)
elif
(
'c1'
in
kwargs
.
keys
(
)
)
and
(
'c2'
in
kwargs
.
keys
(
)
)
and
(
'c3'
in
kwargs
.
keys
(
)
)
and
(
'c4'
in
kwargs
.
keys
(
)
)
:
kwargs
.
update
(
{
'ldmodel'
:
NONLINEAR
}
)
self
.
limbdark
.
update
(
*
*
kwargs
)
self
.
transit
.
update
(
*
*
kwargs
)
self
.
settings
.
update
(
*
*
kwargs
)


def Compute(self):
    '''
    Computes the light curve model

    '''

    err = _Compute(self.transit, self.limbdark, self.settings, self.arrays)
    if err != _ERR_NONE: RaiseError(err)

def Compute ( self ) : err = _Compute ( self . transit , self . limbdark , self . settings , self . arrays ) if err != _ERR_NONE : RaiseError ( err )


def Bin(self):
    '''
    Bins the light curve model to the provided time array

    '''

    err = _Bin(self.transit, self.limbdark, self.settings, self.arrays)
    if err != _ERR_NONE: RaiseError(err)

def Bin ( self ) : err = _Bin ( self . transit , self . limbdark , self . settings , self . arrays ) if err != _ERR_NONE : RaiseError ( err )


def Free(self):
    '''
    Frees the memory used by all of the dynamically allocated C arrays.

    '''

    if self.arrays._calloc:
      _dbl_free(self.arrays._time)
      _dbl_free(self.arrays._flux)
      _dbl_free(self.arrays._bflx)
      _dbl_free(self.arrays._M)
      _dbl_free(self.arrays._E)
      _dbl_free(self.arrays._f)
      _dbl_free(self.arrays._r)
      _dbl_free(self.arrays._x)
      _dbl_free(self.arrays._y)
      _dbl_free(self.arrays._z)
      self.arrays._calloc = 0
    if self.arrays._balloc:
      _dbl_free(self.arrays._b)
      self.arrays._balloc = 0
    if self.arrays._ialloc:
      _dbl_free(self.arrays._iarr)
      self.arrays._ialloc = 0

def Free ( self ) : if self . arrays . _calloc : _dbl_free ( self . arrays . _time ) _dbl_free ( self . arrays . _flux ) _dbl_free ( self . arrays . _bflx ) _dbl_free ( self . arrays . _M ) _dbl_free ( self . arrays . _E ) _dbl_free ( self . arrays . _f ) _dbl_free ( self . arrays . _r ) _dbl_free ( self . arrays . _x ) _dbl_free ( self . arrays . _y ) _dbl_free ( self . arrays . _z ) self . arrays . _calloc = 0 if self . arrays . _balloc : _dbl_free ( self . arrays . _b ) self . arrays . _balloc = 0 if self . arrays . _ialloc : _dbl_free ( self . arrays . _iarr ) self . arrays . _ialloc = 0

Frees the memory used by all of the dynamically allocated C arrays .


def __recv(self, size=4096):
        """Reads data from the socket.

        Raises:
            NNTPError: When connection times out or read from socket fails.
        """
        data = self.socket.recv(size)
        if not data:
            raise NNTPError("Failed to read from socket")
        self.__buffer.write(data)

def
__recv
(
self
,
size
=
4096
)
:
data
=
self
.
socket
.
recv
(
size
)
if
not
data
:
raise
NNTPError
(
"Failed to read from socket"
)
self
.
__buffer
.
write
(
data
)


def __line_gen(self):
        """Generator that reads a line of data from the server.

        It first attempts to read from the internal buffer. If there is not
        enough data to read a line it then requests more data from the server
        and adds it to the buffer. This process repeats until a line of data
        can be read from the internal buffer.

        Yields:
            A line of data when it becomes available.
        """
        while True:
            line = self.__buffer.readline()
            if not line:
                self.__recv()
                continue
            yield line

def __line_gen ( self ) : while True : line = self . __buffer . readline ( ) if not line : self . __recv ( ) continue yield line

Generator that reads a line of data from the server .