def editSpot(request, spot_key=None): spot = AutoRetry(models.Spot).get(spot_key) user = auth.get_current_user(request) if request.method == 'POST': spot_form = forms.SpotForm(request.POST) constraint_form = forms.SpotConstraintForm(request.POST) # check if spot is changed # check if new constraint to be added if spot_form.is_valid(): for field in spot_form.fields.keys(): setattr(spot, field, spot_form.cleaned_data[field]) spot.author = user AutoRetry(models.Spot).put(spot) if constraint_form.is_valid(): connectConstraintsAndSpot( saveConstraint(constraint_form.cleaned_data), spot.key()) return HttpResponseRedirect('/traffic_log/spot/%s' % spot.key()) else: return render_to_response( 'traffic_log/create_edit_spot.html', context(spot=forms.SpotForm(instance=spot), spot_key=spot_key, constraints=spot.constraints, constraint_form=forms.SpotConstraintForm(), edit=True, dow_dict=constants.DOW_DICT, formaction="/traffic_log/spot/edit/%s" % spot.key()), context_instance=RequestContext(request))
def all_spot_copy(self): # two queries (since there is no OR statement). # One for copy that does not expire and one for not-yet-expired copy q = SpotCopy.all().filter("spot =", self).filter("expire_on =", None) active_spots = [c for c in AutoRetry(q)] q = SpotCopy.all().filter("spot =", self).filter("expire_on >", datetime.datetime.now()) for c in AutoRetry(q): active_spots.append(c) return active_spots
def get_by_email(cls, email): query = db.Query(cls) query.filter('email =', email) if AutoRetry(query).count() == 0: return None elif AutoRetry(query).count() == 1: return AutoRetry(query).get() else: raise LookupError('User email collision for %s' % email)
def __setitem__(self, varname, value): q = Config.all().filter("varname =", varname) if q.count(1) == 1: cfg = AutoRetry(q).fetch(1)[0] else: cfg = Config() cfg.varname = varname cfg.value = value AutoRetry(cfg).put() self._memcache(varname, value)
def fetch_by_name(cls, name, include_revoked=False): """Fetch a single Artist by name.""" name = name and name.strip() if not name: return None if include_revoked: for art in AutoRetry(cls.all().filter("name =", name)).fetch(1): return art else: for art in AutoRetry(cls.all().filter("revoked =", False) \ .filter("name =", name)).fetch(1): return art return None
def ChirpBroadcast(): """The continuous CHIRP broadcast""" # There is only one persistant live-stream stream. # If it doesn't exist, create it once for all time query = BroadcastPlaylist.all().filter('channel =', 'CHIRP') if AutoRetry(query).count(1): playlist = AutoRetry(query)[0] else: playlist = BroadcastPlaylist(channel='CHIRP') AutoRetry(playlist).put() return playlist
def spotDetail(request, spot_key=None): spot = AutoRetry(models.Spot).get(spot_key) constraints = [ forms.SpotConstraintForm(instance=x) for x in AutoRetry(spot.constraints) ] form = forms.SpotForm(instance=spot) return render_to_response('traffic_log/spot_detail.html', context({ 'spot': spot, 'constraints': constraints, 'dow_dict': constants.DOW_DICT }), context_instance=RequestContext(request))
def deleteSpotConstraint(request, spot_constraint_key=None, spot_key=None): ## XXX only delete if spot_key is none, otherwise just remove the ## constraint from the spot.constraints constraint = models.SpotConstraint.get(spot_constraint_key) if spot_key: constraint.spots.remove(models.Spot.get(spot_key).key()) AutoRetry(constraint).save() else: ## XXX but will this ever really be needed (since you can't ## just create a constraint on it's own right now)? ## should just raise exception AutoRetry(constraint).delete() return HttpResponseRedirect('/traffic_log/spot/edit/%s' % spot_key)
def createEditSpotCopy(request, spot_copy_key=None, spot_key=None): if spot_copy_key: spot_copy = AutoRetry(models.SpotCopy).get(spot_copy_key) spot_key = spot_copy.spot.key( ) # so that dropdown box is selected when editing formaction = reverse('traffic_log.editSpotCopy', args=(spot_copy_key, )) else: if spot_key: formaction = reverse('traffic_log.views.addCopyForSpot', args=(spot_key, )) else: formaction = reverse('traffic_log.createSpotCopy') spot_copy = None user = auth.get_current_user(request) if request.method == 'POST': spot_copy_form = forms.SpotCopyForm(request.POST, { 'author': user, 'spot_key': spot_key }, instance=spot_copy) if spot_copy_form.is_valid(): spot_copy = spot_copy_form.save() old_spot = spot_copy.spot spot_copy.author = user spot_copy.spot = AutoRetry(models.Spot).get( spot_copy_form['spot_key'].data) # Add spot copy to spot's list of shuffled spot copies. spot_copy.spot.add_spot_copy(spot_copy) AutoRetry(spot_copy).put() if old_spot: # just in case this copy was moved from one spot # to another, bust the old cache of spot copies # See Issue 124 old_spot.shuffle_spot_copies() AutoRetry(old_spot).save() return HttpResponseRedirect(reverse('traffic_log.listSpots')) else: spot_copy_form = forms.SpotCopyForm(initial={'spot_key': spot_key}, instance=spot_copy) return render_to_response('traffic_log/create_edit_spot_copy.html', context(spot_copy=spot_copy_form, formaction=formaction), context_instance=RequestContext(request))
def saveConstraint(constraint): dows = [int(x) for x in constraint['dow_list']] hours = constraint['hour_list'] keys = [] slot = int(constraint['slot']) for d in dows: for h in hours: name = ":".join([constants.DOW_DICT[d], str(h), str(slot)]) obj = AutoRetry(models.SpotConstraint).get_or_insert(name, dow=d, hour=int(h), slot=slot) if not obj.is_saved(): AutoRetry(obj).put() keys.append(obj.key()) return keys
def connectConstraintsAndSpot(constraint_keys, spot_key): for constraint in map( AutoRetry(models.SpotConstraint).get, box(constraint_keys)): #sys.stderr.write(",".join(constraint.spots)) if spot_key not in constraint.spots: constraint.spots.append(spot_key) constraint.put()
def deleteSpot(request, spot_key=None): spot = AutoRetry(models.Spot).get(spot_key) spot.active = False AutoRetry(spot).save() # remove the spot from its constraints: for constraint in AutoRetry(models.SpotConstraint.all().filter( "spots IN", [spot.key()])): active_spots = [] for spot_key in constraint.spots: if spot_key != spot.key(): active_spots.append(spot_key) constraint.spots = active_spots AutoRetry(constraint).save() return HttpResponseRedirect('/traffic_log/spot')
def save(self): if not self.current_user: raise ValueError("Cannot save() without a current_user") playlist_track = PlaylistTrack(playlist=self.playlist, selector=self.current_user) if self.cleaned_data['artist_key']: playlist_track.artist = Artist.get(self.cleaned_data['artist_key']) else: playlist_track.freeform_artist_name = self.cleaned_data['artist'] if self.cleaned_data['song_key']: playlist_track.track = Track.get(self.cleaned_data['song_key']) else: playlist_track.freeform_track_title = self.cleaned_data['song'] if self.cleaned_data['album_key']: playlist_track.album = Album.get(self.cleaned_data['album_key']) elif self.cleaned_data['album']: playlist_track.freeform_album_title = self.cleaned_data['album'] if self.cleaned_data['label']: playlist_track.freeform_label = self.cleaned_data['label'] if self.cleaned_data['song_notes']: playlist_track.notes = self.cleaned_data['song_notes'] if self.cleaned_data['is_heavy_rotation']: playlist_track.categories.append('heavy_rotation') if self.cleaned_data['is_light_rotation']: playlist_track.categories.append('light_rotation') if self.cleaned_data['is_local_current']: playlist_track.categories.append('local_current') if self.cleaned_data['is_local_classic']: playlist_track.categories.append('local_classic') AutoRetry(playlist_track).save() return playlist_track
def fetch_recent(max_num_returned=10, start_dt=None, days=None, author_key=None, order="created"): """Returns the most recent reviews, in reverse chronological order.""" if days is not None: if start_dt: end_dt = start_dt + timedelta(days=days) else: end_dt = datetime.now() + timedelta(days=days) else: end_dt = None rev_query = models.Document.all() rev_query.filter("doctype =", models.DOCTYPE_REVIEW) rev_query.order("-%s" % order) if author_key: author = db.get(author_key) rev_query.filter('author =', author) if start_dt: rev_query.filter('created >=', start_dt) if end_dt: rev_query.filter('created <', end_dt) return AutoRetry(rev_query).fetch(max_num_returned)
def createSpot(request): user = auth.get_current_user(request) all_clear = False if request.method == 'POST': spot_form = forms.SpotForm(request.POST, {'author': user}) constraint_form = forms.SpotConstraintForm(request.POST) if constraint_form.is_valid() and spot_form.is_valid(): constraint_keys = saveConstraint(constraint_form.cleaned_data) spot = spot_form.save() spot.author = user AutoRetry(spot).put() connectConstraintsAndSpot(constraint_keys, spot.key()) all_clear = True else: spot_form = forms.SpotForm() constraint_form = forms.SpotConstraintForm() if all_clear: return HttpResponseRedirect(reverse('traffic_log.listSpots')) return render_to_response('traffic_log/create_edit_spot.html', context(spot=spot_form, constraint_form=constraint_form, Author=user, formaction="/traffic_log/spot/create/"), context_instance=RequestContext(request))
def _expunge_expired_spot_copies(self, random_spot_copies): """Check to see if any of the cached spot copies have expired. if so, expunge them and save the spot with a new list. """ q = SpotCopy.all().filter("spot =", self) # GAE sets a maximum length on lists given to the "in" filter # as below, so split "random_spot_copies" into sublists whose # length is this maximum, then operate on the sublists. Note # that we send a copy of "random_spot_copies" to "split_list" # because we will be mutating random_spot_copies as we work. for sublist in split_list(random_spot_copies[:]): one_expired = False q = q.filter("__key__ in", sublist) expired_spot_copy_keys = [] for copy in q: if copy.expire_on and copy.expire_on <= datetime.datetime.now(): expired_spot_copy_keys.append(copy.key()) for expired_key in expired_spot_copy_keys: for k in random_spot_copies: one_expired = True if str(k) == str(expired_key) and k in random_spot_copies: random_spot_copies.remove(k) if one_expired: # only save if we have to since expunging will be rare self.random_spot_copies = random_spot_copies AutoRetry(self).save()
def modify_tags_and_save(user, obj, to_add, to_remove): """Modify the set of tags attached to an object, and save to the datastore. Args: user: The User object of the person responsible for this change to the tags. obj: The object (either an Album or a Track) containing the tags. to_add: A sequence of tags to add to the object. to_remove: A sequence of tags to remove from the object. Returns: True if a modified version of the object was saved, or False if no changes were necessary. """ to_add = list(set(to_add).difference(obj.current_tags)) to_remove = list(set(to_remove).intersection(obj.current_tags)) if not (to_add or to_remove): return False obj.current_tags = list( set(obj.current_tags).union(to_add).difference(to_remove)) tag_edit = models.TagEdit(parent=obj, subject=obj, author=user, added=to_add, removed=to_remove) # The two objects are in the same entity group, so saving them # is an all-or-nothing operation. AutoRetry(db).save([obj, tag_edit]) # Update search indexer. idx = search.Indexer(obj.parent_key()) for tag in to_remove: idx.remove_key(obj.key(), 'tag', tag) for tag in to_add: idx.add_key(obj.key(), 'tag', tag) idx.save() return True
def query_group_by_track_key(from_date, to_date): ''' app engine Query and GqlQuery do not support SQL group by manually count each record and group them by some unique key ''' query = filter_tracks_by_date_range(from_date, to_date) fields = ['album_title', 'artist_name', 'label'] # key_item = 'group_by_key' key_counter = 'play_count' # group by key/fields def item_key(item): key_parts = [] for key in fields: stub = as_encoded_str(_get_entity_attr(item, key, '')) if stub is None: # for existing None-type attributes stub = '' stub = stub.lower() key_parts.append(stub) return ','.join(key_parts) # dict version of db rec def item2hash(item): d = {} for key in fields: d[key] = _get_entity_attr(item, key, None) # init additional props d[key_counter] = 0 d['from_date'] = from_date d['to_date'] = to_date d['heavy_rotation'] = int(bool(HEAVY_ROTATION_TAG in item.categories)) d['light_rotation'] = int(bool(LIGHT_ROTATION_TAG in item.categories)) return d # unique list of tracks with order items = [] # hash of seen keys seen = {} for item in AutoRetry(query): key = item_key(item) if not seen.has_key(key): x = item2hash(item) seen[key] = x items.append(x) # inc counter seen[key][key_counter] += 1 return items
def finish_spot_copy(self): # Pop off spot copy from this spot's shuffled list of spot copies. spot_copy = self.random_spot_copies.pop(0) # If shuffled spot copy list is empty, regenerate. if len(self.random_spot_copies) == 0: self.shuffle_spot_copies(spot_copy) AutoRetry(self).save()
def all_spot_copy(self, check_start_date=False): """ Returns all spot copies assigned to this spot. If check_start_date is true, will only return spot copies that have started. """ # two queries (since there is no OR statement). # One for copy that does not expire and one for not-yet-expired copy active_spots = [] q = SpotCopy.all().filter("spot =", self).filter("expire_on =", None) for c in AutoRetry(q): if not check_start_date or c.has_started(): active_spots.append(c) q = SpotCopy.all().filter("spot =", self).filter("expire_on >", datetime.datetime.now()) for c in AutoRetry(q): if not check_start_date or c.has_started(): active_spots.append(c) return active_spots
def main_page(request): tmpl = loader.get_template('auth/main_page.html') all_users = list(User.all().order('last_name').order('first_name')) msg = '' """Send password reset emails to selected users.""" if request.method == 'POST': if request.POST.get('SendPwdEmails'): num_emails = 0 for i, user in enumerate(all_users): if request.POST.get('checkbox_%d' % (i + 1)): num_emails += 1 # Assemble the URL that can be used to access the password # reset form. token = auth.get_password_reset_token(user) url = 'http://%s/auth/reset_password?token=%s' % ( os.environ['HTTP_HOST'], token) logging.warn('Sent password recovery URL: %s', url) # Send the email message. msg_tmpl = loader.get_template( 'auth/reset_password_email.txt') msg_ctx = Context({'user': user, 'url': url}) msg_body = msg_tmpl.render(msg_ctx) # print msg_body email.send_to_user( user, subject='Please Set/Reset your CHIRP password', body=msg_body) if num_emails: msg = 'Email(s) sent.' """Lists all users.""" num_active_users = sum(u.is_active for u in AutoRetry(all_users)) active = [u for u in AutoRetry(all_users) if u.is_active] inactive = [u for u in AutoRetry(all_users) if not u.is_active] ctx = RequestContext( request, { 'title': 'User Management', 'all_users': active + inactive, 'num_active_users': num_active_users, 'msg': msg }) return http.HttpResponse(tmpl.render(ctx))
def listSpots(request): spots = [] # TODO(Kumar) introduce paging? for spot in AutoRetry(models.Spot.all().order('-created')).fetch(200): if spot.active is False: continue spots.append(spot) return render_to_response('traffic_log/spot_list.html', context({'spots': spots}), context_instance=RequestContext(request))
def add_tag_and_save(user, obj, new_tag, insert=False): """Adds a single tag to an object, and save to the datastore. Args: user: The User object of the person responsible for this change to the tags. obj: The object (either an Album or a Track) containing the tags. new_tag: A single item to add to the object's list of tags. insert: Whether to insert a new tag entity into the datastore. Returns: True if a modified version of the object was saved, or False if no changes were necessary. """ if insert and AutoRetry(models.Tag.all().filter("name =", new_tag)).count() == 0: tag = models.Tag(name=new_tag) AutoRetry(tag).put() return modify_tags_and_save(user, obj, [new_tag], [])
def get_by_url(cls, url): """Fetches an image from the datastore by URL. Returns None if no matching image can be found. """ i = url.find(cls.URL_PREFIX) if i == -1: return None sha1 = url[i + len(cls.URL_PREFIX):] key_name = cls.get_key_name(sha1) return AutoRetry(cls).get_by_key_name(key_name)
def iter_spots(self): for spot in AutoRetry(Spot).get(self.spots): if spot is None: # there was a bug where deleted spots had lingering constraints. # See http://code.google.com/p/chirpradio/issues/detail?id=103 continue copy, is_logged = spot.get_spot_copy(self.dow, self.hour, self.slot) if copy is None: # probably a spot with expired copy (or copy not yet created) continue yield spot
def delete_event(request, event_key): e = None try: e = AutoRetry(PlaylistEvent).get(event_key) except BadKeyError: pass else: if e and e.selector.key() == auth.get_current_user(request).key(): e.delete() playlist_event_listeners.delete(event_key) return HttpResponseRedirect(reverse('playlists_landing_page'))
def remove_key(self, key, field, text): for term in set(explode(text)): sm = self._get_matches(key.kind(), field, term, key) sm.matches.remove(key) if not sm.matches: # Remove empty search index from datastore. AutoRetry(db).delete(sm) # Remove cached entry. _key = (key.kind(), field, term) if _key in self._matches: del self._matches[_key]
def _fetch_all(query): """Returns a set of (db.Key, matching field) pairs.""" # For now, we don't actually return all results --- just the # results we can gather from the first 999 match objects. # That should always be enough. all_matches = set() for sm in AutoRetry(query).fetch(limit=999): # Ignore objects that are not in the current generation. if sm.generation != _GENERATION: continue all_matches.update((m, sm.field) for m in sm.matches) return all_matches
def create_artists(all_artist_names): """Adds a set of artists to the datastore inside of a transaction. Args: all_artist_names: A sequence of unicode strings, which are the names of the artists to be added. """ idx = Indexer() artist_objs = [] for name in all_artist_names: art = models.Artist.create(name=name, parent=idx.transaction) idx.add_artist(art) AutoRetry(idx).save()
def __init__(self, spot_constraint, spot): self.spot = spot q = (TrafficLogEntry.all() .filter("log_date =", time_util.chicago_now().date()) .filter("spot =", spot) .filter("hour =", spot_constraint.hour) .filter("slot =", spot_constraint.slot) .filter("dow =", spot_constraint.dow)) if AutoRetry(q).count(1): self.finished = True else: self.finished = False