# Path: src/petmail/database.py
# class DBError(Exception):
# class ObservableDatabase:
# def get_schema(version):
# def serialize(row):
#     def __init__(self, connection):
#     def subscribe(self, table, observer):
#     def unsubscribe(self, table, observer):
#     def execute(self, sql, values=None):
#     def insert(self, sql, values, table=None, tags={}):
#     def update(self, sql, values, table=None, id=None, tags={}):
#     def delete(self, sql, values, table, id, tags={}):
#     def commit(self):
# def get_db(dbfile, stderr=sys.stderr):
# def make_observable_db(dbfile, stderr=sys.stderr):
#     VERSION = 1
# 
# Path: src/petmail/util.py
# def equal(a, b):
#     # not vulnerable to timing attack
#     return hashlib.sha256(a).digest() == hashlib.sha256(b).digest()
# 
# def make_nonce():
#     return base64.b32encode(os.urandom(32)).strip("=").lower()
# 
# Path: src/petmail/errors.py
# class CommandError(Exception):
#     def __init__(self, msg):
#         self.msg = msg


import json, collections
from pkg_resources import resource_string, resource_filename
from twisted.application import service, strports
from twisted.web import server, static, resource, http
from .database import Notice
from .util import equal, make_nonce
from .errors import CommandError

    def stop(self):
        self.request.finish()

# note: no versions of IE (including the current IE11) support EventSource

class EventChannel(resource.Resource):
    def __init__(self, db, agent, dispatcher, esid):
        resource.Resource.__init__(self)
        self.db = db
        self.agent = agent
        self.dispatcher = dispatcher
        self.esid = esid
        # this maps topic to set of (table,notifierfunc)
        self.db_subscriptions = collections.defaultdict(set)

    # subclasses must define render_event(), which accepts a Notice and
    # returns a JSON-serializable object

    def render_GET(self, request):
        if "text/event-stream" not in (request.getHeader("accept") or ""):
            request.setResponseCode(http.BAD_REQUEST, "Must use EventSource")
            return "Must use EventSource (Content-Type: text/event-stream)"
        request.setHeader("content-type", "text/event-stream")
        self.events_protocol = EventsProtocol(request)
        request.notifyFinish().addErrback(self._shutdown)
        # tell the frontend it's safe to subscribe
        self.events_protocol.sendEvent(json.dumps({"type": "ready"}))
        return server.NOT_DONE_YET


# Path: src/petmail/database.py
# class DBError(Exception):
# class ObservableDatabase:
# def get_schema(version):
# def serialize(row):
#     def __init__(self, connection):
#     def subscribe(self, table, observer):
#     def unsubscribe(self, table, observer):
#     def execute(self, sql, values=None):
#     def insert(self, sql, values, table=None, tags={}):
#     def update(self, sql, values, table=None, id=None, tags={}):
#     def delete(self, sql, values, table, id, tags={}):
#     def commit(self):
# def get_db(dbfile, stderr=sys.stderr):
# def make_observable_db(dbfile, stderr=sys.stderr):
#     VERSION = 1
# 
# Path: src/petmail/util.py
# def equal(a, b):
#     # not vulnerable to timing attack
#     return hashlib.sha256(a).digest() == hashlib.sha256(b).digest()
# 
# def make_nonce():
#     return base64.b32encode(os.urandom(32)).strip("=").lower()
# 
# Path: src/petmail/errors.py
# class CommandError(Exception):
#     def __init__(self, msg):
#         self.msg = msg


# Path: src/petmail/web.py
import json, collections
from pkg_resources import resource_string, resource_filename
from twisted.application import service, strports
from twisted.web import server, static, resource, http
from .database import Notice
from .util import equal, make_nonce
from .errors import CommandError


    def stop(self):
        self.request.finish()

# note: no versions of IE (including the current IE11) support EventSource

class EventChannel(resource.Resource):
    def __init__(self, db, agent, dispatcher, esid):
        resource.Resource.__init__(self)
        self.db = db
        self.agent = agent
        self.dispatcher = dispatcher
        self.esid = esid
        # this maps topic to set of (table,notifierfunc)
        self.db_subscriptions = collections.defaultdict(set)

    # subclasses must define render_event(), which accepts a Notice and
    # returns a JSON-serializable object

    def render_GET(self, request):
        if "text/event-stream" not in (request.getHeader("accept") or ""):
            request.setResponseCode(http.BAD_REQUEST, "Must use EventSource")
            return "Must use EventSource (Content-Type: text/event-stream)"
        request.setHeader("content-type", "text/event-stream")
        self.events_protocol = EventsProtocol(request)
        request.notifyFinish().addErrback(self._shutdown)
        # tell the frontend it's safe to subscribe
        self.events_protocol.sendEvent(json.dumps({"type": "ready"}))
        return server.NOT_DONE_YET


    def _shutdown(self, _):