commit python-limnoria for openSUSE:Factory
Hello community, here is the log from the commit of package python-limnoria for openSUSE:Factory checked in at 2018-05-01 23:27:57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-limnoria (Old) and /work/SRC/openSUSE:Factory/.python-limnoria.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-limnoria" Tue May 1 23:27:57 2018 rev:2 rq:602624 version:2018.04.21 Changes: -------- --- /work/SRC/openSUSE:Factory/python-limnoria/python-limnoria.changes 2018-04-20 17:31:17.110589531 +0200 +++ /work/SRC/openSUSE:Factory/.python-limnoria.new/python-limnoria.changes 2018-05-01 23:27:59.690998459 +0200 @@ -1,0 +2,7 @@ +Mon Apr 30 18:58:58 UTC 2018 - badshah400@gmail.com + +- Update to version 2018-04-21: + * Do not break UTF-8 characters in long words. Closes + gh#ProgVal/Limnoria#1333. + +------------------------------------------------------------------- Old: ---- master-2018-01-28.tar.gz New: ---- master-2018-04-21.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-limnoria.spec ++++++ --- /var/tmp/diff_new_pack.2GQ0fA/_old 2018-05-01 23:28:00.478969808 +0200 +++ /var/tmp/diff_new_pack.2GQ0fA/_new 2018-05-01 23:28:00.482969663 +0200 @@ -18,9 +18,9 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define appname limnoria -%define srcver 2018-01-28 +%define srcver 2018-04-21 Name: python-limnoria -Version: 2018.01.28 +Version: 2018.04.21 Release: 0 Summary: A modified version of Supybot (an IRC bot and framework) License: BSD-3-Clause @@ -40,13 +40,13 @@ BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: python-rpm-macros -Requires: python-SQLAlchemy Requires: python-PySocks +Requires: python-SQLAlchemy Requires: python-chardet Requires: python-ecdsa Requires: python-feedparser -Requires: python-python-gnupg Requires: python-python-dateutil +Requires: python-python-gnupg Requires: python-pytz Provides: Supybot = %{version} Obsoletes: Supybot < 1.0 ++++++ master-2018-01-28.tar.gz -> master-2018-04-21.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/plugins/Config/plugin.py new/Limnoria-master-2018-04-21/plugins/Config/plugin.py --- old/Limnoria-master-2018-01-28/plugins/Config/plugin.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/plugins/Config/plugin.py 2018-04-14 22:31:30.000000000 +0200 @@ -65,9 +65,15 @@ def getCapability(name): capability = 'owner' # Default to requiring the owner capability. + if not name.startswith('supybot') and not name.startswith('users'): + name = 'supybot.' + name parts = registry.split(name) + group = getattr(conf, parts.pop(0)) while parts: - part = parts.pop() + part = parts.pop(0) + group = group.get(part) + if not getattr(group, '_opSettable', True): + return 'owner' if ircutils.isChannel(part): # If a registry value has a channel in it, it requires a # 'channel,op' capability, or so we assume. We'll see if we're diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/plugins/Config/test.py new/Limnoria-master-2018-04-21/plugins/Config/test.py --- old/Limnoria-master-2018-01-28/plugins/Config/test.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/plugins/Config/test.py 2018-04-14 22:31:30.000000000 +0200 @@ -28,13 +28,23 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from supybot.test import * +import random +from supybot.test import * import supybot.conf as conf +_letters = 'abcdefghijklmnopqrstuvwxyz' +def random_string(): + return ''.join(random.choice(_letters) for _ in range(16)) + class ConfigTestCase(ChannelPluginTestCase): # We add utilities so there's something in supybot.plugins. - plugins = ('Config', 'Utilities') + plugins = ('Config', 'User', 'Utilities') + + prefix1 = 'somethingElse!user@host1.tld' + prefix2 = 'EvensomethingElse!user@host2.tld' + prefix3 = 'Completely!Different@host3.tld__no_testcap__' + def testGet(self): self.assertNotRegexp('config get supybot.reply', r'registry\.Group') self.assertResponse('config supybot.protocols.irc.throttleTime', '0.0') @@ -110,5 +120,52 @@ conf.supybot.commands.allowShell.setValue(True) conf.supybot.directories.plugins.setValue(old_plugins_dirs) + def testOpEditable(self): + var_name = 'testOpEditable' + random_string() + conf.registerChannelValue(conf.supybot.plugins.Config, var_name, + registry.Integer(0, 'help')) + self.assertNotError('register bar passwd', frm=self.prefix3, + private=True) + self.assertRegexp('whoami', 'bar', frm=self.prefix3) + ircdb.users.getUser('bar').addCapability(self.channel + ',op') + + self.assertRegexp('config plugins.Config.%s 1' % var_name, + '^Completely: Error: ', + frm=self.prefix3) + self.assertResponse('config plugins.Config.%s' % var_name, + 'Global: 0; #test: 0') + + self.assertNotRegexp('config channel plugins.Config.%s 1' % var_name, + '^Completely: Error: ', + frm=self.prefix3) + self.assertResponse('config plugins.Config.%s' % var_name, + 'Global: 0; #test: 1') + + def testOpNonEditable(self): + var_name = 'testOpNonEditable' + random_string() + conf.registerChannelValue(conf.supybot.plugins.Config, var_name, + registry.Integer(0, 'help'), opSettable=False) + self.assertNotError('register bar passwd', frm=self.prefix3, + private=True) + self.assertRegexp('whoami', 'bar', frm=self.prefix3) + ircdb.users.getUser('bar').addCapability(self.channel + ',op') + + self.assertRegexp('config plugins.Config.%s 1' % var_name, + '^Completely: Error: ', + frm=self.prefix3) + self.assertResponse('config plugins.Config.%s' % var_name, + 'Global: 0; #test: 0') + + self.assertRegexp('config channel plugins.Config.%s 1' % var_name, + '^Completely: Error: ', + frm=self.prefix3) + self.assertResponse('config plugins.Config.%s' % var_name, + 'Global: 0; #test: 0') + + self.assertNotRegexp('config channel plugins.Config.%s 1' % var_name, + '^Completely: Error: ') + self.assertResponse('config plugins.Config.%s' % var_name, + 'Global: 0; #test: 1') + # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/plugins/Games/test.py new/Limnoria-master-2018-04-21/plugins/Games/test.py --- old/Limnoria-master-2018-01-28/plugins/Games/test.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/plugins/Games/test.py 2018-04-14 22:31:30.000000000 +0200 @@ -36,7 +36,7 @@ self.irc.feedMsg(ircmsgs.op(self.channel, self.irc.nick)) sawKick = False for i in range(100): - m = self.getMsg('roulette', frm='someoneElse') + m = self.getMsg('roulette', frm='someoneElse!foo@bar') if m.command == 'PRIVMSG': self.failUnless(self._nonKickRe.search(m.args[1]), 'Got a msg without bang|click|spin: %r' % m) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/plugins/RSS/plugin.py new/Limnoria-master-2018-04-21/plugins/RSS/plugin.py --- old/Limnoria-master-2018-01-28/plugins/RSS/plugin.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/plugins/RSS/plugin.py 2018-04-14 22:31:30.000000000 +0200 @@ -403,12 +403,15 @@ all = __builtins__['all'] any = __builtins__['any'] + title = getattr(entry, 'title', '') + description = getattr(entry, 'description', '') + if whitelist: - if all(kw not in entry.title and kw not in entry.description + if all(kw not in title and kw not in description for kw in whitelist): return False if blacklist: - if any(kw in entry.title or kw in entry.description + if any(kw in title or kw in description for kw in blacklist): return False return True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/plugins/Services/plugin.py new/Limnoria-master-2018-04-21/plugins/Services/plugin.py --- old/Limnoria-master-2018-01-28/plugins/Services/plugin.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/plugins/Services/plugin.py 2018-04-14 22:31:30.000000000 +0200 @@ -239,7 +239,7 @@ elif chanserv and ircutils.strEqual(msg.nick, chanserv): self.doChanservNotice(irc, msg) - _chanRe = re.compile('\x02(.*?)\x02') + _chanRe = re.compile('\x02(#.*?)\x02') def doChanservNotice(self, irc, msg): if self.disabled(irc): return @@ -250,9 +250,13 @@ on = 'on %s' % irc.network if m is not None: channel = m.group(1) - if 'all bans' in s or 'unbanned from' in s: - # All bans removed (freenode) - # You have been unbanned from (oftc) + if 'all bans' in s or 'unbanned from' in s or \ + ('unbanned %s' % irc.nick.lower()) in \ + ircutils.stripFormatting(s): + # All bans removed (old freenode?) + # You have been unbanned from (oftc, anope) + # "Unbanned \x02someuser\x02 from \x02#channel\x02 (\x02N\x02 + # ban(s) removed)" (atheme 7.x) irc.sendMsg(networkGroup.channels.join(channel)) elif 'isn\'t registered' in s: self.log.warning('Received "%s isn\'t registered" from ChanServ %s', @@ -345,7 +349,8 @@ 'NickServ %s. Check email at %s and send the ' 'auth command to NickServ.', on, email) else: - self.log.info('Received notice from NickServ %s: %q.', on, s) + self.log.info('Received notice from NickServ %s: %q.', on, + ircutils.stripFormatting(msg.args[1])) def checkPrivileges(self, irc, channel): if self.disabled(irc): @@ -404,7 +409,7 @@ chanserv = self.registryValue('ChanServ') if chanserv: msg = ircmsgs.privmsg(chanserv, - ' '.join([command, channel, irc.nick])) + ' '.join([command, channel])) irc.sendMsg(msg) else: if log: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/plugins/Web/config.py new/Limnoria-master-2018-04-21/plugins/Web/config.py --- old/Limnoria-master-2018-01-28/plugins/Web/config.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/plugins/Web/config.py 2018-04-14 22:31:30.000000000 +0200 @@ -55,10 +55,16 @@ conf.registerChannelValue(Web, 'snarferShowDomain', registry.Boolean(True, _("""Determines whether domain names should be displayed by the title snarfer."""))) +conf.registerChannelValue(Web, 'snarfMultipleUrls', + registry.Boolean(False, _("""Determines whether the title snarfer will + query all URLs in a message, or only the first one."""))) conf.registerChannelValue(Web, 'snarferShowTargetDomain', registry.Boolean(False, _("""Determines whether the domain name displayed by the snarfer will be the original one (posted on IRC) or the target one (got after following redirects, if any)."""))) +conf.registerChannelValue(Web, 'snarferPrefix', + registry.String(_('Title: '), _("""Determines the string used at before + a web page's title."""))) conf.registerChannelValue(Web, 'nonSnarfingRegexp', registry.Regexp(None, _("""Determines what URLs matching the given regexp will not be snarfed. Give the empty string if you have no URLs that you'd diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/plugins/Web/plugin.py new/Limnoria-master-2018-04-21/plugins/Web/plugin.py --- old/Limnoria-master-2018-01-28/plugins/Web/plugin.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/plugins/Web/plugin.py 2018-04-14 22:31:30.000000000 +0200 @@ -30,6 +30,7 @@ import re import sys +import string import socket import supybot.conf as conf @@ -198,10 +199,14 @@ domain = utils.web.getDomain(target if self.registryValue('snarferShowTargetDomain', channel) else url) - s = format(_('Title: %s'), title) + prefix = self.registryValue('snarferPrefix', channel) + s = prefix + title if self.registryValue('snarferShowDomain', channel): s += format(_(' (at %s)'), domain) irc.reply(s, prefixNick=False) + if self.registryValue('snarfMultipleUrls', channel): + # FIXME: hack + msg.tag('repliedTo', False) titleSnarfer = urlSnarfer(titleSnarfer) titleSnarfer.__doc__ = utils.web._httpUrlRe diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/plugins/Web/test.py new/Limnoria-master-2018-04-21/plugins/Web/test.py --- old/Limnoria-master-2018-01-28/plugins/Web/test.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/plugins/Web/test.py 2018-04-14 22:31:30.000000000 +0200 @@ -83,16 +83,32 @@ finally: conf.supybot.plugins.Web.titleSnarfer.setValue(False) + def testMultipleTitleSnarfer(self): + try: + conf.supybot.plugins.Web.titleSnarfer.setValue(True) + conf.supybot.plugins.Web.snarfMultipleUrls.setValue(True) + self.feedMsg( + 'https://microsoft.com/ https://google.com/') + m1 = self.getMsg(' ') + m2 = self.getMsg(' ') + self.assertTrue(('Microsoft' in m1.args[1]) ^ + ('Microsoft' in m2.args[1])) + self.assertTrue(('Google' in m1.args[1]) ^ + ('Google' in m2.args[1])) + finally: + conf.supybot.plugins.Web.titleSnarfer.setValue(False) + conf.supybot.plugins.Web.snarfMultipleUrls.setValue(False) + def testNonSnarfing(self): snarf = conf.supybot.plugins.Web.nonSnarfingRegexp() title = conf.supybot.plugins.Web.titleSnarfer() try: - conf.supybot.plugins.Web.nonSnarfingRegexp.set('m/sf/') + conf.supybot.plugins.Web.nonSnarfingRegexp.set('m/fr/') try: conf.supybot.plugins.Web.titleSnarfer.setValue(True) - self.assertSnarfNoResponse('http://sf.net/', 2) - self.assertSnarfRegexp('http://www.sourceforge.net/', - r'Sourceforge\.net') + self.assertSnarfNoResponse('https://www.google.fr/', 2) + self.assertSnarfRegexp('https://www.google.com/', + r'Google') finally: conf.supybot.plugins.Web.titleSnarfer.setValue(title) finally: @@ -116,10 +132,10 @@ conf.supybot.plugins.Web.checkIgnored.setValue(False) (oldprefix, self.prefix) = (self.prefix, 'foo!bar@baz') try: - self.assertSnarfRegexp('https://google.com/', 'Google') + self.assertSnarfRegexp('https://google.it/', 'Google') self.assertNotError('admin ignore add %s' % self.prefix) - self.assertSnarfRegexp('https://www.google.com/', 'Google') - self.assertNoResponse('title http://www.google.com/') + self.assertSnarfRegexp('https://www.google.it/', 'Google') + self.assertNoResponse('title http://www.google.it/') finally: conf.supybot.plugins.Web.titleSnarfer.setValue(False) conf.supybot.plugins.Web.checkIgnored.setValue(True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/scripts/supybot-wizard new/Limnoria-master-2018-04-21/scripts/supybot-wizard --- old/Limnoria-master-2018-01-28/scripts/supybot-wizard 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/scripts/supybot-wizard 2018-04-14 22:31:30.000000000 +0200 @@ -184,6 +184,14 @@ 'run directly in the HOME directory. ' 'You should not do this unless you want it to ' 'create multiple files in your HOME directory.') + parser.add_option('', '--allow-bin', action='store_true', + dest='allowBin', + help='Determines whether the wizard will be allowed to ' + 'run directly in a directory for binaries (eg. ' + '/usr/bin, /usr/local/bin, or ~/.local/bin). ' + 'You should not do this unless you want it to ' + 'create multiple non-binary files in directory ' + 'that should only contain binaries.') parser.add_option('', '--no-network', action='store_false', dest='network', help='Determines whether the wizard will be allowed to ' @@ -195,6 +203,8 @@ if os.name == 'posix': if (os.getcwd() == os.path.expanduser('~')) and not options.allowHome: error('Please, don\'t run this in your HOME directory.') + if (os.path.split(os.getcwd())[-1] == 'bin') and not options.allowBin: + error('Please, don\'t run this in a "bin" directory.') if os.path.isfile(os.path.join('scripts', 'supybot-wizard')) or \ os.path.isfile(os.path.join('..', 'scripts', 'supybot-wizard')): print('') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/setup.py new/Limnoria-master-2018-04-21/setup.py --- old/Limnoria-master-2018-01-28/setup.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/setup.py 2018-04-14 22:31:30.000000000 +0200 @@ -37,7 +37,6 @@ import datetime import tempfile import subprocess -from math import ceil warnings.filterwarnings('always', category=DeprecationWarning) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/src/callbacks.py new/Limnoria-master-2018-04-21/src/callbacks.py --- old/Limnoria-master-2018-01-28/src/callbacks.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/src/callbacks.py 2018-04-14 22:31:30.000000000 +0200 @@ -383,36 +383,28 @@ return ' '.join(command) def checkCommandCapability(msg, cb, commandName): + plugin = cb.name().lower() if not isinstance(commandName, minisix.string_types): + assert commandName[0] == plugin, ('checkCommandCapability no longer ' + 'accepts command names that do not start with the callback\'s ' + 'name (%s): %s') % (plugin, commandName) commandName = '.'.join(commandName) - plugin = cb.name().lower() - pluginCommand = '%s.%s' % (plugin, commandName) def checkCapability(capability): assert ircdb.isAntiCapability(capability) if ircdb.checkCapability(msg.prefix, capability): log.info('Preventing %s from calling %s because of %s.', - msg.prefix, pluginCommand, capability) + msg.prefix, commandName, capability) raise RuntimeError(capability) try: - antiPlugin = ircdb.makeAntiCapability(plugin) antiCommand = ircdb.makeAntiCapability(commandName) - antiPluginCommand = ircdb.makeAntiCapability(pluginCommand) - checkCapability(antiPlugin) checkCapability(antiCommand) - checkCapability(antiPluginCommand) - checkAtEnd = [commandName, pluginCommand] + checkAtEnd = [commandName] default = conf.supybot.capabilities.default() if ircutils.isChannel(msg.args[0]): channel = msg.args[0] checkCapability(ircdb.makeChannelCapability(channel, antiCommand)) - checkCapability(ircdb.makeChannelCapability(channel, antiPlugin)) - checkCapability(ircdb.makeChannelCapability(channel, - antiPluginCommand)) - chanPlugin = ircdb.makeChannelCapability(channel, plugin) chanCommand = ircdb.makeChannelCapability(channel, commandName) - chanPluginCommand = ircdb.makeChannelCapability(channel, - pluginCommand) - checkAtEnd += [chanCommand, chanPlugin, chanPluginCommand] + checkAtEnd += [chanCommand] default &= ircdb.channels.getChannel(channel).defaultAllow return not (default or \ any(lambda x: ircdb.checkCapability(msg.prefix, x), @@ -925,9 +917,8 @@ log.warning('Truncating to %s bytes from %s bytes.', maximumLength, len(s)) s = s[:maximumLength] - s_too_long = len(s.encode()) < allowedLength \ - if minisix.PY3 else len(s) < allowedLength - if s_too_long or \ + s_size = len(s.encode()) if minisix.PY3 else len(s) + if s_size <= allowedLength or \ not conf.get(conf.supybot.reply.mores, target): # In case we're truncating, we add 20 to allowedLength, # because our allowedLength is shortened for the @@ -950,8 +941,7 @@ stripCtcp=stripCtcp) sendMsg(m) return m - msgs = ircutils.wrap(s, allowedLength, - break_long_words=True) + msgs = ircutils.wrap(s, allowedLength) msgs.reverse() instant = conf.get(conf.supybot.reply.mores.instant,target) while instant > 1 and msgs: @@ -1302,18 +1292,29 @@ else: self.log.info('%s called on %s by %q.', formatCommand(command), msg.args[0], msg.prefix) - # XXX I'm being extra-special-careful here, but we need to refactor - # this. try: - cap = checkCommandCapability(msg, self, command) + if len(command) == 1 or command[0] != self.canonicalName(): + fullCommandName = [self.canonicalName()] + command + else: + fullCommandName = command + # Let "P" be the plugin and "X Y" the command name. The + # fullCommandName is "P X Y" + + # check "Y" + cap = checkCommandCapability(msg, self, command[-1]) if cap: irc.errorNoCapability(cap) return - for name in command: - cap = checkCommandCapability(msg, self, name) + + # check "P", "P.X", and "P.X.Y" + prefix = [] + for name in fullCommandName: + prefix.append(name) + cap = checkCommandCapability(msg, self, prefix) if cap: irc.errorNoCapability(cap) return + try: self.callingCommand = command self.callCommand(command, irc, msg, *args, **kwargs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/src/conf.py new/Limnoria-master-2018-04-21/src/conf.py --- old/Limnoria-master-2018-01-28/src/conf.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/src/conf.py 2018-04-14 22:31:30.000000000 +0200 @@ -86,9 +86,10 @@ value.channelValue = False return group.register(name, value) -def registerChannelValue(group, name, value): +def registerChannelValue(group, name, value, opSettable=True): value._supplyDefault = True value.channelValue = True + value._opSettable = opSettable g = group.register(name, value) gname = g._name.lower() for name in registry._cache.keys(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/src/ircutils.py new/Limnoria-master-2018-04-21/src/ircutils.py --- old/Limnoria-master-2018-01-28/src/ircutils.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/src/ircutils.py 2018-04-14 22:31:30.000000000 +0200 @@ -254,9 +254,9 @@ if not args: return [] modes = args[0] - assert modes[0] in '+-', 'Invalid args: %r' % args args = list(args[1:]) ret = [] + last = '+' for c in modes: if c in '+-': last = c @@ -596,12 +596,9 @@ else: self.ungetChar(c) -def wrap(s, length, break_on_hyphens = False, break_long_words = False): +def wrap(s, length, break_on_hyphens = False): processed = [] - wrapper = textwrap.TextWrapper(width=length) - wrapper.break_long_words = break_long_words - wrapper.break_on_hyphens = break_on_hyphens - chunks = wrapper.wrap(s) + chunks = utils.str.byteTextWrap(s, length) context = None for chunk in chunks: if context is not None: @@ -819,7 +816,7 @@ 'm': localtime[4], 'min': localtime[4], 'minute': localtime[4], 's': localtime[5], 'sec': localtime[5], 'second': localtime[5], 'tz': time.strftime('%Z', localtime), - 'version': 'Limnoria %s' % version, + 'version': version, }) if irc: vars.update({ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/src/utils/str.py new/Limnoria-master-2018-04-21/src/utils/str.py --- old/Limnoria-master-2018-01-28/src/utils/str.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/src/utils/str.py 2018-04-14 22:31:30.000000000 +0200 @@ -34,6 +34,7 @@ """ import re +import sys import time import string import textwrap @@ -305,6 +306,46 @@ return '$' + unbraced return _perlVarSubstituteRe.sub(replacer, text) +def splitBytes(word, size): + # I'm going to hell for this function + for i in range(4): # a character takes at most 4 bytes in UTF-8 + try: + if sys.version_info[0] >= 3: + word[size-i:].decode() + else: + word[size-i:].encode('utf8') + except UnicodeDecodeError: + continue + else: + return (word[0:size-i], word[size-i:]) + assert False, (word, size) + +def byteTextWrap(text, size, break_on_hyphens=False): + """Similar to textwrap.wrap(), but considers the size of strings (in bytes) + instead of their length (in characters).""" + try: + words = textwrap.TextWrapper()._split_chunks(text) + except AttributeError: # Python 2 + words = textwrap.TextWrapper()._split(text) + words.reverse() # use it as a stack + if sys.version_info[0] >= 3: + words = [w.encode() for w in words] + lines = [b''] + while words: + word = words.pop(-1) + if len(word) > size: + (before, after) = splitBytes(word, size) + words.append(after) + word = before + if len(lines[-1]) + len(word) <= size: + lines[-1] += word + else: + lines.append(word) + if sys.version_info[0] >= 3: + return [l.decode() for l in lines] + else: + return lines + def commaAndify(seq, comma=',', And=None): """Given a a sequence, returns an English clause for that sequence. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/src/world.py new/Limnoria-master-2018-04-21/src/world.py --- old/Limnoria-master-2018-01-28/src/world.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/src/world.py 2018-04-14 22:31:30.000000000 +0200 @@ -99,6 +99,7 @@ ircs = [] # A list of all the IRCs. def getIrc(network): + """Returns Irc object of the given network. <network> is string and not case-sensitive.""" network = network.lower() for irc in ircs: if irc.network.lower() == network: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Limnoria-master-2018-01-28/test/test_ircutils.py new/Limnoria-master-2018-04-21/test/test_ircutils.py --- old/Limnoria-master-2018-01-28/test/test_ircutils.py 2018-01-25 14:09:19.000000000 +0100 +++ new/Limnoria-master-2018-04-21/test/test_ircutils.py 2018-04-14 22:31:30.000000000 +0200 @@ -168,6 +168,66 @@ s = ircutils.mircColor('[', 'blue') + ircutils.bold('09:21') self.assertEqual(ircutils.stripFormatting(s), '[09:21') + def testWrap(self): + if sys.version_info[0] < 3: + pred = len + else: + pred = lambda s:len(s.encode()) + + s = ('foo bar baz qux ' * 100)[0:-1] + + r = ircutils.wrap(s, 10) + self.assertTrue(max(map(pred, r)) <= 10) + self.assertEqual(''.join(r), s) + + r = ircutils.wrap(s, 100) + self.assertTrue(max(map(pred, r)) <= 100) + self.assertEqual(''.join(r), s) + + if sys.version_info[0] < 3: + uchr = unichr + u = lambda s: s.decode('utf8') + else: + uchr = chr + u = lambda x: x + s = (u('').join([uchr(0x1f527), uchr(0x1f527), uchr(0x1f527), u(' ')]) * 100)\ + [0:-1] + + r = ircutils.wrap(s, 20) + self.assertTrue(max(map(pred, r)) <= 20, (max(map(pred, r)), repr(r))) + self.assertEqual(''.join(r), s) + + r = ircutils.wrap(s, 100) + self.assertTrue(max(map(pred, r)) <= 100) + self.assertEqual(''.join(r), s) + + s = ('foobarbazqux ' * 100)[0:-1] + + r = ircutils.wrap(s, 10) + self.assertTrue(max(map(pred, r)) <= 10) + self.assertEqual(''.join(r), s) + + r = ircutils.wrap(s, 100) + self.assertTrue(max(map(pred, r)) <= 100) + self.assertEqual(''.join(r), s) + + s = ('foobarbazqux' * 100)[0:-1] + + r = ircutils.wrap(s, 10) + self.assertTrue(max(map(pred, r)) <= 10) + self.assertEqual(''.join(r), s) + + r = ircutils.wrap(s, 100) + self.assertTrue(max(map(pred, r)) <= 100) + self.assertEqual(''.join(r), s) + + s = uchr(233)*500 + r = ircutils.wrap(s, 500) + self.assertTrue(max(map(pred, r)) <= 500) + r = ircutils.wrap(s, 139) + self.assertTrue(max(map(pred, r)) <= 139) + + def testSafeArgument(self): s = 'I have been running for 9 seconds' bolds = ircutils.bold(s)
participants (1)
-
root@hilbert.suse.de