Odoo 12 AttributeError: 'bool' object has no attribute 'ids' - odoo-10

I am trying to get mail when a new record is created and modified for a field in CRM Module so I have defined these functions
in py:
#api.multi
def write (self, vals):
if 'lead_status' in vals and self.ids:
for rec in self:
template = self.env.ref ('crm_extended.crm_lead_mail_template')
template.send_mail (rec.id, force_send = True)
return super (crm_extended, self) .write (vals)
#api.multi
def create (self, vals):
if 'lead_status' in vals and self.ids:
for rec in self:
template = self.env.ref ('crm_extended.create_crm_lead_mail_template')
template.send_mail (rec.id, force_send = True)
return super (crm_extended, self) .write (vals)
when the change the state or give save, odoo popping me an error as below
Error:
Odoo Server Error
Traceback (most recent call last):
File "/opt/odoo/odoo-12.0/odoo/http.py", line 656, in _handle_exception
return super (JsonRequest, self) ._ handle_exception (exception)
File "/opt/odoo/odoo-12.0/odoo/http.py", line 314, in _handle_exception
raise pycompat.reraise (type (exception), exception, sys.exc_info () [2])
File "/opt/odoo/odoo-12.0/odoo/tools/pycompat.py", line 87, in reraise
raise value
File "/opt/odoo/odoo-12.0/odoo/http.py", line 698, in dispatch
result = self._call_function (** self.params)
File "/opt/odoo/odoo-12.0/odoo/http.py", line 346, in _call_function
return checked_call (self.db, * args, ** kwargs)
File "/opt/odoo/odoo-12.0/odoo/service/model.py", line 98, in wrapper
return f (dbname, * args, ** kwargs)
File "/opt/odoo/odoo-12.0/odoo/http.py", line 339, in checked_call
result = self.endpoint (* a, ** kw)
File "/opt/odoo/odoo-12.0/odoo/http.py", line 941, in __call__
return self.method (* args, ** kw)
File "/opt/odoo/odoo-12.0/odoo/http.py", line 519, in response_wrap
response = f (* args, ** kw)
File "/opt/odoo/odoo-12.0/addons/web/controllers/main.py", line 962, in call_kw
return self._call_kw (model, method, args, kwargs)
File "/opt/odoo/odoo-12.0/addons/web/controllers/main.py", line 954, in _call_kw
return call_kw (request.env [model], method, args, kwargs)
File "/opt/odoo/odoo-12.0/odoo/api.py", line 757, in call_kw
return _call_kw_model_create (method, model, args, kwargs)
File "/opt/odoo/odoo-12.0/odoo/api.py", line 737, in _call_kw_model_create
result = method (recs, * args, ** kwargs)
File "<decorator-gen-260>", line 2, in create
File "/opt/odoo/odoo-12.0/odoo/api.py", line 461, in _model_create_multi
return create (self, [arg])
File "/opt/odoo/odoo-12.0/addons/base_automation/models/base_automation.py", line 231, in create
action._process (action._filter_post (records))
File "/opt/odoo/odoo-12.0/addons/base_automation/models/base_automation.py", line 164, in _filter_post
return self._filter_post_export_domain (records) [0]
File "/opt/odoo/odoo-12.0/addons/base_automation/models/base_automation.py", line 169, in _filter_post_export_domain
domain = [('id', 'in', records.ids)] + safe_eval (self.filter_domain, self._get_eval_context ())
AttributeError: 'bool' object has no attribute 'ids'
function:
#api.multi
def create (self, vals):
if 'lead_status' in vals and self.ids:
for rec in self:
template = self.env.ref ('crm_extended.create_crm_lead_mail_template')
template.send_mail (rec.id, force_send = True)
return super (crm_extended, self) .write (vals)

you can not write #api.multi above the create method.
you have to use #api.model.

You tried to use self before calling super and you called the super write method instead of the create method.
Try to correct the create method inheritance:
#api.model
def create(self, vals):
res = super(crm_extended, self).create(vals)
if 'lead_status' in vals:
template = self.env.ref('crm_extended.create_crm_lead_mail_template')
for record in res:
template.send_mail (record.id, force_send=True)
return res

Related

Python discord-bot

#-----Import Libraries-----#
import discord
import random
from discord.ext import commands
intents = discord.Intents.all()
intents.members = True
client= commands.Bot(command_prefix='#', intents=intents)
#Tictactoe
player1=""
player2=""
turn=""
gameover =True
board=[]
winningConditions = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
]
#client.event
async def on_ready():
guild_count = 0
for guild in client.guilds:
print(f' - id: {guild.id} name: {guild.name}')
guild_count+=1
print('Test run is in ' + str(guild_count) + ' servers.')
client.event
async def on_message(message):
if '#tictactoe' in message.content:
global player1
global player2
global turn
global gameover
global count
global board
await message.channel.send('Who do you want to play against?')
try:
message=await client.wait_for('message', check=lambda m: m.author==message.author and m.channel==message.channel, timeout=15)
except asyncio.TimeoutError:
message.channel.send('you ran out of time')
else:
if gameover:
global board
board=[":white_large_square:",":white_large_square:",":white_large_square:",
":white_large_square:",":white_large_square:",":white_large_square:",
":white_large_square:",":white_large_square:",":white_large_square:"]
turn=""
gameover=False
count=0
player1=message.author
player2=message.mentions[0]
#print board
line=""
for x in range(len(board)):
if x==2 or x==5 or x==8:
line+=""+board[x]
await message.channel.send(line)
line=""
else:
line+=""+board[x]
#who goes first
num=random.randint(1,2)
if num==1:
turn=player1
message.channel.send("it is <#"+str(player1.id)+">'s turn")
else:
turn=player2
await message.channel.send("it is <#"+str(player2.id)+">'s turn")
else:
await message.channel.send("A game is already in progress")
#-----Execute bot-----#
client.run('OTMwMDYzMzMzOTY3NjgzNjM0.Ydwa-g.ds5OBaMSOEAUL72AYkSURgrdl54')
And this is the error I keep getting. When i tried the same code in another laptop it worked although i have the same libraries.
Traceback (most recent call last):
File "C:\Users\Nagariamf\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\http.py", line 300, in static_login
data = await self.request(Route('GET', '/users/#me'))
File "C:\Users\Nagariamf\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\http.py", line 254, in request
raise HTTPException(r, data)
discord.errors.HTTPException: 401 Unauthorized (error code: 0): 401: Unauthorized
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "D:\FIDYAN\python\projecttk.py", line 96, in <module>
client.run('OTMwMDYzMzMzOTY3NjgzNjM0.Ydwa-g.ds5OBaMSOEAUL72AYkSURgrdl54')
File "C:\Users\Nagariamf\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py", line 723, in run
return future.result()
File "C:\Users\Nagariamf\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py", line 702, in runner
await self.start(*args, **kwargs)
File "C:\Users\Nagariamf\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py", line 665, in start
await self.login(*args, bot=bot)
File "C:\Users\Nagariamf\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py", line 511, in login
await self.http.static_login(token.strip(), bot=bot)
File "C:\Users\Nagariamf\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\http.py", line 304, in static_login
raise LoginFailure('Improper token has been passed.') from exc
discord.errors.LoginFailure: Improper token has been passed.
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000024447E19670>
Traceback (most recent call last):
File "C:\Users\Nagariamf\AppData\Local\Programs\Python\Python39\lib\asyncio\proactor_events.py", line 116, in __del__
self.close()
File "C:\Users\Nagariamf\AppData\Local\Programs\Python\Python39\lib\asyncio\proactor_events.py", line 108, in close
self._loop.call_soon(self._call_connection_lost, None)
File "C:\Users\Nagariamf\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 746, in call_soon
self._check_closed()
File "C:\Users\Nagariamf\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 510, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

How can I keep comments of a yaml file when modify its values in nested dictionaries using ruamel.yaml

I'm using solution in the related answer for How to auto-dump modified values in nested dictionaries using ruamel.yaml, which uses the default (round-trip) loader/dumper.
I believe, it is a hard problem since additinal dict should keep comments as well.
=> Would it be possible to prevent comments to be removed if we use modify values in nested dictionaries using ruamel.yaml approach?
Example:
config.yaml:
c: # my comment
b:
f: 5
a:
z: 4
b: 4 # my comment
code (same code from How to auto-dump modified values in nested dictionaries using ruamel.yaml
), which changed to use the default (round-trip) loader/dumper:
#!/usr/bin/env python3
from pathlib import Path
from ruamel.yaml import YAML, representer
class SubConfig(dict):
def __init__(self, parent):
self.parent = parent
def updated(self):
self.parent.updated()
def __setitem__(self, key, value):
if isinstance(value, dict):
v = SubConfig(self)
v.update(value)
value = v
super().__setitem__(key, value)
self.updated()
def __getitem__(self, key):
try:
res = super().__getitem__(key)
except KeyError:
super().__setitem__(key, SubConfig(self))
self.updated()
return super().__getitem__(key)
return res
def __delitem__(self, key):
res = super().__delitem__(key)
self.updated()
def update(self, *args, **kw):
for arg in args:
for k, v in arg.items():
self[k] = v
for k, v in kw.items():
self[k] = v
self.updated()
return
_SR = representer.RoundTripRepresenter
_SR.add_representer(SubConfig, _SR.represent_dict)
class Config(dict):
def __init__(self, filename, auto_dump=True):
self.filename = filename if hasattr(filename, "open") else Path(filename)
self.auto_dump = auto_dump
self.changed = False
self.yaml = YAML()
self.yaml.indent(mapping=4, sequence=4, offset=2)
self.yaml.default_flow_style = False
if self.filename.exists():
with open(filename) as f:
self.update(self.yaml.load(f) or {})
def updated(self):
if self.auto_dump:
self.dump(force=True)
else:
self.changed = True
def dump(self, force=False):
if not self.changed and not force:
return
with open(self.filename, "w") as f:
self.yaml.dump(dict(self), f)
self.changed = False
def __setitem__(self, key, value):
if isinstance(value, dict):
v = SubConfig(self)
v.update(value)
value = v
super().__setitem__(key, value)
self.updated()
def __getitem__(self, key):
try:
res = super().__getitem__(key)
except KeyError:
super().__setitem__(key, SubConfig(self))
self.updated()
return super().__getitem__(key)
def __delitem__(self, key):
res = super().__delitem__(key)
self.updated()
def update(self, *args, **kw):
for arg in args:
for k, v in arg.items():
self[k] = v
for k, v in kw.items():
self[k] = v
self.updated()
cfg = Config(Path("config.yaml"))
=> config.yaml file is updated as follows, where its comments are removed:
c:
b:
f: 5
a:
z: 4
b: 4
Yes, it is possible to prevent comments from being lost. The object returned from self.yaml.load() in your Config.__init__() method is not a dict, but a subclass thereof (ruamel.yaml.comments.CommentedMap) that includes all of the comment information (in its .ca attribute. And that CommentedMap will have values that are in itself again CommentedMap instances (at least with your input.
So what you need to do is change your classes:
class Config(ruamel.yaml.comments.CommentedMap):
and do the same for SubConfig. Then during the update routine you should try to copy the .ca attribute (it will be created empty on the CommentedMap, but not be available on {})
Make sure you all add a the representer for Config, and don't cast to dict in your Config.dump() method.
If you also copy the .fa attribute of the loaded data (also on Subconfig), you'll preserve the flow/block style of the original, and you can do a away with the self.yaml.default_flow_style = False.
The above is the theory, in practise there are a few more issues.
Your config.yaml changes, although you do not explicitly dump. That is
because your auto_dump is True by default. But that also means it
dumps for every change, i.e. your config.yaml gets dumped 10 (ten) times while the
Config/SubConfig data structure gets build.
I changed this to dump only once if auto_dump is True, but even that I would not
recommend, instead only dump if changed after loading.
A dict doesn't need initializing, but a CommentedMap does.
If you don't you get an attribute error at some point. So you'll have to
call super().__init__(self) in each the __init__ of each class.
from pathlib import Path
import ruamel.yaml
_SR = ruamel.yaml.representer.RoundTripRepresenter
class SubConfig(ruamel.yaml.comments.CommentedMap):
def __init__(self, parent):
self.parent = parent
super().__init__(self)
def updated(self):
self.parent.updated()
def __setitem__(self, key, value):
if isinstance(value, dict):
v = SubConfig(self)
v.update(value)
value = v
super().__setitem__(key, value)
self.updated()
def __getitem__(self, key):
try:
res = super().__getitem__(key)
except KeyError:
super().__setitem__(key, SubConfig(self))
self.updated()
return super().__getitem__(key)
return res
def __delitem__(self, key):
res = super().__delitem__(key)
self.updated()
def update(self, *args, **kw):
for arg in args:
for k, v in arg.items():
self[k] = v
for attr in [ruamel.yaml.comments.Comment.attrib, ruamel.yaml.comments.Format.attrib]:
if hasattr(arg, attr):
setattr(self, attr, getattr(arg, attr))
for k, v in kw.items():
self[k] = v
self.updated()
return
_SR.add_representer(SubConfig, _SR.represent_dict)
class Config(ruamel.yaml.comments.CommentedMap):
def __init__(self, filename, auto_dump=True):
super().__init__(self)
self.filename = filename if hasattr(filename, "open") else Path(filename)
self.auto_dump = False # postpone setting during loading of config
self.changed = False
self.yaml = ruamel.yaml.YAML()
self.yaml.indent(mapping=4, sequence=4, offset=2)
# self.yaml.default_flow_style = False
if self.filename.exists():
with open(filename) as f:
self.update(self.yaml.load(f) or {})
self.auto_dump = auto_dump
if auto_dump:
self.dump()
def updated(self):
if self.auto_dump:
self.dump(force=True)
else:
self.changed = True
def dump(self, force=False):
if not self.changed and not force:
return
# use the capability of dump to take a Path. It will open the file 'wb' as
# is appropriate for a YAML file, which is UTF-8
self.yaml.dump(self, self.filename)
self.changed = False
def __setitem__(self, key, value):
if isinstance(value, dict):
v = SubConfig(self)
v.update(value)
value = v
super().__setitem__(key, value)
self.updated()
def __getitem__(self, key):
try:
res = super().__getitem__(key)
except KeyError:
super().__setitem__(key, SubConfig(self))
self.updated()
return super().__getitem__(key)
def __delitem__(self, key):
res = super().__delitem__(key)
self.updated()
def update(self, *args, **kw):
for arg in args:
for k, v in arg.items():
self[k] = v
for attr in [ruamel.yaml.comments.Comment.attrib, ruamel.yaml.comments.Format.attrib]:
if hasattr(arg, attr):
setattr(self, attr, getattr(arg, attr))
for k, v in kw.items():
self[k] = v
self.updated()
_SR.add_representer(Config, _SR.represent_dict)
fn = Path('config.yaml')
fn.write_text("""
c: # my comment
b:
f: 5
x: {g: 6}
a:
z: 4
b: 4 # my comment
""")
cfg = Config(fn)
print(Path(fn).read_text())
which gives:
c: # my comment
b:
f: 5
x: {g: 6}
a:
z: 4
b: 4 # my comment
Since the input changes, I write the config file to test out on every run.
I also added a flow style dict, to make clear that original formatting is performed.

sqlany-django : Error - 'django.db.backends.utils' has no attribute 'typecast_decimal'

When I am running server in django, getting this error:
File "D:\API\createapi\lib\site-packages\sqlany_django\base.py", line 48, in Database.register_converter(Database.DT_DECIMAL, util.typecast_decimal)
AttributeError: module 'django.db.backends.utils' has no attribute typecast_decimal'.
Found some threads regarding this but was not able to find a solution.
Kindly advise on how to proceed! Thanks in advance.
Base.py
"""
SQL Anywhere database backend for Django.
Requires sqlanydb
"""
import re,ctypes,sys
try:
import sqlanydb as Database
except ImportError as e:
from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured("Error loading sqlanydb module: %s" % e)
from django import VERSION as djangoVersion
if djangoVersion[:2] >= (1, 4):
from django.utils.timezone import is_aware, is_naive, utc, make_naive, make_aware, get_default_timezone
import datetime
from django.conf import settings
if djangoVersion[:2] >= (1, 8):
from django.db.backends.base.features import BaseDatabaseFeatures
from django.db.backends.base.operations import BaseDatabaseOperations
from django.db.backends.base.base import BaseDatabaseWrapper
from django.db.backends import utils as util
else:
from django.db.backends import *
if djangoVersion[:2] >= (1, 7):
# renamed in 1.7
util = utils
from django.db.backends.signals import connection_created
from sqlany_django.client import DatabaseClient
from sqlany_django.creation import DatabaseCreation
from sqlany_django.introspection import DatabaseIntrospection
from sqlany_django.validation import DatabaseValidation
if djangoVersion[:2] >= (1, 7):
from sqlany_django.schema import DatabaseSchemaEditor
if djangoVersion[:2] >= (1, 8):
from sqlany_django.creation import global_data_types
DatabaseError = Database.DatabaseError
IntegrityError = Database.IntegrityError
Database.register_converter(Database.DT_TIMESTAMP, util.typecast_timestamp)
Database.register_converter(Database.DT_DATE, util.typecast_date)
Database.register_converter(Database.DT_TIME, util.typecast_time)
Database.register_converter(Database.DT_DECIMAL, util.typecast_decimal)
Database.register_converter(Database.DT_BIT, lambda x: x if x is None else bool(x))
def trace(x):
# print( x )
return x
def _datetimes_in(args):
def fix(arg):
if isinstance(arg, datetime.datetime):
if is_naive(arg):
warnings.warn("Received a naive datetime (%s) while timezone support is active." % arg, RuntimeWarning)
arg = make_aware(arg, timezone.get_default_timezone())
arg = arg.astimezone(utc).replace(tzinfo=None)
return arg
return tuple(fix(arg) for arg in args)
class CursorWrapper(object):
"""
A thin wrapper around sqlanydb's normal cursor class so that we can catch
particular exception instances and reraise them with the right types.
Implemented as a wrapper, rather than a subclass, so that we aren't stuck
to the particular underlying representation returned by Connection.cursor().
"""
codes_for_integrityerror = (1048,)
def __init__(self, cursor):
self.cursor = cursor
def __del__(self):
if self.cursor:
self.cursor.close()
self.cursor = None
def convert_query(self, query, num_params):
"""
Django uses "format" style placeholders, but SQL Anywhere uses "qmark" style.
This fixes it -- but note that if you want to use a literal "%s" in a query,
you'll need to use "%%s".
"""
return query if num_params == 0 else query % tuple("?" * num_params)
def execute(self, query, args=()):
if djangoVersion[:2] >= (1, 4) and settings.USE_TZ:
args = _datetimes_in(args)
try:
if args != None:
query = self.convert_query(query, len(args))
ret = self.cursor.execute(trace(query), trace(args))
return ret
except Database.OperationalError as e:
if e.message == 'Connection was terminated':
from django import db
try:
db.close_old_connections()
except AttributeError:
db.close_connection()
# Map some error codes to IntegrityError, since they seem to be
# misclassified and Django would prefer the more logical place.
if e.errorcode in self.codes_for_integrityerror:
raise Database.IntegrityError(e)
raise
def executemany(self, query, args):
if djangoVersion[:2] >= (1, 4) and settings.USE_TZ:
args = tuple(_datetimes_in(arg) for arg in args)
try:
try:
len(args)
except TypeError:
args = tuple(args)
if len(args) > 0:
query = self.convert_query(query, len(args[0]))
ret = self.cursor.executemany(trace(query), trace(args))
return trace(ret)
else:
return None
except Database.OperationalError as e:
# Map some error codes to IntegrityError, since they seem to be
# misclassified and Django would prefer the more logical place.
if e.errorcode in self.codes_for_integrityerror:
raise Database.IntegrityError(e)
raise
def fetchone(self):
if djangoVersion[:2] < (1, 4) or not settings.USE_TZ:
return trace(self.cursor.fetchone())
return self._datetimes_out(self.cursor.fetchone())
def fetchmany(self, size=0):
if djangoVersion[:2] < (1, 4) or not settings.USE_TZ:
return trace(self.cursor.fetchmany(size))
rows = self.cursor.fetchmany(size)
return list(self._datetimes_out(row) for row in rows)
def fetchall(self):
if djangoVersion[:2] < (1, 4) or not settings.USE_TZ:
return trace(self.cursor.fetchall())
return list(self._datetimes_out(row) for row in self.cursor.fetchall())
def _datetimes_out(self, row):
def fix(item):
value, desc = item
if desc[1] == Database.DATETIME:
if value is not None and is_naive(value):
value = value.replace(tzinfo=utc)
return value
if row is None:
return row
return trace(tuple(fix(item) for item in zip(row, self.cursor.description)))
def __getattr__(self, attr):
if attr in self.__dict__:
return self.__dict__[attr]
else:
return getattr(self.cursor, attr)
def __iter__(self):
return iter(self.fetchall())
class DatabaseFeatures(BaseDatabaseFeatures):
allows_group_by_pk = False
empty_fetchmany_value = []
has_bulk_insert = True
has_select_for_update = True
has_zoneinfo_database = False
related_fields_match_type = True
supports_regex_backreferencing = False
supports_sequence_reset = False
update_can_self_select = False
uses_custom_query_class = False
class DatabaseOperations(BaseDatabaseOperations):
compiler_module = "sqlany_django.compiler"
def bulk_insert_sql(self, fields, num_values):
items_sql = "(%s)" % ", ".join(["%s"] * len(fields))
return "VALUES " + ", ".join([items_sql] * num_values)
def date_extract_sql(self, lookup_type, field_name):
"""
Given a lookup_type of 'year', 'month' or 'day', returns the SQL that
extracts a value from the given date field field_name.
"""
if lookup_type == 'week_day':
# Returns an integer, 1-7, Sunday=1
return "DATEFORMAT(%s, 'd')" % field_name
else:
# YEAR(), MONTH(), DAY() functions
return "%s(%s)" % (lookup_type.upper(), field_name)
if djangoVersion[:2] >= (1, 8):
# SQL Anywhere does not support the INTERVAL syntax
pass
#def date_interval_sql(self, timedelta):
else:
def date_interval_sql(self, sql, connector, timedelta):
"""
Implements the date interval functionality for expressions
"""
return 'DATEADD(day, %s(%d), DATEADD(second, %s(%d), DATEADD(microsecond, %s(%d), %s)))' % (connector, timedelta.days, connector, timedelta.seconds, connector, timedelta.microseconds, sql)
def date_trunc_sql(self, lookup_type, field_name):
"""
Given a lookup_type of 'year', 'month' or 'day', returns the SQL that
truncates the given date field field_name to a DATE object with only
the given specificity.
"""
fields = ['year', 'month', 'day', 'hour', 'minute', 'second']
format = ('YYYY-', 'MM', '-DD', 'HH:', 'NN', ':SS') # Use double percents to escape.
format_def = ('0000-', '01', '-01', ' 00:', '00', ':00')
try:
i = fields.index(lookup_type) + 1
except ValueError:
sql = field_name
else:
format_str = ''.join([f for f in format[:i]] + [f for f in format_def[i:]])
sql = "CAST(DATEFORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
return sql
def datetime_extract_sql(self, lookup_type, field_name, tzname):
"""
Given a lookup_type of 'year', 'month', 'day', 'hour', 'minute' or
'second', returns the SQL that extracts a value from the given
datetime field field_name, and a tuple of parameters.
"""
if lookup_type == 'week_day':
# Returns an integer, 1-7, Sunday=1
sql = "DATEFORMAT(%s, 'd')" % field_name
else:
# YEAR(), MONTH(), DAY(), HOUR(), MINUTE(), SECOND() functions
sql = "%s(%s)" % (lookup_type.upper(), field_name)
return sql,[]
def datetime_trunc_sql(self, lookup_type, field_name, tzname):
"""
Given a lookup_type of 'year', 'month', 'day', 'hour', 'minute' or
'second', returns the SQL that truncates the given datetime field
field_name to a datetime object with only the given specificity, and
a tuple of parameters.
"""
fields = ['year', 'month', 'day', 'hour', 'minute', 'second']
format = ('YYYY-', 'MM', '-DD', 'HH:', 'NN', ':SS') # Use double percents to escape.
format_def = ('0000-', '01', '-01', ' 00:', '00', ':00')
try:
i = fields.index(lookup_type) + 1
except ValueError:
sql = field_name
else:
format_str = ''.join([f for f in format[:i]] + [f for f in format_def[i:]])
sql = "CAST(DATEFORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
return sql,[]
def deferrable_sql(self):
return ""
def drop_foreignkey_sql(self):
"""
Returns the SQL command that drops a foreign key.
"""
# This will work provided it is inserted in an ALTER TABLE statement
return "DROP FOREIGN KEY"
def force_no_ordering(self):
"""
"ORDER BY NULL" prevents SQL Anywhere from implicitly ordering by grouped
columns. If no ordering would otherwise be applied, we don't want any
implicit sorting going on.
"""
return ["NULL"]
def fulltext_search_sql(self, field_name):
"""
Returns the SQL WHERE clause to use in order to perform a full-text
search of the given field_name. Note that the resulting string should
contain a '%s' placeholder for the value being searched against.
"""
return 'CONTAINS(%s, %%s)' % field_name
def last_insert_id(self, cursor, table_name, pk_name):
cursor.execute('SELECT ##identity')
return cursor.fetchone()[0]
def max_name_length(self):
"""
Returns the maximum length of table and column names, or None if there
is no limit.
"""
# SQL Anywhere 11 has a maximum of 128 for table and column names
return 128
def no_limit_value(self):
"""
Returns the value to use for the LIMIT when we are wanting "LIMIT
infinity". Returns None if the limit clause can be omitted in this case.
"""
return None
def prep_for_iexact_query(self, x):
return x
def query_class(self, DefaultQueryClass):
"""
Given the default Query class, returns a custom Query class
to use for this backend. Returns None if a custom Query isn't used.
See also BaseDatabaseFeatures.uses_custom_query_class, which regulates
whether this method is called at all.
"""
return query.query_class(DefaultQueryClass)
def quote_name(self, name):
"""
Returns a quoted version of the given table, index or column name. Does
not quote the given name if it's already been quoted.
"""
if name.startswith('"') and name.endswith('"'):
return name # Quoting once is enough.
return '"%s"' % name
def regex_lookup(self, lookup_type):
"""
Returns the string to use in a query when performing regular expression
lookups (using "regex" or "iregex"). The resulting string should
contain a '%s' placeholder for the column being searched against.
"""
if lookup_type == 'iregex':
raise NotImplementedError("SQL Anywhere does not support case insensitive regular expressions")
return "%s REGEXP ('.*'||%s||'.*')"
def random_function_sql(self):
"""
Returns a SQL expression that returns a random value.
"""
return 'RAND()'
def savepoint_create_sql(self, sid):
"""
Returns the SQL for starting a new savepoint. Only required if the
"uses_savepoints" feature is True. The "sid" parameter is a string
for the savepoint id.
"""
return 'SAVEPOINT ' + self.quote_name(sid)
def savepoint_commit_sql(self, sid):
"""
Returns the SQL for committing the given savepoint.
"""
return 'COMMIT'
def savepoint_rollback_sql(self, sid):
"""
Returns the SQL for rolling back the given savepoint.
"""
return 'ROLLBACK TO SAVEPOINT ' + self.quote_name(sid)
def sql_flush(self, style, tables, sequences):
"""
Returns a list of SQL statements required to remove all data from
the given database tables (without actually removing the tables
themselves).
"""
if tables:
sql = ['SET TEMPORARY OPTION wait_for_commit = \'On\';']
# TODO: We should truncate tables here, but there may cause an error;
# for now, delete (all) from each table
for table in tables:
sql.append('DELETE FROM %s;' % self.quote_name(table))
# TODO: This requires DBA authority, but once the truncate bug is fixed
# it won't be necessary
for sequence in sequences:
sql.append('call sa_reset_identity(\'%s\', NULL, 0);' % sequence['table'])
sql.append('SET TEMPORARY OPTION wait_for_commit = \'Off\';')
sql.append('COMMIT;')
return sql
def value_to_db_datetime(self, value):
if value is None:
return None
if djangoVersion[:2] <= (1, 3):
# SQL Anywhere doesn't support tz-aware datetimes
if value.tzinfo is not None:
raise ValueError("SQL Anywhere backend does not support timezone-aware datetimes.")
else:
if is_aware(value):
if settings.USE_TZ:
value = value.astimezone(utc).replace(tzinfo=None)
else:
make_naive(value, get_default_timezone())
return str(value)
def value_to_db_time(self, value):
if value is None:
return None
if djangoVersion[:2] <= (1, 3):
# SQL Anywhere doesn't support tz-aware datetimes
if value.tzinfo is not None:
raise ValueError("SQL Anywhere backend does not support timezone-aware datetimes.")
else:
if is_aware(value):
make_naive(value, get_default_timezone())
return str(value)
class DatabaseWrapper(BaseDatabaseWrapper):
vendor = 'sqlanywhere'
operators = {
'exact': '= %s',
'iexact': '= %s',
'contains': "LIKE %s ESCAPE '\\'",
'icontains': "LIKE %s ESCAPE '\\'",
'regex': "REGEXP ('.*'||%s||'.*')",
# 'iregex': "REGEXP ('.*'||%s||'.*')",
'gt': '> %s',
'gte': '>= %s',
'lt': '< %s',
'lte': '<= %s',
'startswith': "LIKE %s ESCAPE '\\'",
'istartswith': "LIKE %s ESCAPE '\\'",
'endswith': "LIKE %s ESCAPE '\\'",
'iendswith': "LIKE %s ESCAPE '\\'"
}
if djangoVersion[:2] >= (1, 8):
# Moved from DatabaseCreation in 1.8
data_types = global_data_types
Database = Database
def __init__(self, *args, **kwargs):
super(DatabaseWrapper, self).__init__(*args, **kwargs)
self.server_version = None
if djangoVersion[:2] >= (1, 3):
self.features = DatabaseFeatures(self)
else:
self.features = DatabaseFeatures()
if djangoVersion[:2] >= (1, 4):
self.ops = DatabaseOperations(self)
else:
self.ops = DatabaseOperations()
self.client = DatabaseClient(self)
self.creation = DatabaseCreation(self)
self.introspection = DatabaseIntrospection(self)
if djangoVersion[:2] >= (1, 2):
self.validation = DatabaseValidation(self)
else:
self.validation = DatabaseValidation()
def _valid_connection(self):
if self.connection is not None:
try:
self.connection.con()
return True
except InterfaceError:
self.connection.close()
self.connection = None
return False
def check_constraints(self, table_names=None):
self.cursor().execute('PREPARE TO COMMIT')
def _cursor(self):
return self.create_cursor()
def _rollback(self):
try:
BaseDatabaseWrapper._rollback(self)
except Database.NotSupportedError:
pass
# New methods for Django 1.6
def get_connection_params(self):
kwargs = {}
links = {}
settings_dict = self.settings_dict
def setting( key ):
if key in settings_dict:
return settings_dict[key]
dbkey = 'DATABASE_%s' % key
if dbkey in settings_dict:
return settings_dict[dbkey]
return None
#
def empty( s ):
return True if ( s is None or s == '' ) else False
#
uid = setting( 'USER' )
if not empty( uid ):
kwargs['uid'] = uid
dbn = setting( 'NAME' )
if not empty( dbn ):
kwargs['dbn'] = dbn
pwd = setting( 'PASSWORD' )
if not empty( pwd ):
kwargs['pwd'] = pwd
root = Database.Root('PYTHON')
try:
vers = root.api.sqlany_client_version()
ret = True
except:
length = 1000
buffer = ctypes.create_string_buffer(length)
ret = root.api.sqlany_client_version(ctypes.byref(buffer), length)
vers = buffer.value
if ret:
if sys.version_info[0] >= 3:
# Python 3: convert bytes to str
vers = str(vers, 'utf-8')
vers = int(vers.split('.')[0])
else:
vers = 11 # assume old
host = setting( 'HOST' )
if host == '':
host = 'localhost' # "Set to empty string for localhost"
if not empty( host ) and vers > 11:
kwargs['host'] = host
port = setting( 'PORT' )
if not empty( port ):
kwargs['host'] += ':%s' % port
else:
if not empty( host ):
links['host'] = host
port = setting( 'PORT' )
if not empty( port ):
links['port'] = str( port )
if len(links) > 0:
kwargs['links'] = 'tcpip(' + ','.join(k+'='+v for k, v in list(links.items())) + ')'
kwargs.update(setting( 'OPTIONS' ))
return kwargs
def get_new_connection( self, conn_params ):
conn = Database.connect(**conn_params)
if conn is not None and djangoVersion[:2] >= (1, 6):
# Autocommit is the default for 1.6+
curs = conn.cursor()
curs.execute( "SET TEMPORARY OPTION chained='Off'" )
curs.close()
return conn
def init_connection_state( self ):
if 'AUTOCOMMIT' in self.settings_dict and \
not self.settings_dict['AUTOCOMMIT']:
self.set_autocommit( False )
def create_cursor( self ):
cursor = None
if not self._valid_connection():
kwargs = self.get_connection_params()
self.connection = self.get_new_connection(kwargs)
cursor = CursorWrapper(self.connection.cursor())
if djangoVersion[:2] < (1, 2):
cursor.execute("SET TEMPORARY OPTION PUBLIC.reserved_keywords='LIMIT'")
cursor.execute("SET TEMPORARY OPTION TIMESTAMP_FORMAT='YYYY-MM-DD HH:NN:SS.SSSSSS'")
connection_created.send(sender=self.__class__, connection=self)
if not cursor:
cursor = CursorWrapper(self.connection.cursor())
return cursor
def _set_autocommit( self, autocommit ):
"""
Backend-specific implementation to enable or disable autocommit.
"""
curs = self.create_cursor()
curs.execute( "SET TEMPORARY OPTION chained='%s'" %
('Off' if autocommit else 'On') )
curs.close()
def is_usable(self):
"""
Tests if the database connection is usable.
This function may assume that self.connection is not None.
"""
return self._valid_connection()
# New methods for Django 1.7
if djangoVersion[:2] >= (1, 7):
def schema_editor(self, *args, **kwargs):
"Returns a new instance of this backend's SchemaEditor"
return DatabaseSchemaEditor( self, *args, **kwargs )

Snakes and Ladders using tkinter python

import random
from tkinter import *
class Spinner(object):
#staticmethod
def getSpin():
newSpin = random.randint(1,6)
return newSpin
class Player(object):
def __init__(self,name):
self.position = 1
self.name = name
def setName(self,name):
self.name = name
def changePosition(self,number):
self.position = self.position + number
def setPosition(self,pos):
self.position = pos
return self.position
def getPosition(self):
return self.position
def getName(self):
return self.name
def spin(self):
newSpin = Spinner.getSpin()
self.position = self.position + newSpin
print(str(self.name) + "'s spin was: " + str(newSpin))
class Path(object):
#staticmethod
def buildLadders():
ladders = [[0 for x in range(2)] for x in range(9)]
ladders[0][0] = 2
ladders[0][1] = 9
ladders[1][0] = 8
ladders[1][1] = 11
return ladders
#staticmethod
def buildChutes():
chutes = [[0 for x in range(2)] for x in range(10)]
chutes[0][0] = 9
chutes[0][1] = 3
chutes[1][0] = 12
chutes[1][1] = 6
return chutes
class Check(Player):
def __init__(self):
super(Check,self).__init__()
def checkLadders(self):
ladders = Path.buildLadders()
for i in range(0,len(ladders),1):
if self.getPosition() == ladders[i][0]:
self.position = self.setPosition(ladders[i][1])
print(str(self.name) + " Landed on a Ladder! from " + \
str(ladders[i][0]) +" to " + str(ladders[i][1]))
def newPosition(self):
return self.position
def checkChutes(self):
chutes = Path.buildChutes()
for i in range(0,len(chutes),1):
if self.getPosition() == chutes[i][0]:
self.position = self.setPosition(chutes[i][1])
print(str(self.name) + " Landed on a Chutes!")
class Match_Position(Player):
def __init__(self,name):
super(Match_Position,self).__init__(name)
self.match = [[70,235],
[180,235],
[290,235],
[400, 235],
[400, 140],
[290, 140],
[180, 140],
[70, 140],
[70, 45],
[180, 45],
[290, 45],
[400, 45]]
self.name = name
self.players = Player(self.name)
self.pos = self.players.getPosition()
self.position_actual = []
self.__str__()
self.actualpos()
def __str__(self):
for j in range(len(self.match)):
if self.pos == (j+1):
self.position_actual.append(self.match[j][0])
self.position_actual.append(self.match[j][1])
def actualpos(self):
return self.position_actual
class Display(object):
def __init__(self,master,img,name):
canvas_width = 650
canvas_height = 300
self.name = name
print(self.name)
self.pos = Match_Position(self.name).actualpos()
print(self.pos)
self.canvas = Canvas(master, width = canvas_width, height = canvas_height, bg = "yellow")
self.canvas.grid(padx=0, pady=0)
self.canvas.create_image(300,150,anchor=CENTER, image = img)
self.animate(master)
def animate(self,master):
Button(master, text= "ROLL", command=self.say_hello(self.name[0])).grid( row=3, column=0, sticky=E)
Button(master, text= "ROLL", command=self.say_hello1(self.name[1])).grid( row=3, column=1, sticky=E)
def say_hello(self,name):
self.name = name
self.name = Player(self.name)
self.name.spin()
Check.checkLadders(self.name)
Check.checkChutes(self.name)
x = self.pos[0]
y = self.pos[1]
self.canvas.create_oval(x,y,x+20,y+20, fill='blue')
def say_hello1(self,name):
self.name = name
self.name = Player(self.name)
self.name.spin()
Check.checkLadders(self.name)
Check.checkChutes(self.name)
x = self.pos[0]
y = self.pos[1]
self.canvas.create_oval(x,y,x+20,y+20, fill='red')
class BounceController(object):
def __init__(self):
master = Tk()
master.title("Snake and Ladder")
master.geometry("700x350")
img = PhotoImage( file = "puzzlor-chutes-and-ladders.gif" )
name = ['n','s']
Display(master,img,name).animate(master)
master.mainloop()
def main():
BounceController()
main()
It printed out this, but the error:
"'Player' object does not support indexing" pop out.
What is object does not support indexing error is?
And when I click the button, the oval does not actually move.
And using tkinter Button, I can call the method, right?
But by doing so, if I want to make for example, clicking the button, result to the oval moving to different location, how do I achieve that? Since as my code, above, the oval does not move eventhough the button is clicked.
Thanks. Since I'm quite new to python and programming, any help would be such a gratitude.
Indexing is when you suffix an object with [n], where n is an int. Here is how to reproduce the message.
>>> class C: pass
>>> C()[1]
Traceback (most recent call last):
File "<pyshell#21>", line 1, in <module>
C()[1]
TypeError: 'C' object does not support indexing
The File entry above the error message tells you the line number and expression that gave the error. Someplace in your code, as indicated by the traceback you did not show us, you have x[n], where x in an instance of the Player class you defined.
An object is subscriptable if and only if it has a __getitem__ method, which Player does not have and should not have.

how to delegate on specific postion(row, col) in PyQt QTreeView

my purpose is to display an different icon in treeview list when a specific postion(row, column) match a value. eg: (row, 2) is dir or file, will diplay different icon. because this is not used in local filesystem, QDir or Qfilesystem model not suite for this.
i know a bit on MVC that controller display in view, make model as data interface api. but i do not how to make it works on specific position(row ,col) as my expect.
i have tried to add args in ImageDelegate(like pass icon file name to it), but failed maybe due to its parent Class not accept more args.
hope someone can give me some light.
class ImageDelegate(QtGui.QStyledItemDelegate):
def __init__(self, parent=None):
QtGui.QStyledItemDelegate.__init__(self, parent)
#self.icon =icon
def paint(self, painter, option, index):
#painter.fillRect(option.rect, QtGui.QColor(191,222,185))
# path = "path\to\my\image.jpg"
path = "icon1.png"
image = QtGui.QImage(str(path))
pixmap = QtGui.QPixmap.fromImage(image)
pixmap.scaled(16, 16, QtCore.Qt.KeepAspectRatio)
painter.drawPixmap(option.rect.x(), option.rect.y(), pixmap)
and i can use this delegate in my view. but it will change all line in specific column.
def init_remotetreeview(self):
self.model = myModel(self.remote_Treeview)
for therow in range(self.model.rowCount(QModelIndex())) :
print self.model.data(self.model.index(therow, 2, QtCore.QModelIndex()),Qt.DisplayRole).toString() # i do check the value will used to load correct icon.
self.remote_Treeview.setItemDelegate(ImageDelegate(self)) # this change all lines
self.remote_Treeview.setModel(self.model)
In fact, your have some light in your code, isn't it ? (Just kidding.)
Your have right way to use QtGui.QStyledItemDelegate. I have reference how to implement it (But, C++ only). 'Star Delegate Example', 'QItemDelegate Class Reference C++' and 'QItemDelegate Class Reference PyQt4';
Keyword : Your have to implement paint draw your element what your want (I think this is your want.)
Little example, Hope is help;
import sys
from PyQt4 import QtCore, QtGui
from functools import partial
class QCustomDelegate (QtGui.QItemDelegate):
signalNewPath = QtCore.pyqtSignal(object)
def createEditor (self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex):
column = indexQModelIndex.column()
if column == 0:
editorQWidget = QtGui.QPushButton(parentQWidget)
editorQWidget.released.connect(partial(self.requestNewPath, indexQModelIndex))
return editorQWidget
else:
return QtGui.QItemDelegate.createEditor(self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex)
def setEditorData (self, editorQWidget, indexQModelIndex):
column = indexQModelIndex.column()
if column == 0:
textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
editorQWidget.setText(textQString)
else:
QtGui.QItemDelegate.setEditorData(self, editorQWidget, indexQModelIndex)
def setModelData (self, editorQWidget, modelQAbstractItemModel, indexQModelIndex):
column = indexQModelIndex.column()
if column == 0:
textQString = editorQWidget.text()
modelQAbstractItemModel.setData(indexQModelIndex, textQString, QtCore.Qt.EditRole)
else:
QtGui.QItemDelegate.setModelData(self, editorQWidget, modelQAbstractItemModel, indexQModelIndex)
def updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex):
column = indexQModelIndex.column()
if column == 0:
editorQWidget.setGeometry(optionQStyleOptionViewItem.rect)
else:
QtGui.QItemDelegate.updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex)
def requestNewPath (self, indexQModelIndex):
self.signalNewPath.emit(indexQModelIndex)
def paint (self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex):
column = indexQModelIndex.column()
if column == 0:
textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
painterQPainter.drawPixmap (
optionQStyleOptionViewItem.rect.x(),
optionQStyleOptionViewItem.rect.y(),
QtGui.QPixmap(textQString).scaled(180, 180, QtCore.Qt.KeepAspectRatio))
else:
QtGui.QItemDelegate.paint(self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex)
class QCustomTreeWidget (QtGui.QTreeWidget):
def __init__(self, parent = None):
super(QCustomTreeWidget, self).__init__(parent)
self.setColumnCount(1)
myQCustomDelegate = QCustomDelegate()
self.setItemDelegate(myQCustomDelegate)
myQCustomDelegate.signalNewPath.connect(self.getNewPath)
def addMenu (self, path, parentQTreeWidgetItem = None):
if parentQTreeWidgetItem == None:
parentQTreeWidgetItem = self.invisibleRootItem()
currentQTreeWidgetItem = QtGui.QTreeWidgetItem(parentQTreeWidgetItem)
currentQTreeWidgetItem.setData(0, QtCore.Qt.EditRole, path)
currentQTreeWidgetItem.setFlags(currentQTreeWidgetItem.flags() | QtCore.Qt.ItemIsEditable)
for i in range(self.columnCount()):
currentQSize = currentQTreeWidgetItem.sizeHint(i)
currentQTreeWidgetItem.setSizeHint(i, QtCore.QSize(currentQSize.width(), currentQSize.height() + 200))
def getNewPath (self, indexQModelIndex):
currentQTreeWidgetItem = self.itemFromIndex(indexQModelIndex)
pathQStringList = QtGui.QFileDialog.getOpenFileNames()
if pathQStringList.count() > 0:
textQString = pathQStringList.first()
currentQTreeWidgetItem.setData(indexQModelIndex.column(), QtCore.Qt.EditRole, textQString)
print textQString
class QCustomQWidget (QtGui.QWidget):
def __init__ (self, parent = None):
super(QCustomQWidget, self).__init__(parent)
self.myQCustomTreeWidget = QCustomTreeWidget(self)
self.allQHBoxLayout = QtGui.QHBoxLayout()
self.allQHBoxLayout.addWidget(self.myQCustomTreeWidget)
self.setLayout(self.allQHBoxLayout)
self.myQCustomTreeWidget.addMenu(r'''C:\Users\Kitsune Meyoko\Desktop\twitter01.jpg''')
self.myQCustomTreeWidget.addMenu(r'''C:\Users\Kitsune Meyoko\Desktop\twitter02.jpg''')
self.myQCustomTreeWidget.addMenu(r'''C:\Users\Kitsune Meyoko\Desktop\twitter04.jpg''')
self.myQCustomTreeWidget.addMenu(r'''C:\Users\Kitsune Meyoko\Desktop\twitter05.jpg''')
app = QtGui.QApplication([])
myQCustomQWidget = QCustomQWidget()
myQCustomQWidget.show()
sys.exit(app.exec_())
Note: In same way to implement QTreeView, but different is set values only.
If your want to show image by path in some index (In this case : 2nd). Your can find it by using QModelIndex QAbstractItemModel.index (self, int row, int column, QModelIndex parent = QModelIndex()), And do want your want.
Example;
import sys
from PyQt4 import QtCore, QtGui
class QCustomDelegate (QtGui.QItemDelegate):
def paint (self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex):
column = indexQModelIndex.column()
if column == 3:
currentQAbstractItemModel = indexQModelIndex.model()
iconQModelIndex = currentQAbstractItemModel.index(indexQModelIndex.row(), 1, indexQModelIndex.parent())
pathQString = currentQAbstractItemModel.data(iconQModelIndex, QtCore.Qt.EditRole).toString()
iconQPixmap = QtGui.QPixmap(pathQString)
if not iconQPixmap.isNull():
painterQPainter.drawPixmap (
optionQStyleOptionViewItem.rect.x(),
optionQStyleOptionViewItem.rect.y(),
iconQPixmap.scaled(20, 20, QtCore.Qt.KeepAspectRatio))
else:
QtGui.QItemDelegate.paint(self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex)
myQApplication = QtGui.QApplication([])
myQTreeView = QtGui.QTreeView()
headerQStandardItemModel = QtGui.QStandardItemModel()
headerQStandardItemModel.setHorizontalHeaderLabels([''] * 4)
myQTreeView.setModel(headerQStandardItemModel)
# Set delegate
myQCustomDelegate = QCustomDelegate()
myQTreeView.setItemDelegate(myQCustomDelegate)
# Append data row 1
row1QStandardItem = QtGui.QStandardItem('ROW 1')
row1QStandardItem.appendRow([QtGui.QStandardItem(''), QtGui.QStandardItem('1.jpg'), QtGui.QStandardItem(''), QtGui.QStandardItem('')])
headerQStandardItemModel.appendRow(row1QStandardItem)
# Append data row 2
row2QStandardItem = QtGui.QStandardItem('ROW 2')
row2QStandardItem.appendRow([QtGui.QStandardItem(''), QtGui.QStandardItem('2.png'), QtGui.QStandardItem(''), QtGui.QStandardItem('')])
headerQStandardItemModel.appendRow(row2QStandardItem)
myQTreeView.show()
sys.exit(myQApplication.exec_())
experimental result:
Note: I have image 1.jpg, 2.png.

Resources