[Common] Rename decode_string to decode_bytes

- Switch to using Python 3 naming convention where str now refers to unicode
   and bytes are encoded strings.
 - Cleanup docs and code
 - Also rename convert_to_utf8 to utf8_encode_structure to clarify functionality.
This commit is contained in:
Calum Lind 2017-02-22 12:53:20 +00:00
commit beb4f8c8f9
14 changed files with 64 additions and 65 deletions

View file

@ -777,36 +777,36 @@ def is_ipv6(ip):
return True return True
else: else:
try: try:
return ipaddress.IPv6Address(decode_string(ip)) return ipaddress.IPv6Address(decode_bytes(ip))
except ipaddress.AddressValueError: except ipaddress.AddressValueError:
pass pass
return False return False
def decode_string(s, encoding='utf8'): def decode_bytes(byte_str, encoding='utf8'):
""" """Decodes a byte string and return unicode.
Decodes a string and return unicode. If it cannot decode using
`:param:encoding` then it will try latin1, and if that fails,
try to detect the string encoding. If that fails, decode with
ignore.
:param s: string to decode If it cannot decode using `encoding` then it will try latin1,
:type s: string and if that fails, try to detect the string encoding. If that fails,
:param encoding: the encoding to use in the decoding decode with ignore.
:type encoding: string
:returns: s converted to unicode Args:
:rtype: unicode byte_str (bytes): The byte string to decode.
encoding (str): The encoding to try first when decoding.
Returns:
str: A unicode string.
""" """
if not s: if not byte_str:
return '' return ''
elif isinstance(s, unicode): elif isinstance(byte_str, unicode):
return s return byte_str
encodings = [lambda: ('utf8', 'strict'), encodings = [lambda: ('utf8', 'strict'),
lambda: ('iso-8859-1', 'strict'), lambda: ('iso-8859-1', 'strict'),
lambda: (chardet.detect(s)['encoding'], 'strict'), lambda: (chardet.detect(byte_str)['encoding'], 'strict'),
lambda: (encoding, 'ignore')] lambda: (encoding, 'ignore')]
if encoding is not 'utf8': if encoding is not 'utf8':
@ -814,7 +814,7 @@ def decode_string(s, encoding='utf8'):
for l in encodings: for l in encodings:
try: try:
return s.decode(*l()) return byte_str.decode(*l())
except UnicodeDecodeError: except UnicodeDecodeError:
pass pass
return '' return ''
@ -833,13 +833,13 @@ def utf8_encoded(s, encoding='utf8'):
""" """
if isinstance(s, str): if isinstance(s, str):
s = decode_string(s, encoding).encode('utf8') s = decode_bytes(s, encoding).encode('utf8')
elif isinstance(s, unicode): elif isinstance(s, unicode):
s = s.encode('utf8') s = s.encode('utf8')
return s return s
def convert_to_utf8(data): def utf8_encode_structure(data):
"""Recursively convert all unicode keys and values in a data structure to utf8. """Recursively convert all unicode keys and values in a data structure to utf8.
e.g. converting keys and values for a dict with nested dicts and lists etc. e.g. converting keys and values for a dict with nested dicts and lists etc.
@ -851,13 +851,12 @@ def convert_to_utf8(data):
input type: The data with unicode keys and values converted to utf8. input type: The data with unicode keys and values converted to utf8.
""" """
if isinstance(data, unicode): if isinstance(data, unicode):
return data.encode('utf8') return data.encode('utf8')
elif isinstance(data, (list, tuple)): elif isinstance(data, (list, tuple)):
return type(data)(map(convert_to_utf8, data)) return type(data)(map(utf8_encode_structure, data))
elif isinstance(data, dict): elif isinstance(data, dict):
return dict(map(convert_to_utf8, data.items())) return dict(map(utf8_encode_structure, data.items()))
else: else:
return data return data

View file

@ -47,7 +47,7 @@ import logging
import os import os
import shutil import shutil
from deluge.common import decode_string, get_default_config_dir, utf8_encoded from deluge.common import decode_bytes, get_default_config_dir, utf8_encoded
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
callLater = None # Necessary for the config tests callLater = None # Necessary for the config tests
@ -245,7 +245,7 @@ class Config(object):
""" """
if isinstance(self.__config[key], basestring): if isinstance(self.__config[key], basestring):
return decode_string(self.__config[key]) return decode_bytes(self.__config[key])
else: else:
return self.__config[key] return self.__config[key]

View file

@ -23,7 +23,7 @@ from twisted.internet import reactor
import deluge.component as component import deluge.component as component
from deluge._libtorrent import lt from deluge._libtorrent import lt
from deluge.common import decode_string from deluge.common import decode_bytes
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -112,7 +112,7 @@ class AlertManager(component.Component):
alert_type = type(alert).__name__ alert_type = type(alert).__name__
# Display the alert message # Display the alert message
if log.isEnabledFor(logging.DEBUG): if log.isEnabledFor(logging.DEBUG):
log.debug('%s: %s', alert_type, decode_string(alert.message())) log.debug('%s: %s', alert_type, decode_bytes(alert.message()))
# Call any handlers for this alert type # Call any handlers for this alert type
if alert_type in self.handlers: if alert_type in self.handlers:
for handler in self.handlers[alert_type]: for handler in self.handlers[alert_type]:

View file

@ -26,7 +26,7 @@ from twisted.internet.defer import Deferred, DeferredList
import deluge.component as component import deluge.component as component
from deluge._libtorrent import lt from deluge._libtorrent import lt
from deluge.common import decode_string, utf8_encoded from deluge.common import decode_bytes, utf8_encoded
from deluge.configmanager import ConfigManager, get_config_dir from deluge.configmanager import ConfigManager, get_config_dir
from deluge.core.authmanager import AUTH_LEVEL_ADMIN from deluge.core.authmanager import AUTH_LEVEL_ADMIN
from deluge.decorators import deprecated from deluge.decorators import deprecated
@ -612,7 +612,7 @@ class Torrent(object):
self.state = 'Error' self.state = 'Error'
# auto-manage status will be reverted upon resuming. # auto-manage status will be reverted upon resuming.
self.handle.auto_managed(False) self.handle.auto_managed(False)
self.set_status_message(decode_string(status_error)) self.set_status_message(decode_bytes(status_error))
elif status.moving_storage: elif status.moving_storage:
self.state = 'Moving' self.state = 'Moving'
elif not session_paused and status.paused and status.auto_managed: elif not session_paused and status.paused and status.auto_managed:
@ -761,7 +761,7 @@ class Torrent(object):
if peer.flags & peer.connecting or peer.flags & peer.handshake: if peer.flags & peer.connecting or peer.flags & peer.handshake:
continue continue
client = decode_string(peer.client) client = decode_bytes(peer.client)
try: try:
country = component.get('Core').geoip_instance.country_code_by_addr(peer.ip[0]) country = component.get('Core').geoip_instance.country_code_by_addr(peer.ip[0])
@ -868,7 +868,7 @@ class Torrent(object):
if not self.options['name']: if not self.options['name']:
handle_name = self.handle.name() handle_name = self.handle.name()
if handle_name: if handle_name:
name = decode_string(handle_name) name = decode_bytes(handle_name)
else: else:
name = self.torrent_id name = self.torrent_id
else: else:
@ -1013,7 +1013,7 @@ class Torrent(object):
'trackers': lambda: self.trackers, 'trackers': lambda: self.trackers,
'tracker_status': lambda: self.tracker_status, 'tracker_status': lambda: self.tracker_status,
'upload_payload_rate': lambda: self.status.upload_payload_rate, 'upload_payload_rate': lambda: self.status.upload_payload_rate,
'comment': lambda: decode_string(self.torrent_info.comment()) if self.has_metadata else '', 'comment': lambda: decode_bytes(self.torrent_info.comment()) if self.has_metadata else '',
'num_files': lambda: self.torrent_info.num_files() if self.has_metadata else 0, 'num_files': lambda: self.torrent_info.num_files() if self.has_metadata else 0,
'num_pieces': lambda: self.torrent_info.num_pieces() if self.has_metadata else 0, 'num_pieces': lambda: self.torrent_info.num_pieces() if self.has_metadata else 0,
'piece_length': lambda: self.torrent_info.piece_length() if self.has_metadata else 0, 'piece_length': lambda: self.torrent_info.piece_length() if self.has_metadata else 0,
@ -1114,7 +1114,7 @@ class Torrent(object):
bool: True if successful, otherwise False bool: True if successful, otherwise False
""" """
dest = decode_string(dest) dest = decode_bytes(dest)
if not os.path.exists(dest): if not os.path.exists(dest):
try: try:
@ -1253,7 +1253,7 @@ class Torrent(object):
""" """
for index, filename in filenames: for index, filename in filenames:
# Make sure filename is a unicode object # Make sure filename is a unicode object
filename = sanitize_filepath(decode_string(filename)) filename = sanitize_filepath(decode_bytes(filename))
# libtorrent needs unicode object if wstrings are enabled, utf8 bytestring otherwise # libtorrent needs unicode object if wstrings are enabled, utf8 bytestring otherwise
try: try:
self.handle.rename_file(index, filename) self.handle.rename_file(index, filename)

View file

@ -24,7 +24,7 @@ from twisted.internet.task import LoopingCall
import deluge.component as component import deluge.component as component
from deluge._libtorrent import lt from deluge._libtorrent import lt
from deluge.common import decode_string, get_magnet_info, utf8_encoded from deluge.common import decode_bytes, get_magnet_info, utf8_encoded
from deluge.configmanager import ConfigManager, get_config_dir from deluge.configmanager import ConfigManager, get_config_dir
from deluge.core.authmanager import AUTH_LEVEL_ADMIN from deluge.core.authmanager import AUTH_LEVEL_ADMIN
from deluge.core.torrent import Torrent, TorrentOptions, sanitize_filepath from deluge.core.torrent import Torrent, TorrentOptions, sanitize_filepath
@ -358,7 +358,7 @@ class TorrentManager(component.Component):
# Check for renamed files and if so, rename them in the torrent_info before adding. # Check for renamed files and if so, rename them in the torrent_info before adding.
if options['mapped_files'] and torrent_info: if options['mapped_files'] and torrent_info:
for index, fname in options['mapped_files'].items(): for index, fname in options['mapped_files'].items():
fname = sanitize_filepath(decode_string(fname)) fname = sanitize_filepath(decode_bytes(fname))
if log.isEnabledFor(logging.DEBUG): if log.isEnabledFor(logging.DEBUG):
log.debug('renaming file index %s to %s', index, fname) log.debug('renaming file index %s to %s', index, fname)
try: try:
@ -1045,7 +1045,7 @@ class TorrentManager(component.Component):
except (RuntimeError, KeyError): except (RuntimeError, KeyError):
return return
# Set the tracker status for the torrent # Set the tracker status for the torrent
torrent.set_tracker_status('Warning: %s' % decode_string(alert.message())) torrent.set_tracker_status('Warning: %s' % decode_bytes(alert.message()))
def on_alert_tracker_error(self, alert): def on_alert_tracker_error(self, alert):
"""Alert handler for libtorrent tracker_error_alert""" """Alert handler for libtorrent tracker_error_alert"""
@ -1054,10 +1054,10 @@ class TorrentManager(component.Component):
except (RuntimeError, KeyError): except (RuntimeError, KeyError):
return return
error_message = decode_string(alert.error_message()) error_message = decode_bytes(alert.error_message())
if not error_message: if not error_message:
error_message = alert.error.message() error_message = alert.error.message()
log.debug('Tracker Error Alert: %s [%s]', decode_string(alert.message()), error_message) log.debug('Tracker Error Alert: %s [%s]', decode_bytes(alert.message()), error_message)
torrent.set_tracker_status('Error: ' + error_message) torrent.set_tracker_status('Error: ' + error_message)
def on_alert_storage_moved(self, alert): def on_alert_storage_moved(self, alert):
@ -1085,9 +1085,9 @@ class TorrentManager(component.Component):
except (RuntimeError, KeyError): except (RuntimeError, KeyError):
return return
log.warning('on_alert_storage_moved_failed: %s', decode_string(alert.message())) log.warning('on_alert_storage_moved_failed: %s', decode_bytes(alert.message()))
# Set an Error message and pause the torrent # Set an Error message and pause the torrent
alert_msg = decode_string(alert.message()).split(':', 1)[1].strip() alert_msg = decode_bytes(alert.message()).split(':', 1)[1].strip()
torrent.force_error_state('Failed to move download folder: %s' % alert_msg) torrent.force_error_state('Failed to move download folder: %s' % alert_msg)
if torrent_id in self.waiting_on_finish_moving: if torrent_id in self.waiting_on_finish_moving:
@ -1145,7 +1145,7 @@ class TorrentManager(component.Component):
return return
if torrent_id in self.waiting_on_resume_data: if torrent_id in self.waiting_on_resume_data:
self.waiting_on_resume_data[torrent_id].errback(Exception(decode_string(alert.message()))) self.waiting_on_resume_data[torrent_id].errback(Exception(decode_bytes(alert.message())))
def on_alert_fastresume_rejected(self, alert): def on_alert_fastresume_rejected(self, alert):
"""Alert handler for libtorrent fastresume_rejected_alert""" """Alert handler for libtorrent fastresume_rejected_alert"""
@ -1155,7 +1155,7 @@ class TorrentManager(component.Component):
except (RuntimeError, KeyError): except (RuntimeError, KeyError):
return return
alert_msg = decode_string(alert.message()) alert_msg = decode_bytes(alert.message())
log.error('on_alert_fastresume_rejected: %s', alert_msg) log.error('on_alert_fastresume_rejected: %s', alert_msg)
if alert.error.value() == 134: if alert.error.value() == 134:
if not os.path.isdir(torrent.options['download_location']): if not os.path.isdir(torrent.options['download_location']):
@ -1179,7 +1179,7 @@ class TorrentManager(component.Component):
except (RuntimeError, KeyError): except (RuntimeError, KeyError):
return return
new_name = decode_string(alert.new_name) new_name = decode_bytes(alert.new_name)
log.debug('index: %s name: %s', alert.index, new_name) log.debug('index: %s name: %s', alert.index, new_name)
# We need to see if this file index is in a waiting_on_folder dict # We need to see if this file index is in a waiting_on_folder dict
@ -1251,13 +1251,13 @@ class TorrentManager(component.Component):
'external IP received: 0:0:0:0:0:0:0:0' 'external IP received: 0:0:0:0:0:0:0:0'
""" """
external_ip = decode_string(alert.message()).split(' ')[-1] external_ip = decode_bytes(alert.message()).split(' ')[-1]
log.info('on_alert_external_ip: %s', external_ip) log.info('on_alert_external_ip: %s', external_ip)
component.get('EventManager').emit(ExternalIPEvent(external_ip)) component.get('EventManager').emit(ExternalIPEvent(external_ip))
def on_alert_performance(self, alert): def on_alert_performance(self, alert):
"""Alert handler for libtorrent performance_alert""" """Alert handler for libtorrent performance_alert"""
log.warning('on_alert_performance: %s, %s', decode_string(alert.message()), alert.warning_code) log.warning('on_alert_performance: %s, %s', decode_bytes(alert.message()), alert.warning_code)
if alert.warning_code == lt.performance_warning_t.send_buffer_watermark_too_low: if alert.warning_code == lt.performance_warning_t.send_buffer_watermark_too_low:
max_send_buffer_watermark = 3 * 1024 * 1024 # 3MiB max_send_buffer_watermark = 3 * 1024 * 1024 # 3MiB
settings = self.session.get_settings() settings = self.session.get_settings()

View file

@ -19,7 +19,7 @@ from twisted.python.failure import Failure
from twisted.web import client, http from twisted.web import client, http
from twisted.web.error import PageRedirect from twisted.web.error import PageRedirect
from deluge.common import convert_to_utf8, get_version from deluge.common import get_version, utf8_encode_structure
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -175,7 +175,7 @@ def _download_file(url, filename, callback=None, headers=None, force_filename=Fa
url = url.encode('utf8') url = url.encode('utf8')
filename = filename.encode('utf8') filename = filename.encode('utf8')
headers = convert_to_utf8(headers) if headers else headers headers = utf8_encode_structure(headers) if headers else headers
factory = HTTPDownloader(url, filename, callback, headers, force_filename, allow_compression) factory = HTTPDownloader(url, filename, callback, headers, force_filename, allow_compression)
# In Twisted 13.1.0 _parse() function replaced by _URI class. # In Twisted 13.1.0 _parse() function replaced by _URI class.

View file

@ -14,7 +14,7 @@ import sys
from hashlib import sha1 as sha from hashlib import sha1 as sha
from deluge.bencode import bencode from deluge.bencode import bencode
from deluge.common import convert_to_utf8, get_path_size from deluge.common import get_path_size, utf8_encode_structure
class InvalidPath(Exception): class InvalidPath(Exception):
@ -194,7 +194,7 @@ class TorrentMetadata(object):
# Write out the torrent file # Write out the torrent file
with open(torrent_path, 'wb') as _file: with open(torrent_path, 'wb') as _file:
_file.write(bencode(convert_to_utf8(torrent))) _file.write(bencode(utf8_encode_structure(torrent)))
def get_data_path(self): def get_data_path(self):
"""Get the path to the files that the torrent will contain. """Get the path to the files that the torrent will contain.

View file

@ -18,7 +18,7 @@ import deluge.component as component
import deluge.core.torrent import deluge.core.torrent
import deluge.tests.common as common import deluge.tests.common as common
from deluge._libtorrent import lt from deluge._libtorrent import lt
from deluge.common import convert_to_utf8 from deluge.common import utf8_encode_structure
from deluge.core.core import Core from deluge.core.core import Core
from deluge.core.rpcserver import RPCServer from deluge.core.rpcserver import RPCServer
from deluge.core.torrent import Torrent from deluge.core.torrent import Torrent
@ -180,7 +180,7 @@ class TorrentTestCase(BaseTestCase):
filename = common.get_test_data_file('test_torrent.file.torrent') filename = common.get_test_data_file('test_torrent.file.torrent')
with open(filename) as _file: with open(filename) as _file:
filedump = _file.read() filedump = _file.read()
resume_data = convert_to_utf8(resume_data) resume_data = utf8_encode_structure(resume_data)
torrent_id = yield self.core.torrentmanager.add(state=torrent_state, filedump=filedump, torrent_id = yield self.core.torrentmanager.add(state=torrent_state, filedump=filedump,
resume_data=lt.bencode(resume_data)) resume_data=lt.bencode(resume_data))
torrent = self.core.torrentmanager.torrents[torrent_id] torrent = self.core.torrentmanager.torrents[torrent_id]

View file

@ -24,7 +24,7 @@ import deluge.ui.console
import deluge.ui.console.cmdline.commands.quit import deluge.ui.console.cmdline.commands.quit
import deluge.ui.console.main import deluge.ui.console.main
import deluge.ui.web.server import deluge.ui.web.server
from deluge.common import convert_to_utf8 from deluge.common import utf8_encode_structure
from deluge.ui import ui_entry from deluge.ui import ui_entry
from deluge.ui.web.server import DelugeWeb from deluge.ui.web.server import DelugeWeb
@ -168,7 +168,7 @@ class GtkUIDelugeScriptEntryTestCase(BaseTestCase, GtkUIBaseTestCase):
self.var['cmd_name'] = 'deluge gtk' self.var['cmd_name'] = 'deluge gtk'
self.var['start_cmd'] = ui_entry.start_ui self.var['start_cmd'] = ui_entry.start_ui
self.var['sys_arg_cmd'] = convert_to_utf8(['./deluge', 'gtk']) self.var['sys_arg_cmd'] = utf8_encode_structure(['./deluge', 'gtk'])
def set_up(self): def set_up(self):
return GtkUIBaseTestCase.set_up(self) return GtkUIBaseTestCase.set_up(self)

View file

@ -18,7 +18,7 @@ from twisted.trial.unittest import SkipTest
from twisted.web.client import Agent, FileBodyProducer from twisted.web.client import Agent, FileBodyProducer
from twisted.web.http_headers import Headers from twisted.web.http_headers import Headers
from deluge.common import convert_to_utf8 from deluge.common import utf8_encode_structure
from . import common from . import common
from .common import get_test_data_file from .common import get_test_data_file
@ -46,7 +46,7 @@ class WebServerTestCase(WebServerTestBase, WebServerMockBase):
'Content-Type': ['application/json']} 'Content-Type': ['application/json']}
url = 'http://127.0.0.1:%s/json' % self.webserver_listen_port url = 'http://127.0.0.1:%s/json' % self.webserver_listen_port
d = yield agent.request(b'POST', url.encode('utf-8'), Headers(convert_to_utf8(headers)), d = yield agent.request(b'POST', url.encode('utf-8'), Headers(utf8_encode_structure(headers)),
FileBodyProducer(StringIO(input_file.encode('utf-8')))) FileBodyProducer(StringIO(input_file.encode('utf-8'))))
try: try:
body = yield twisted.web.client.readBody(d) body = yield twisted.web.client.readBody(d)

View file

@ -20,7 +20,7 @@ from hashlib import sha1 as sha
import deluge.configmanager import deluge.configmanager
from deluge import bencode from deluge import bencode
from deluge.common import decode_string from deluge.common import decode_bytes
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -166,9 +166,9 @@ class TorrentInfo(object):
# Check if 'name.utf-8' is in the torrent and if not try to decode the string # Check if 'name.utf-8' is in the torrent and if not try to decode the string
# using the encoding found. # using the encoding found.
if 'name.utf-8' in self.__m_metadata['info']: if 'name.utf-8' in self.__m_metadata['info']:
self.__m_name = decode_string(self.__m_metadata['info']['name.utf-8']) self.__m_name = decode_bytes(self.__m_metadata['info']['name.utf-8'])
else: else:
self.__m_name = decode_string(self.__m_metadata['info']['name'], self.encoding) self.__m_name = decode_bytes(self.__m_metadata['info']['name'], self.encoding)
# Get list of files from torrent info # Get list of files from torrent info
paths = {} paths = {}
@ -180,10 +180,10 @@ class TorrentInfo(object):
for index, f in enumerate(self.__m_metadata['info']['files']): for index, f in enumerate(self.__m_metadata['info']['files']):
if 'path.utf-8' in f: if 'path.utf-8' in f:
path = decode_string(os.path.join(prefix, *f['path.utf-8'])) path = decode_bytes(os.path.join(prefix, *f['path.utf-8']))
del f['path.utf-8'] del f['path.utf-8']
else: else:
path = os.path.join(prefix, decode_string(os.path.join(*f['path']), self.encoding)) path = os.path.join(prefix, decode_bytes(os.path.join(*f['path']), self.encoding))
f['path'] = path f['path'] = path
f['index'] = index f['index'] = index
if 'sha1' in f and len(f['sha1']) == 20: if 'sha1' in f and len(f['sha1']) == 20:

View file

@ -181,7 +181,7 @@ class AddTorrents(BaseMode):
self.formatted_rows = [] self.formatted_rows = []
for row in self.raw_rows: for row in self.raw_rows:
filename = deluge.common.decode_string(row[0]) filename = deluge.common.decode_bytes(row[0])
size = row[1] size = row[1]
time = row[2] time = row[2]

View file

@ -23,7 +23,7 @@ from twisted.internet import reactor
from twisted.internet.protocol import ClientFactory, Factory, Protocol, connectionDone from twisted.internet.protocol import ClientFactory, Factory, Protocol, connectionDone
import deluge.component as component import deluge.component as component
from deluge.common import decode_string, is_magnet, is_url, windows_check from deluge.common import decode_bytes, is_magnet, is_url, windows_check
from deluge.configmanager import ConfigManager, get_config_dir from deluge.configmanager import ConfigManager, get_config_dir
from deluge.ui.client import client from deluge.ui.client import client
@ -206,7 +206,7 @@ def process_args(args):
log.debug('Attempting to add file (%s) from external source...', arg) log.debug('Attempting to add file (%s) from external source...', arg)
if urlparse(arg).scheme == 'file': if urlparse(arg).scheme == 'file':
arg = url2pathname(urlparse(arg).path) arg = url2pathname(urlparse(arg).path)
path = os.path.abspath(decode_string(arg)) path = os.path.abspath(decode_bytes(arg))
if not os.path.exists(path): if not os.path.exists(path):
log.error('No such file: %s', path) log.error('No such file: %s', path)

View file

@ -910,7 +910,7 @@ class Preferences(component.Component):
response = chooser.run() response = chooser.run()
if response == gtk.RESPONSE_OK: if response == gtk.RESPONSE_OK:
filepath = deluge.common.decode_string(chooser.get_filename()) filepath = deluge.common.decode_bytes(chooser.get_filename())
else: else:
chooser.destroy() chooser.destroy()
return return