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.
21 '"Sverre Rabbelier" <sverre@rabbelier.nl>',
33 def dateFetch(queryGen
, last
=None, batchSize
=100):
34 """Iterator that yields an entity in batches.
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).
44 from google
.appengine
.ext
import db
46 # AppEngine will not fetch more than 1000 results
47 batchSize
= min(batchSize
,1000)
56 query
.order('last_modified_on')
58 query
.filter("last_modified_on > ", last
)
59 results
= query
.fetch(batchSize
)
60 for result
in results
:
63 if batchSize
> len(results
):
66 last
= results
[-1].last_modified_on
69 def addKey(target
, fieldname
):
70 """Adds the key of the specified field.
73 result
= target
.copy()
74 result
['%s_key' % fieldname
] = target
[fieldname
].key().name()
78 def getEntities(model
):
79 """Returns all users as dictionary.
83 gen
= lambda: model
.all()
84 it
= interactive
.deepFetch(gen
)
86 entities
= [(i
.key().name(), i
) for i
in it
]
92 def getProps(last
=None):
93 """Returns all proposals as a list of dictionaries.
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
]
109 last
= i
.last_modified_on
# last modified entity
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()]
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()
140 for proposal_key
in proposals
.keys():
141 students
[proposals
[proposal_key
].scope_path
] = True
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 savePopularity(popularities
):
157 """Saves the specified popularities.
161 from google
.appengine
.ext
import db
163 from soc
.models
.organization
import Organization
165 def txn(key_name
, popularity
):
166 org
= Organization
.get_by_key_name(key_name
)
167 org
.nr_applications
= popularity
170 for key
, value
in sorted(popularities
.iteritems()):
172 db
.run_in_transaction_custom_retries(10, txn
, key
, value
)
177 def addFollower(follower
, proposals
, add_public
=True, add_private
=True):
178 """Adds a user as follower to the specified proposals.
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
194 'link_id': follower
.link_id
,
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
)
208 def loadPickle(name
):
212 f
= open(name
+ '.dat')
213 return cPickle
.load(f
)
216 def dumpPickle(target
, name
):
220 f
= open("%s.dat" % name
, 'w')
221 cPickle
.dump(target
, f
)
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
239 'orgStats': orgStats
,
240 'printPopularity': printPopularity
,
241 'savePopularity': savePopularity
,
242 'getOrgs': getEntities(Organization
),
243 'getUsers': getEntities(User
),
244 'getStudents': getEntities(Student
),
245 'getMentors': getEntities(Mentor
),
246 'getOrgAdmins': getEntities(OrgAdmin
),
247 'getProps': getProps
,
248 'countStudentsWithProposals': countStudentsWithProposals
,
249 'addFollower': addFollower
,
250 'Organization': Organization
,
254 'OrgAdmin': OrgAdmin
,
257 interactive
.remote(args
, context
)
259 if __name__
== '__main__':
260 if len(sys
.argv
) < 2:
261 print "Usage: %s app_id [host]" % (sys
.argv
[0],)