Fix too long line in soc.views.models.program module.
[Melange.git] / scripts / stats.py
blob9ed2b10fe16149665fdc32a110fb637b36b65716
1 #!/usr/bin/python2.5
3 # Copyright 2009 the Melange authors.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """Starts an interactive shell with statistic helpers.
18 """
20 __authors__ = [
21 '"Sverre Rabbelier" <sverre@rabbelier.nl>',
25 import cPickle
26 import datetime
27 import operator
28 import sys
30 import interactive
33 def dateFetch(queryGen, last=None, batchSize=100):
34 """Iterator that yields an entity in batches.
36 Args:
37 queryGen: should return a Query object
38 last: used to .filter() for last_modified_on
39 batchSize: how many entities to retrieve in one datastore call
41 Retrieved from http://tinyurl.com/d887ll (AppEngine cookbook).
42 """
44 from google.appengine.ext import db
46 # AppEngine will not fetch more than 1000 results
47 batchSize = min(batchSize,1000)
49 query = None
50 done = False
51 count = 0
53 while not done:
54 print count
55 query = queryGen()
56 query.order('last_modified_on')
57 if last:
58 query.filter("last_modified_on > ", last)
59 results = query.fetch(batchSize)
60 for result in results:
61 count += 1
62 yield result
63 if batchSize > len(results):
64 done = True
65 else:
66 last = results[-1].last_modified_on
69 def addKey(target, fieldname):
70 """Adds the key of the specified field.
71 """
73 result = target.copy()
74 result['%s_key' % fieldname] = target[fieldname].key().name()
75 return result
78 def getEntities(model):
79 """Returns all users as dictionary.
80 """
82 def wrapped():
83 gen = lambda: model.all()
84 it = interactive.deepFetch(gen)
86 entities = [(i.key().name(), i) for i in it]
87 return dict(entities)
89 return wrapped
92 def getProps(last=None):
93 """Returns all proposals as a list of dictionaries.
94 """
96 key_order = [
97 'link_id', 'scope_path', 'title', 'abstract', 'content',
98 'additional_info', '_mentor', 'possible_mentors', 'score',
99 'status', '_org', 'created_on', 'last_modified_on']
101 from soc.models.student_proposal import StudentProposal
103 gen = lambda: StudentProposal.all()
105 it = dateFetch(gen, last)
107 proposals = [(i.key().name(), i.toDict(key_order)) for i in it]
108 if proposals:
109 last = i.last_modified_on # last modified entity
110 else:
111 last = datetime.datetime.now()
113 return dict(proposals), last
116 def orgStats(target, orgs):
117 """Retrieves org stats.
120 from soc.logic import dicts
122 orgs = [(v.key(), v) for k, v in orgs.iteritems()]
123 orgs = dict(orgs)
125 grouped = dicts.groupby(target.values(), '_org')
127 grouped = [(orgs[k], v) for k, v in grouped.iteritems()]
128 popularity = [(k.link_id, len(v)) for k, v in grouped]
130 return dict(grouped), dict(popularity)
133 def countStudentsWithProposals():
134 """Retrieves number of Students who have submitted at least one Student Proposal.
137 proposals = getStudentProposals()
138 students = {}
140 for proposal_key in proposals.keys():
141 students[proposals[proposal_key].scope_path] = True
143 return len(students)
146 def printPopularity(popularity):
147 """Prints the popularity for the specified proposals.
150 g = operator.itemgetter(1)
152 for item in sorted(popularity.iteritems(), key=g, reverse=True):
153 print "%s: %d" % item
156 def saveValues(values, saver):
157 """Saves the specified popularities.
160 import logging
161 from google.appengine.ext import db
163 from soc.models.organization import Organization
165 def txn(key, value):
166 org = Organization.get_by_key_name(key)
167 saver(org, value)
168 org.put()
170 for key, value in sorted(values.iteritems()):
171 print key
172 db.run_in_transaction_custom_retries(10, txn, key, value)
174 print "done"
177 def addFollower(follower, proposals, add_public=True, add_private=True):
178 """Adds a user as follower to the specified proposals.
180 Args:
181 follower: the User to add as follower
182 proposals: a list with the StudnetProposals that should be subscribed to
183 add_public: whether the user is subscribed to public updates
184 add_private: whether the user should be subscribed to private updates
187 from soc.models.review_follower import ReviewFollower
189 result = []
191 for i in proposals:
192 properties = {
193 'user': follower,
194 'link_id': follower.link_id,
195 'scope': i,
196 'scope_path': i.key().name(),
197 'key_name': '%s/%s' % (i.key().name(), follower.link_id),
198 'subscribed_public': add_public,
199 'subscribed_private': add_private,
202 entity = ReviewFollower(**properties)
203 result.append(entity)
205 return result
208 def loadPickle(name):
209 """Loads a pickle.
212 f = open(name + '.dat')
213 return cPickle.load(f)
216 def dumpPickle(target, name):
217 """Dumps a pickle.
220 f = open("%s.dat" % name, 'w')
221 cPickle.dump(target, f)
224 def main(args):
225 """Main routine.
228 interactive.setup()
230 from soc.models.organization import Organization
231 from soc.models.user import User
232 from soc.models.student import Student
233 from soc.models.mentor import Mentor
234 from soc.models.org_admin import OrgAdmin
236 def slotSaver(org, value):
237 org.slots = value
238 def popSaver(org, value):
239 org.nr_applications = value
240 def rawSaver(org, value):
241 org.slots_calculated = value
243 context = {
244 'load': loadPickle,
245 'dump': dumpPickle,
246 'orgStats': orgStats,
247 'printPopularity': printPopularity,
248 'saveValues': saveValues,
249 'getOrgs': getEntities(Organization),
250 'getUsers': getEntities(User),
251 'getStudents': getEntities(Student),
252 'getMentors': getEntities(Mentor),
253 'getOrgAdmins': getEntities(OrgAdmin),
254 'getProps': getProps,
255 'countStudentsWithProposals': countStudentsWithProposals,
256 'addFollower': addFollower,
257 'Organization': Organization,
258 'User': User,
259 'Student': Student,
260 'Mentor': Mentor,
261 'OrgAdmin': OrgAdmin,
262 'slotSaver': slotSaver,
263 'popSaver': popSaver,
264 'rawSaver': rawSaver,
267 interactive.remote(args, context)
269 if __name__ == '__main__':
270 if len(sys.argv) < 2:
271 print "Usage: %s app_id [host]" % (sys.argv[0],)
272 sys.exit(1)
274 main(sys.argv[1:])