Пример #1
0
 def __init__(self, data):
     """
     The Python constructor. You should use :meth:`make` or
     :meth:`lookup` to construct instances.
     """
     self._id     = data.get('_id', None)
     self._openid = data['openid']
     self._input  = data['input']
     self._output = PadOutput(data['output'])
     self._title  = data['title']
     self._mode   = data['mode']
     self._public = data['public']
     self._ctime  = data['ctime']
     self._mtime  = data.get('mtime', None)
     self._readonly = True
Пример #2
0
class Pad(object):
    
    def __init__(self, data):
        """
        The Python constructor. You should use :meth:`make` or
        :meth:`lookup` to construct instances.
        """
        self._id     = data.get('_id', None)
        self._openid = data['openid']
        self._input  = data['input']
        self._output = PadOutput(data['output'])
        self._title  = data['title']
        self._mode   = data['mode']
        self._public = data['public']
        self._ctime  = data['ctime']
        self._mtime  = data.get('mtime', None)
        self._readonly = True

    def save(self):
        if self._readonly:
            raise PadWriteException('Cannot save, Pad is read only.')
        self._mtime = datetime.utcnow()
        self._title = self._guess_title()
        pad = {'openid'   : self._openid, 
               'input'    : self._input, 
               'output'   : self._output.to_dict(),
               'title'    : self._title,
               'mode'     : self._mode,
               'public'   : self._public,
               'ctime'    : self._ctime,
               'mtime'    : self._mtime }
        db = Pad.get_database()
        if self._id is None:
            self._id = db.insert(pad)
        else:
            criterion = {'_id' : self._id}
            db.update(criterion, pad)

    def erase(self):
        if self._readonly:
            raise PadWriteException('Cannot erase, Pad is read only.')
        if self._id is None:
            return
        db = Pad.get_database()
        db.remove({'_id' : self._id})

    @staticmethod
    def make(openid, pad_input=None, pad_output=None, 
             title='Untitled', mode='sage', public=True):
        """
        Construct a new pad
        """
        if not isinstance(openid, basestring):
            openid = openid.get_id()
        if pad_input is None:
            global default_input
            pad_input = default_input
        if pad_output is None:
            pad_output = PadOutput()
        pad = Pad({'openid' : openid, 
                   'input'  : pad_input,
                   'output' : pad_output,
                   'title'  : title,
                   'mode'   : mode,
                   'public' : public,
                   'ctime'  : datetime.utcnow()})
        pad._readonly = False
        pad.save()
        return pad

    @staticmethod
    def make_id(pad_id):
        """
        Construct a the pad_id from a string
        """
        try:
            return ObjectId(pad_id)
        except InvalidId:
            raise PadInvalidId('The pad_id is not valid.')

    def is_default(self):
        global default_input
        return self._input == default_input

    @staticmethod
    def lookup(pad_id, user):
        """
        Find the pad with given id in the database
        """
        if not isinstance(pad_id, ObjectId):
            pad_id = Pad.make_id(pad_id)
        db = Pad.get_database()
        data = db.find_one({'_id' :  pad_id})
        if data is None:
            raise PadInvalidId('The pad ID does not exist.')
        pad = Pad(data)
        if not pad.viewable_by(user):
            raise PadReadException('No read permission for pad')
        pad._readonly = not pad.editable_by(user)
        return pad

    @staticmethod
    def iterate(user, limit=None):
        """
        Iterate over the pads with given id in the database
        """
        db = Pad.get_database()
        for data in db.find({'openid' :  user.get_id()}).sort('mtime', DESCENDING):
            yield Pad(data)
            if limit is not None:
                limit -= 1
                if limit == 0:
                    return

    @staticmethod
    def get_database():
        """
        Return the database connection
        """
        global DATABASE
        if DATABASE is None:
            connection = Connection('localhost', 27017)
            DATABASE = connection.sagepad['pads']
        return DATABASE

    @staticmethod
    def max_pad_id():
        """
        Return the maximum pad id

        TODO: cache & increment whenever we add another pad
        """
        from pymongo.code import Code
        get_pad_id = Code(
            "function () {"
            "  this.pad_id.forEach(function(z) {"
            "    emit(z, 1);"
            "  });"
            "}")
        find_max = Code(
            "function (key, values) {"
            "  var maximum = 0;"
            "  for (var i = 0; i < values.length; i++) {"
            "    maximum = Math.max(maximum, values[i]);"
            "  }"
            "  return maximum;"
            "}")
        return Pad.get_database().map_reduce(get_pad_id, find_max)

    def _guess_title(self):
        """
        Guess the title from the module docstring or comment
        """
        fluff = [ '#', '//', '/*', '"""', "'''" ]
        found_fluff = False
        for line in self.get_input().splitlines():
            line.strip()
            for s in fluff:
                if line.startswith(s):
                    line = line[len(s):]
                    found_fluff = True
                line.strip()
            if line == '' or not found_fluff:
                continue
            return line
        return 'Untitled pad'
        

    def viewable_by(self, user):
        """
        Whether the user may view the pad
        """
        return True

    def editable_by(self, user):
        """
        Whether the user may edit the pad
        """
        return self._openid == user.get_id()

    def get_id(self):
        """
        Returns the mongo object id
        """
        return self._id

    def get_id_str(self):
        """
        Returns the mongo object id as string
        """
        return str(self._id)

    def get_ctime(self):
        return self._ctime

    def get_mtime(self):
        return self._mtime

    def pretty_mtime(self):
        """
        Get a datetime object or a int() Epoch timestamp and return a
        pretty string like 'an hour ago', 'Yesterday', '3 months ago',
        'just now', etc
        """
        time = self._mtime
        now = datetime.utcnow()
        diff = now - time 
        second_diff = diff.seconds
        day_diff = diff.days
        if day_diff < 0:
            return 'from future?'

        if day_diff == 0:
            if second_diff < 10:
                return "just now"
            if second_diff < 60:
                return str(second_diff) + " seconds ago"
            if second_diff < 120:
                return  "a minute ago"
            if second_diff < 3600:
                return str( second_diff / 60 ) + " minutes ago"
            if second_diff < 7200:
                return "an hour ago"
            if second_diff < 86400:
                return str( second_diff / 3600 ) + " hours ago"
        if day_diff == 1:
            return "Yesterday"
        if day_diff < 7:
            return str(day_diff) + " days ago"
        if day_diff < 31:
            return str(day_diff/7) + " weeks ago"
        if day_diff < 365:
            return str(day_diff/30) + " months ago"
        return str(day_diff/365) + " years ago"


    def get_eval_mode(self):
        return self._mode

    def set_eval_mode(self, eval_mode):
        self._mode = eval_mode
        self.save()

    def get_input(self):
        return self._input

    def set_input(self, input):
        self._input = input
        self._mtime = datetime.utcnow()
        self.save()

    def get_output(self):
        return self._output

    def set_output(self, output):
        self._output = PadOutput(output)
        self._mtime = datetime.utcnow()
        self.save()

    def get_title(self):
        return self._title
    
    def set_title(self, title):
        self._title = title
        self.save()
Пример #3
0
 def set_output(self, output):
     self._output = PadOutput(output)
     self._mtime = datetime.utcnow()
     self.save()