I've got a simple external method that returns a
list containing dictionaries. If I run it from python it works fine, imported
and used in Zope it raises an exception "Loop over
non-sequence".
The script extracts some data from a table,
containing the results from a parsed logfile, created by the game Counter-strike
( if you're interested ). I'm no expert in SQL ( as the code below probably
shows )
but doing it in Python is no match ( even if the
code is verbose and perhaps a bit inefficient. Tips and clues are appreciated if
you can make anything out of it ).
I import the method in Zope, calling it
PlayerStats, from the module CSPlayerStats. The file itself is the
Extensions-folder under the Zope main-folder. Try to test it in the ZMI and the
error pops up. Thought of using it like so :
<dtml-in PlayerStats>
<dtml-let
item=sequence-item>
<dtml-var
"item['player']"><!-- more fields from the dictionary, here represented as
item --><br>
</dtml-let>
</dtml-in>
The external method :
import MySQLdb
SQL_PLAYER_INFO =
"""
select
cs_attacker,
cs_attacker_clantag,
cs_weapon,
cs_event,
cs_health,
cs_damage,
cs_armor,
cs_damage_armor,
cs_victim,
cs_team_attacker,
cs_team_victim
from cs_log
order
by
cs_attacker,
cs_event,
cs_weapon
"""
SQL_DEATHS = """
select
cs_victim,
count(*) as deaths
from cs_log
where cs_event =
1
group by cs_victim
order by deaths desc
"""
SQL_KILLS = """
select
cs_attacker,
count(*) as kills
from cs_log
where cs_event
= 1
group by cs_attacker
order by kills desc
"""
SQL_HOSTAGE_KILLS = """
select
cs_attacker,
count(*) as kills
from cs_log
where cs_event
= 5
group by cs_attacker
order by kills desc
"""
SQL_TEAM_KILLS = """
select
cs_attacker,
count(*) as kills
from cs_log
where cs_event
= 3
group by cs_attacker
order by kills desc
"""
SQL_RESCUED_HOSTAGE = """
select
cs_attacker,
count(*) as rescued_hostages
from
cs_log
where cs_event = 7
group by cs_attacker
order by
rescued_hostages desc
"""
SQL_MOST_TEAM_DAMAGE = """
select cs_attacker,
sum(cs_damage) + sum(cs_damage_armor) as damage
from cs_log
where cs_event
= 4
group by cs_attacker
order by damage desc
"""
SQL_MOST_DAMAGE = """
select cs_attacker,
sum(cs_damage)+sum(cs_damage_armor) as damage
from cs_log
where cs_event =
2
group by cs_attacker
order by damage desc
"""
def PlayerStats(self):
players = {}
db =
MySQLdb.connect(db='zopetest')
cur =
db.cursor()
cur.execute(SQL_KILLS)
for player, kills in
cur.fetchall():
players[player] =
{'kills':kills,
'deaths':0,
'team_kills':0,
'team_damage':0,
'hostage_kills':0,
'hostage_rescued':0}
cur.execute(SQL_DEATHS)
res =
cur.fetchall()
for player, deaths in
res:
if not
players.has_key(player):
players[player] = {}
players[player]['deaths'] = deaths
cur.execute(SQL_TEAM_KILLS)
res =
cur.fetchall()
for player, team_kills in
res:
if not
players.has_key(player):
players[player] = {}
players[player]['team_kills'] = team_kills
cur.execute(SQL_RESCUED_HOSTAGE)
res =
cur.fetchall()
for player, hostage_rescued in
res:
if not
players.has_key(player):
players[player] = {}
players[player]['hostage_rescued'] = hostage_rescued
cur.execute(SQL_MOST_TEAM_DAMAGE)
res =
cur.fetchall()
for player, team_damage in
res:
if not
players.has_key(player):
players[player] = {}
players[player]['team_damage'] = team_damage
cur.execute(SQL_MOST_DAMAGE)
res =
cur.fetchall()
for player, damage in
res:
if not
players.has_key(player):
players[player] = {}
players[player]['damage'] = damage
cur.execute(SQL_HOSTAGE_KILLS)
res =
cur.fetchall()
for player, hostage_kills in
res:
if not
players.has_key(player):
players[player] = {}
players[player]['hostage_kills'] = hostage_kills
result =
[]
for player in
players:
kill_death_ratio =
float(players[player]['kills']) /
float(players[player]['deaths'])
damage_team_damage_ratio = float(players[player]['damage']) /
float(players[player]['team_damage'])
score = kill_death_ratio *
damage_team_damage_ratio
result.append((score, player,
players[player]['kills'], players[player]['deaths'], players[player]['damage'],
players[player]['team_damage'], kill_death_ratio,
damage_team_damage_ratio))
result.sort()
result.reverse()
stats
= []
for piece in
result:
score, player, kills,
deaths, damage, team_damage, kd_ratio, dt_ratio =
piece
stats.append({'player':player, 'score':score, 'kills': kills, 'deaths': deaths,
'damage': damage, 'team_damage': team_damage, 'kd_ratio':kd_ratio,
'dt_ratio':dt_ratio})
return stats
Doing something simple like this :
def AList(self):
return
[{'fname':'Thomas'}, {'fname':'Roger'}]
in a module and importing it works just fine.
Testing is ok and the same DTML-piece fitted to the simple method works like a
charm.
What am I doing wrong???
Appreciate any help you can provide.
Best regards,
Thomas Weholt, not yet Zope-meister but want to be
;-)