appengine/standard/ndb/property_subclasses/my_models.py (60 lines of code) (raw):

# Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from datetime import date from google.appengine.ext import ndb class LongIntegerProperty(ndb.StringProperty): def _validate(self, value): if not isinstance(value, (int, long)): raise TypeError("expected an integer, got %s" % repr(value)) def _to_base_type(self, value): return str(value) # Doesn't matter if it's an int or a long def _from_base_type(self, value): return long(value) # Always return a long class BoundedLongIntegerProperty(ndb.StringProperty): def __init__(self, bits, **kwds): assert isinstance(bits, int) assert bits > 0 and bits % 4 == 0 # Make it simple to use hex super(BoundedLongIntegerProperty, self).__init__(**kwds) self._bits = bits def _validate(self, value): assert -(2 ** (self._bits - 1)) <= value < 2 ** (self._bits - 1) def _to_base_type(self, value): # convert from signed -> unsigned if value < 0: value += 2**self._bits assert 0 <= value < 2**self._bits # Return number as a zero-padded hex string with correct number of # digits: return "%0*x" % (self._bits // 4, value) def _from_base_type(self, value): value = int(value, 16) if value >= 2 ** (self._bits - 1): value -= 2**self._bits return value # Define an entity class holding some long integers. class MyModel(ndb.Model): name = ndb.StringProperty() abc = LongIntegerProperty(default=0) xyz = LongIntegerProperty(repeated=True) class FuzzyDate(object): def __init__(self, first, last=None): assert isinstance(first, date) assert last is None or isinstance(last, date) self.first = first self.last = last or first class FuzzyDateModel(ndb.Model): first = ndb.DateProperty() last = ndb.DateProperty() class FuzzyDateProperty(ndb.StructuredProperty): def __init__(self, **kwds): super(FuzzyDateProperty, self).__init__(FuzzyDateModel, **kwds) def _validate(self, value): assert isinstance(value, FuzzyDate) def _to_base_type(self, value): return FuzzyDateModel(first=value.first, last=value.last) def _from_base_type(self, value): return FuzzyDate(value.first, value.last) class MaybeFuzzyDateProperty(FuzzyDateProperty): def _validate(self, value): if isinstance(value, date): return FuzzyDate(value) # Must return the converted value! # Otherwise, return None and leave validation to the base class # Class to record historic people and events in their life. class HistoricPerson(ndb.Model): name = ndb.StringProperty() birth = FuzzyDateProperty() death = FuzzyDateProperty() # Parallel lists: event_dates = FuzzyDateProperty(repeated=True) event_names = ndb.StringProperty(repeated=True)