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 ;-)