jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/354454 )
Change subject: flake8: Fix C408 errors
......................................................................
flake8: Fix C408 errors
Bug: T165701
Change-Id: Iaa142d4c947a86a7dd158aa3d6ce91265b48b7fb
---
M pywikibot/data/api.py
M pywikibot/page.py
M pywikibot/pagegenerators.py
M pywikibot/site.py
M pywikibot/textlib.py
M pywikibot/tools/formatter.py
M pywikibot/userinterfaces/gui.py
M pywikibot/version.py
M scripts/archive/featured.py
M scripts/blockpageschecker.py
M scripts/checkimages.py
M scripts/claimit.py
M scripts/harvest_template.py
M scripts/imagetransfer.py
M scripts/patrol.py
M scripts/standardize_interwiki.py
M scripts/welcome.py
M tests/family_tests.py
M tests/pagegenerators_tests.py
M tests/tools_tests.py
M tests/ui_tests.py
M tests/wikibase_edit_tests.py
22 files changed, 117 insertions(+), 137 deletions(-)
Approvals:
Mpaa: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/data/api.py b/pywikibot/data/api.py
index 4f362af..e704023 100644
--- a/pywikibot/data/api.py
+++ b/pywikibot/data/api.py
@@ -3030,9 +3030,11 @@
# base login request
login_request = self.site._request(
use_get=False,
- parameters=dict(action='login',
- lgname=self.login_name,
- lgpassword=self.password))
+ parameters={
+ 'action': 'login',
+ 'lgname': self.login_name,
+ 'lgpassword': self.password,
+ })
if self.site.family.ldapDomain:
login_request['lgdomain'] = self.site.family.ldapDomain
@@ -3078,9 +3080,8 @@
'at least MediaWiki version 1.27.')
login_token_request = self.site._request(
use_get=False,
- parameters=dict(action='query',
- meta='tokens',
- type='login'))
+ parameters={'action': 'query', 'meta':
'tokens', 'type': 'login'},
+ )
login_token_result = login_token_request.submit()
return
login_token_result['query']['tokens'].get('logintoken')
diff --git a/pywikibot/page.py b/pywikibot/page.py
index cb4a17a..8e4a40f 100644
--- a/pywikibot/page.py
+++ b/pywikibot/page.py
@@ -3686,7 +3686,7 @@
self.aliases = {}
if 'aliases' in self._content:
for lang in self._content['aliases']:
- self.aliases[lang] = list()
+ self.aliases[lang] = []
for value in self._content['aliases'][lang]:
self.aliases[lang].append(value['value'])
@@ -4267,7 +4267,7 @@
Sites should be a list, with values either
being Site objects, or dbNames.
"""
- data = list()
+ data = []
for site in sites:
site = self.getdbName(site)
data.append({'site': site, 'title': ''})
diff --git a/pywikibot/pagegenerators.py b/pywikibot/pagegenerators.py
index 5af0619..96f2100 100644
--- a/pywikibot/pagegenerators.py
+++ b/pywikibot/pagegenerators.py
@@ -1287,8 +1287,10 @@
retrieved page will be downloaded.
"""
- kwargs = dict(recurse=recurse, total=total,
- content=content, namespaces=namespaces)
+ kwargs = {
+ 'recurse': recurse, 'total': total,
+ 'content': content, 'namespaces': namespaces,
+ }
if start:
kwargs['sortby'] = 'sortkey'
kwargs['startsort'] = start
@@ -2778,7 +2780,7 @@
if site is None:
site = pywikibot.Site()
repo = site.data_repository()
- dependencies = dict(endpoint=endpoint, entity_url=entity_url)
+ dependencies = {'endpoint': endpoint, 'entity_url': entity_url}
if not endpoint or not entity_url:
dependencies['repo'] = repo
query_object = sparql.SparqlQuery(**dependencies)
diff --git a/pywikibot/site.py b/pywikibot/site.py
index 0b15cb9..34a774a 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -226,7 +226,7 @@
self.id = id
if aliases is None:
- self.aliases = list()
+ self.aliases = []
else:
self.aliases = aliases
@@ -258,7 +258,7 @@
alias += u' talk'
self.aliases = [alias]
else:
- self.aliases = list()
+ self.aliases = []
else:
self.aliases = aliases
@@ -1540,11 +1540,9 @@
request = self._site._request(
expiry=pywikibot.config.API_config_expiry
if expiry is False else expiry,
- parameters=dict(
- action='query',
- meta='siteinfo',
- siprop=props
- )
+ parameters={
+ 'action': 'query', 'meta':
'siteinfo', 'siprop': props,
+ }
)
# With 1.25wmf5 it'll require continue or rawcontinue. As we don't
# continue anyway we just always use continue.
@@ -2312,9 +2310,12 @@
@need_extension('Echo')
def notifications(self, **kwargs):
"""Yield Notification objects from the Echo
extension."""
- params = dict(action='query',
- meta='notifications',
- notprop='list', notformat='text')
+ params = {
+ 'action': 'query',
+ 'meta': 'notifications',
+ 'notprop': 'list',
+ 'notformat': 'text',
+ }
for key in kwargs:
params['not' + key] = kwargs[key]
@@ -2869,11 +2870,8 @@
pirequest = self._request(
expiry=pywikibot.config.API_config_expiry
if expiry is False else expiry,
- parameters=dict(
- action='query',
- meta='proofreadinfo',
- piprop='namespaces|qualitylevels'
- )
+ parameters={'action': 'query', 'meta':
'proofreadinfo',
+ 'piprop': 'namespaces|qualitylevels'}
)
pidata = pirequest.submit()
@@ -3776,9 +3774,8 @@
u"categorymembers: non-Category page '%s' specified"
% category.title())
cmtitle = category.title(withSection=False).encode(self.encoding())
- cmargs = dict(type_arg="categorymembers",
- gcmtitle=cmtitle,
- gcmprop="ids|title|sortkey")
+ cmargs = {'type_arg': "categorymembers", 'gcmtitle':
cmtitle,
+ 'gcmprop': "ids|title|sortkey"}
if sortby in ["sortkey", "timestamp"]:
cmargs["gcmsort"] = sortby
elif sortby:
@@ -4416,7 +4413,7 @@
@raises TypeError: a namespace identifier has an inappropriate
type such as NoneType or bool
"""
- iuargs = dict(giutitle=image.title(withSection=False))
+ iuargs = {'giutitle': image.title(withSection=False)}
if filterredir is not None:
iuargs['giufilterredir'] = ('redirects' if filterredir else
'nonredirects')
@@ -7400,11 +7397,8 @@
This is used specifically because we can cache
the value for a much longer time (near infinite).
"""
- params = dict(
- action='wbgetentities',
- ids=prop.getID(),
- props='datatype',
- )
+ params = {'action': 'wbgetentities', 'ids':
prop.getID(),
+ 'props': 'datatype'}
expiry = datetime.timedelta(days=365 * 100)
# Store it for 100 years
req = self._request(expiry=expiry, parameters=params)
@@ -7471,14 +7465,10 @@
@param summary: Edit summary
@type summary: str
"""
- params = dict(action='wbcreateclaim',
- entity=item.getID(),
- baserevid=item.latest_revision_id,
- snaktype=claim.getSnakType(),
- property=claim.getID(),
- summary=summary,
- bot=bot,
- )
+ params = {'action': 'wbcreateclaim', 'entity':
item.getID(),
+ 'baserevid': item.latest_revision_id,
+ 'snaktype': claim.getSnakType(), 'property':
claim.getID(),
+ 'summary': summary, 'bot': bot}
if claim.getSnakType() == 'value':
params['value'] = json.dumps(claim._formatValue())
@@ -7514,14 +7504,10 @@
if not claim.snak:
# We need to already have the snak value
raise NoPage(claim)
- params = dict(action='wbsetclaimvalue',
- claim=claim.snak,
- snaktype=snaktype,
- summary=summary,
- bot=bot,
- )
+ params = {'action': 'wbsetclaimvalue', 'claim':
claim.snak,
+ 'snaktype': snaktype, 'summary': summary,
'bot': bot,
+ 'token': self.tokens['edit']}
- params['token'] = self.tokens['edit']
if snaktype == 'value':
params['value'] = json.dumps(claim._formatValue())
@@ -7582,14 +7568,10 @@
"""
if claim.isReference or claim.isQualifier:
raise ValueError("The claim cannot have a source.")
- params = dict(action='wbsetreference',
- statement=claim.snak,
- baserevid=self._get_baserevid(claim, baserevid),
- summary=summary,
- bot=bot,
- )
+ params = {'action': 'wbsetreference', 'statement':
claim.snak,
+ 'baserevid': self._get_baserevid(claim, baserevid),
+ 'summary': summary, 'bot': bot, 'token':
self.tokens['edit']}
- params['token'] = self.tokens['edit']
# build up the snak
if isinstance(source, list):
sources = source
@@ -7639,12 +7621,9 @@
"""
if claim.isReference or claim.isQualifier:
raise ValueError("The claim cannot have a qualifier.")
- params = dict(action='wbsetqualifier',
- claim=claim.snak,
- baserevid=self._get_baserevid(claim, baserevid),
- summary=summary,
- bot=bot,
- )
+ params = {'action': 'wbsetqualifier', 'claim':
claim.snak,
+ 'baserevid': self._get_baserevid(claim, baserevid),
+ 'summary': summary, 'bot': bot}
if (not new and
hasattr(qualifier, 'hash') and
@@ -7683,14 +7662,13 @@
items = set(claim.on_item for claim in claims if claim.on_item)
assert len(items) == 1
- params = dict(action='wbremoveclaims',
- baserevid=baserevid,
- summary=summary,
- bot=bot,
- )
-
- params['claim'] = '|'.join(claim.snak for claim in claims)
- params['token'] = self.tokens['edit']
+ params = {
+ 'action': 'wbremoveclaims', 'baserevid': baserevid,
+ 'summary': summary,
+ 'bot': bot,
+ 'claim': '|'.join(claim.snak for claim in claims),
+ 'token': self.tokens['edit'],
+ }
req = self._simple_request(**params)
data = req.submit()
@@ -7714,15 +7692,14 @@
When omitted, revision of claim.on_item is used. DEPRECATED.
@type baserevid: long
"""
- params = dict(action='wbremovereferences',
- baserevid=self._get_baserevid(claim, baserevid),
- summary=summary,
- bot=bot,
- )
-
- params['statement'] = claim.snak
- params['references'] = '|'.join(source.hash for source in
sources)
- params['token'] = self.tokens['edit']
+ params = {
+ 'action': 'wbremovereferences',
+ 'baserevid': self._get_baserevid(claim, baserevid),
+ 'summary': summary, 'bot': bot,
+ 'statement': claim.snak,
+ 'references': '|'.join(source.hash for source in sources),
+ 'token': self.tokens['edit'],
+ }
req = self._simple_request(**params)
data = req.submit()
@@ -7746,15 +7723,15 @@
When omitted, revision of claim.on_item is used. DEPRECATED.
@type baserevid: long
"""
- params = dict(action='wbremovequalifiers',
- claim=claim.snak,
- baserevid=self._get_baserevid(claim, baserevid),
- summary=summary,
- bot=bot,
- )
-
- params['qualifiers'] = [qualifier.hash for qualifier in qualifiers]
- params['token'] = self.tokens['edit']
+ params = {
+ 'action': 'wbremovequalifiers',
+ 'claim': claim.snak,
+ 'baserevid': self._get_baserevid(claim, baserevid),
+ 'summary': summary,
+ 'bot': bot,
+ 'qualifiers': [qualifier.hash for qualifier in qualifiers],
+ 'token': self.tokens['edit']
+ }
req = self._simple_request(**params)
data = req.submit()
diff --git a/pywikibot/textlib.py b/pywikibot/textlib.py
index 850db61..ebb72a9 100644
--- a/pywikibot/textlib.py
+++ b/pywikibot/textlib.py
@@ -2042,7 +2042,7 @@
return '_' * (match.end() - match.start())
# match date fields
- dateDict = dict()
+ dateDict = {}
# Analyze comments separately from rest of each line to avoid to skip
# dates in comments, as the date matched by timestripper is the
diff --git a/pywikibot/tools/formatter.py b/pywikibot/tools/formatter.py
index 6c95058..94a4d95 100644
--- a/pywikibot/tools/formatter.py
+++ b/pywikibot/tools/formatter.py
@@ -130,7 +130,7 @@
additional_params = result[1:]
result = result[0]
else:
- additional_params = tuple()
+ additional_params = ()
result = self._convert_bytes(result)
if additional_params:
result = (result, ) + additional_params
diff --git a/pywikibot/userinterfaces/gui.py b/pywikibot/userinterfaces/gui.py
index 27bc8cc..1cfe2df 100644
--- a/pywikibot/userinterfaces/gui.py
+++ b/pywikibot/userinterfaces/gui.py
@@ -55,23 +55,23 @@
Get default settings from user's IDLE configuration.
"""
currentTheme = idleConf.CurrentTheme()
- textcf = dict(padx=5, wrap='word', undo='True',
- foreground=idleConf.GetHighlight(currentTheme,
- 'normal',
fgBg='fg'),
- background=idleConf.GetHighlight(currentTheme,
- 'normal',
fgBg='bg'),
- highlightcolor=idleConf.GetHighlight(currentTheme,
- 'hilite',
fgBg='fg'),
- highlightbackground=idleConf.GetHighlight(currentTheme,
- 'hilite',
- fgBg='bg'),
- insertbackground=idleConf.GetHighlight(currentTheme,
- 'cursor',
- fgBg='fg'),
- width=idleConf.GetOption('main', 'EditorWindow',
'width'),
- height=idleConf.GetOption('main', 'EditorWindow',
- 'height')
- )
+ textcf = {
+ 'padx': 5,
+ 'wrap': 'word',
+ 'undo': 'True',
+ 'foreground': idleConf.GetHighlight(
+ currentTheme, 'normal', fgBg='fg'),
+ 'background': idleConf.GetHighlight(
+ currentTheme, 'normal', fgBg='bg'),
+ 'highlightcolor': idleConf.GetHighlight(
+ currentTheme, 'hilite', fgBg='fg'),
+ 'highlightbackground': idleConf.GetHighlight(
+ currentTheme, 'hilite', fgBg='bg'),
+ 'insertbackground': idleConf.GetHighlight(
+ currentTheme, 'cursor', fgBg='fg'),
+ 'width': idleConf.GetOption('main', 'EditorWindow',
'width'),
+ 'height': idleConf.GetOption('main', 'EditorWindow',
'height'),
+ }
fontWeight = 'normal'
if idleConf.GetOption('main', 'EditorWindow',
'font-bold', type='bool'):
fontWeight = 'bold'
diff --git a/pywikibot/version.py b/pywikibot/version.py
index 3025532..c48db41 100644
--- a/pywikibot/version.py
+++ b/pywikibot/version.py
@@ -126,7 +126,7 @@
warn('Unable to detect package date', UserWarning)
datestring = '-2 (unknown)'
- cache = dict(tag=tag, rev=rev, date=datestring, hsh=hsh)
+ cache = {'tag': tag, 'rev': rev, 'date': datestring,
'hsh': hsh}
return cache
diff --git a/scripts/archive/featured.py b/scripts/archive/featured.py
index a6a661f..5ae04e1 100755
--- a/scripts/archive/featured.py
+++ b/scripts/archive/featured.py
@@ -232,14 +232,14 @@
'fromlang': None,
'good': False,
'lists': False,
- 'nocache': list(),
+ 'nocache': [],
'side': False, # not template_on_top
'quiet': False,
'interactive': False,
})
super(FeaturedBot, self).__init__(**kwargs)
- self.cache = dict()
+ self.cache = {}
self.filename = None
self.site = pywikibot.Site()
self.repo = self.site.data_repository()
@@ -335,7 +335,7 @@
% (len(self.cache), self.filename))
with open(self.filename, "wb") as f:
pickle.dump(self.cache, f, protocol=config.pickle_protocol)
- self.cache = dict()
+ self.cache = {}
def run(self):
for task in self.tasks:
diff --git a/scripts/blockpageschecker.py b/scripts/blockpageschecker.py
index 5fe9446..91af606 100755
--- a/scripts/blockpageschecker.py
+++ b/scripts/blockpageschecker.py
@@ -273,7 +273,7 @@
if not generator:
generator = genFactory.getCombinedGenerator()
if not generator:
- generator = list()
+ generator = []
pywikibot.output(u'Loading categories...')
# Define the category if no other generator has been setted
for CAT in categories:
diff --git a/scripts/checkimages.py b/scripts/checkimages.py
index 83e421a..ecdebda 100755
--- a/scripts/checkimages.py
+++ b/scripts/checkimages.py
@@ -1126,7 +1126,7 @@
self.settingsData = None
else:
wikiPage = pywikibot.Page(self.site, settingsPage)
- self.settingsData = list()
+ self.settingsData = []
try:
testo = wikiPage.get()
number = 1
diff --git a/scripts/claimit.py b/scripts/claimit.py
index 4594922..e88259b 100755
--- a/scripts/claimit.py
+++ b/scripts/claimit.py
@@ -162,7 +162,7 @@
@rtype: bool
"""
exists_arg = ''
- commandline_claims = list()
+ commandline_claims = []
# Process global args and prepare generator args parser
local_args = pywikibot.handle_args(args)
@@ -181,7 +181,7 @@
pywikibot.error('Incomplete command line property-value pair.')
return False
- claims = list()
+ claims = []
repo = pywikibot.Site().data_repository()
for i in range(0, len(commandline_claims), 2):
claim = pywikibot.Claim(repo, commandline_claims[i])
diff --git a/scripts/harvest_template.py b/scripts/harvest_template.py
index 0aee728..93ff8a3 100755
--- a/scripts/harvest_template.py
+++ b/scripts/harvest_template.py
@@ -226,7 +226,7 @@
@param args: command line arguments
@type args: list of unicode
"""
- commandline_arguments = list()
+ commandline_arguments = []
template_title = u''
# Process global args and prepare generator args parser
@@ -253,7 +253,7 @@
if len(commandline_arguments) % 2:
raise ValueError # or something.
- fields = dict()
+ fields = {}
for i in range(0, len(commandline_arguments), 2):
fields[commandline_arguments[i]] = commandline_arguments[i + 1]
diff --git a/scripts/imagetransfer.py b/scripts/imagetransfer.py
index b745171..33e71f4 100755
--- a/scripts/imagetransfer.py
+++ b/scripts/imagetransfer.py
@@ -154,8 +154,8 @@
description = i18n.twtranslate(self.targetSite,
'imagetransfer-file_page_message',
- dict(site=sourceSite,
- description=description))
+ {'site': sourceSite,
+ 'description': description})
description += '\n\n'
description += sourceImagePage.getFileVersionHistoryTable()
# add interwiki link
diff --git a/scripts/patrol.py b/scripts/patrol.py
index 7506db2..9c72285 100755
--- a/scripts/patrol.py
+++ b/scripts/patrol.py
@@ -426,7 +426,7 @@
if pywikibot.config.verbose_output:
pywikibot.output(u'loading page links on %s' % self.page_title)
p = pywikibot.Page(self.site, self.page_title)
- linkedpages = list()
+ linkedpages = []
for linkedpage in p.linkedPages():
linkedpages.append(linkedpage.title())
diff --git a/scripts/standardize_interwiki.py b/scripts/standardize_interwiki.py
index ed12fb2..55c2b14 100644
--- a/scripts/standardize_interwiki.py
+++ b/scripts/standardize_interwiki.py
@@ -42,9 +42,9 @@
# Some parameters
-options = list()
-start = list()
-filelist = list()
+options = []
+start = []
+filelist = []
hints = {}
debug = 0
start = '!'
diff --git a/scripts/welcome.py b/scripts/welcome.py
index cbef2c6..08b8204 100755
--- a/scripts/welcome.py
+++ b/scripts/welcome.py
@@ -428,10 +428,10 @@
"""Constructor."""
self.site = pywikibot.Site()
self.check_managed_sites()
- self.bname = dict()
+ self.bname = {}
self._totallyCount = 0
- self.welcomed_users = list()
+ self.welcomed_users = []
if globalvar.randomSign:
self.defineSign(True)
@@ -495,7 +495,7 @@
badword_page = pywikibot.Page(self.site,
i18n.translate(self.site,
bad_pag))
- list_loaded = list()
+ list_loaded = []
if badword_page.exists():
pywikibot.output(u'\nLoading the bad words list from %s...'
% self.site)
@@ -510,7 +510,7 @@
# initialize whitelist
whitelist_default = ['emiliano']
wtlpg = i18n.translate(self.site, whitelist_pg)
- list_white = list()
+ list_white = []
if wtlpg:
whitelist_page = pywikibot.Page(self.site, wtlpg)
if whitelist_page.exists():
@@ -607,7 +607,7 @@
minorEdit=True)
showStatus(5)
pywikibot.output(u'Reported')
- self.BAQueue = list()
+ self.BAQueue = []
else:
return True
@@ -790,7 +790,7 @@
% welcomed_count)
if welcomed_count >= globalvar.dumpToLog:
if self.makelogpage(self.welcomed_users):
- self.welcomed_users = list()
+ self.welcomed_users = []
welcomed_count = 0
else:
continue
@@ -817,10 +817,10 @@
u'Putting the log of the latest %d users...'
% welcomed_count)
if self.makelogpage(self.welcomed_users):
- self.welcomed_users = list()
+ self.welcomed_users = []
else:
continue
- self.welcomed_users = list()
+ self.welcomed_users = []
if hasattr(self, '_BAQueue'):
showStatus()
pywikibot.output("Putting bad name to report page....")
diff --git a/tests/family_tests.py b/tests/family_tests.py
index f619c10..5359776 100644
--- a/tests/family_tests.py
+++ b/tests/family_tests.py
@@ -175,7 +175,7 @@
@PatchingTestCase.patched(pywikibot, 'Site')
def Site(self, code, fam, *args, **kwargs):
"""Own DrySite creator."""
- self.assertEqual(args, tuple())
+ self.assertEqual(args, ())
self.assertEqual(kwargs, {})
self.assertEqual(code, self.current_code)
self.assertEqual(fam, self.current_family)
diff --git a/tests/pagegenerators_tests.py b/tests/pagegenerators_tests.py
index 23b5b3b..b24180d 100755
--- a/tests/pagegenerators_tests.py
+++ b/tests/pagegenerators_tests.py
@@ -583,7 +583,7 @@
pages = pywikibot.tools.DequeGenerator([mainpage])
gen = pagegenerators.DequePreloadingGenerator(pages)
- pages_out = list()
+ pages_out = []
for page in gen:
pages_out.append(page)
# Add a page to the generator
diff --git a/tests/tools_tests.py b/tests/tools_tests.py
index c0e916c..be7acc0 100644
--- a/tests/tools_tests.py
+++ b/tests/tools_tests.py
@@ -514,7 +514,7 @@
def test_dict(self):
"""Test filter_unique with a dict."""
- deduped = dict()
+ deduped = {}
deduper = tools.filter_unique(self.ints, container=deduped)
self._test_dedup_int(deduped, deduper)
diff --git a/tests/ui_tests.py b/tests/ui_tests.py
index 4f27e30..75fd646 100644
--- a/tests/ui_tests.py
+++ b/tests/ui_tests.py
@@ -732,7 +732,7 @@
def test_no_color(self):
"""Test a string without any colors."""
- self._colors = tuple()
+ self._colors = ()
self.ui_obj._print('Hello world you!', self.stream)
self.assertEqual(self._getvalue(), 'Hello world you!')
diff --git a/tests/wikibase_edit_tests.py b/tests/wikibase_edit_tests.py
index 7ae5dd0..5c50893 100644
--- a/tests/wikibase_edit_tests.py
+++ b/tests/wikibase_edit_tests.py
@@ -155,7 +155,7 @@
repo = self.get_repo()
item = pywikibot.ItemPage(repo)
- self.assertEqual(item._defined_by(), dict())
+ self.assertEqual(item._defined_by(), {})
item.editEntity(data)
def test_set_redirect_target(self):
--
To view, visit
https://gerrit.wikimedia.org/r/354454
To unsubscribe, visit
https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Iaa142d4c947a86a7dd158aa3d6ce91265b48b7fb
Gerrit-PatchSet: 2
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Dalba <dalba.wiki(a)gmail.com>
Gerrit-Reviewer: Magul <tomasz.magulski(a)gmail.com>
Gerrit-Reviewer: Mpaa <mpaa.wiki(a)gmail.com>
Gerrit-Reviewer: jenkins-bot <>