Merge branch 'develop'

This commit is contained in:
Philip Wellnitz [10] 2024-08-29 20:02:46 +09:00
commit 51570938d4
13 changed files with 92 additions and 48 deletions

View File

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [2.7, 3.5, 3.6, 3.7, 3.8]
python-version: [3.7, 3.8, 3.9, 3.11, 3.12]
steps:
- name: Checkout code

View File

@ -3,11 +3,9 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct
import os
from inspect import formatargspec
from sphinx.ext import autodoc
from powerline.lint.inspect import getconfigargspec
from powerline.lint.inspect import formatconfigargspec, getconfigargspec
from powerline.segments import Segment
from powerline.lib.unicode import unicode
@ -28,7 +26,7 @@ class ThreadedDocumenter(autodoc.FunctionDocumenter):
def format_args(self):
argspec = getconfigargspec(self.object)
return formatargspec(*argspec, formatvalue=formatvalue).replace('\\', '\\\\')
return formatconfigargspec(*argspec, formatvalue=formatvalue).replace('\\', '\\\\')
class Repr(object):

View File

@ -176,7 +176,7 @@ def init_tmux_environment(pl, args, set_tmux_environment=set_tmux_environment):
' ' * powerline.renderer.strwidth(left_dividers['hard'])))
TMUX_VAR_RE = re.compile('\$(_POWERLINE_\w+)')
TMUX_VAR_RE = re.compile(r'\$(_POWERLINE_\w+)')
def tmux_setup(pl, args):

View File

@ -46,12 +46,12 @@ def get_preferred_output_encoding():
if hasattr(locale, 'LC_MESSAGES'):
return (
locale.getlocale(locale.LC_MESSAGES)[1]
or locale.getdefaultlocale()[1]
or locale.getlocale()[1]
or 'ascii'
)
return (
locale.getdefaultlocale()[1]
locale.getlocale()[1]
or 'ascii'
)
@ -66,12 +66,12 @@ def get_preferred_input_encoding():
if hasattr(locale, 'LC_MESSAGES'):
return (
locale.getlocale(locale.LC_MESSAGES)[1]
or locale.getdefaultlocale()[1]
or locale.getlocale()[1]
or 'latin1'
)
return (
locale.getdefaultlocale()[1]
locale.getlocale()[1]
or 'latin1'
)
@ -86,7 +86,7 @@ def get_preferred_arguments_encoding():
a problem.
'''
return (
locale.getdefaultlocale()[1]
locale.getlocale()[1]
or 'latin1'
)

View File

@ -41,7 +41,7 @@ def generate_json_config_loader(lhadproblem):
return load_json_config
function_name_re = '^(\w+\.)*[a-zA-Z_]\w*$'
function_name_re = r'^(\w+\.)*[a-zA-Z_]\w*$'
divider_spec = Spec().printable().len(
@ -205,7 +205,7 @@ vim_colorscheme_spec = (Spec(
mode_translations_value_spec(),
).optional().context_message('Error while loading mode translations (key {key})'),
).context_message('Error while loading vim colorscheme'))
shell_mode_spec = Spec().re('^(?:[\w\-]+|\.safe)$').copy
shell_mode_spec = Spec().re(r'^(?:[\w\-]+|\.safe)$').copy
shell_colorscheme_spec = (Spec(
name=name_spec(),
groups=groups_spec(),
@ -223,7 +223,7 @@ args_spec = Spec(
segment_module_spec = Spec().type(unicode).func(check_segment_module).optional().copy
exinclude_spec = Spec().re(function_name_re).func(check_exinclude_function).copy
segment_spec_base = Spec(
name=Spec().re('^[a-zA-Z_]\w*$').optional(),
name=Spec().re(r'^[a-zA-Z_]\w*$').optional(),
function=Spec().re(function_name_re).func(check_segment_function).optional(),
exclude_modes=Spec().list(vim_mode_spec()).optional(),
include_modes=Spec().list(vim_mode_spec()).optional(),

View File

@ -1,7 +1,8 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
from inspect import ArgSpec, getargspec
from inspect import FullArgSpec, getfullargspec
from itertools import zip_longest
from powerline.segments import Segment
@ -33,7 +34,7 @@ def getconfigargspec(obj):
requires_filesystem_watcher = hasattr(obj, 'powerline_requires_filesystem_watcher')
for name, method in argspecobjs:
argspec = getargspec(method)
argspec = getfullargspec(method)
omitted_args = get_omitted_args(name, method)
largs = len(argspec.args)
for i, arg in enumerate(reversed(argspec.args)):
@ -60,4 +61,31 @@ def getconfigargspec(obj):
if arg not in args:
args.insert(0, arg)
return ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults))
return FullArgSpec(args=args, varargs=None, varkw=None, defaults=tuple(defaults), kwonlyargs=(), kwonlydefaults={}, annotations={})
def formatconfigargspec(args, varargs=None, varkw=None, defaults=None,
kwonlyargs=(), kwonlydefaults={}, annotations={},
formatvalue=lambda value: '=' + repr(value)):
'''Format an argument spec from the values returned by getconfigargspec.
This is a specialized replacement for inspect.formatargspec, which has been
deprecated since Python 3.5 and was removed in Python 3.11. It supports
valid values for args, defaults and formatvalue; all other parameters are
expected to be either empty or None.
'''
assert varargs is None
assert varkw is None
assert not kwonlyargs
assert not kwonlydefaults
assert not annotations
specs = []
if defaults:
firstdefault = len(args) - len(defaults)
for i, arg in enumerate(args):
spec = arg
if defaults and i >= firstdefault:
spec += formatvalue(defaults[i - firstdefault])
specs.append(spec)
return '(' + ', '.join(specs) + ')'

View File

@ -34,7 +34,7 @@ class Spec(object):
.. note::
Methods that create the specifications return ``self``, so calls to them
may be chained: ``Spec().type(unicode).re('^\w+$')``. This does not
may be chained: ``Spec().type(unicode).re('^\\w+$')``. This does not
apply to functions that *apply* specification like :py:meth`Spec.match`.
.. note::
@ -585,7 +585,7 @@ class Spec(object):
msg_func
or (lambda value: 'String "{0}" is not an alphanumeric/underscore colon-separated identifier'.format(value))
)
return self.re('^\w+(?::\w+)?$', msg_func)
return self.re(r'^\w+(?::\w+)?$', msg_func)
def oneof(self, collection, msg_func=None):
'''Describe value that is equal to one of the value in the collection

View File

@ -1,6 +1,8 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import os
import re
from imaplib import IMAP4_SSL_PORT, IMAP4_SSL, IMAP4
@ -17,9 +19,19 @@ class EmailIMAPSegment(KwThreadedSegment):
interval = 60
@staticmethod
def key(username, password, server='imap.gmail.com', port=IMAP4_SSL_PORT, folder='INBOX', use_ssl=None, **kwargs):
def key(username='', password='', server='imap.gmail.com', port=IMAP4_SSL_PORT, username_variable='', password_variable='', server_variable='', port_variable='', folder='INBOX', use_ssl=None, **kwargs):
if use_ssl is None:
use_ssl = (port == IMAP4_SSL_PORT)
# catch if user set custom mail credential env variables
if username_variable:
username = os.environ[username_variable]
if password_variable:
password = os.environ[password_variable]
if server_variable:
server = os.environ[server_variable]
if port_variable:
port = os.environ[port_variable]
return _IMAPKey(username, password, server, port, folder, use_ssl)
def compute_state(self, key):
@ -33,7 +45,7 @@ class EmailIMAPSegment(KwThreadedSegment):
mail.login(key.username, key.password)
rc, message = mail.status(key.folder, '(UNSEEN)')
unread_str = message[0].decode('utf-8')
unread_count = int(re.search('UNSEEN (\d+)', unread_str).group(1))
unread_count = int(re.search(r'UNSEEN (\d+)', unread_str).group(1))
return unread_count
@staticmethod
@ -64,6 +76,14 @@ email_imap_alert = with_docstring(EmailIMAPSegment(),
e-mail server
:param int port:
e-mail server port
:param str username_variable:
name of environment variable to check for login username
:param str password_variable:
name of environment variable to check for login password
:param str server_variable:
name of environment variable to check for email server
:param str port_variable:
name of environment variable to check for email server port
:param str folder:
folder to check for e-mails
:param int max_msgs:

View File

@ -1,7 +1,5 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
from datetime import datetime
from datetime import datetime, timezone
def date(pl, format='%Y-%m-%d', istime=False, timezone=None):
@ -45,11 +43,11 @@ UNICODE_TEXT_TRANSLATION = {
}
def fuzzy_time(pl, format='{minute_str} {hour_str}', unicode_text=False, timezone=None, hour_str=['twelve', 'one', 'two', 'three', 'four',
def fuzzy_time(pl, format=None, unicode_text=False, timezone=None, hour_str=['twelve', 'one', 'two', 'three', 'four',
'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven'], minute_str = {
'0': 'o\'clock', '5': 'five past', '10': 'ten past','15': 'quarter past',
'20': 'twenty past', '25': 'twenty-five past', '30': 'half past', '35': 'twenty-five to',
'40': 'twenty to', '45': 'quarter to', '50': 'ten to', '55': 'five to'
'0': '{hour_str} o\'clock', '5': 'five past {hour_str}', '10': 'ten past {hour_str}','15': 'quarter past {hour_str}',
'20': 'twenty past {hour_str}', '25': 'twenty-five past {hour_str}', '30': 'half past {hour_str}', '35': 'twenty-five to {hour_str}',
'40': 'twenty to {hour_str}', '45': 'quarter to {hour_str}', '50': 'ten to {hour_str}', '55': 'five to {hour_str}'
}, special_case_str = {
'(23, 58)': 'round about midnight',
'(23, 59)': 'round about midnight',
@ -62,8 +60,7 @@ def fuzzy_time(pl, format='{minute_str} {hour_str}', unicode_text=False, timezon
'''Display the current time as fuzzy time, e.g. "quarter past six".
:param string format:
Format used to display the fuzzy time. (Ignored when a special time
is displayed.)
(unused)
:param bool unicode_text:
If true then hyphenminuses (regular ASCII ``-``) and single quotes are
replaced with unicode dashes and apostrophes.
@ -74,7 +71,9 @@ def fuzzy_time(pl, format='{minute_str} {hour_str}', unicode_text=False, timezon
Strings to be used to display the hour, starting with midnight.
(This list may contain 12 or 24 entries.)
:param dict minute_str:
Dictionary mapping minutes to strings to be used to display them.
Dictionary mapping minutes to strings to be used to display them. Each entry may
optionally come with a format field "{hour_str}" to indicate the position of the
string used for the current hour.
:param dict special_case_str:
Special strings for special times.
@ -100,7 +99,7 @@ def fuzzy_time(pl, format='{minute_str} {hour_str}', unicode_text=False, timezon
pass
hour = now.hour
if now.minute >= 30:
if now.minute >= 32:
hour = hour + 1
hour = hour % len(hour_str)
@ -115,7 +114,7 @@ def fuzzy_time(pl, format='{minute_str} {hour_str}', unicode_text=False, timezon
elif now.minute < mn and mn - now.minute < min_dis:
min_dis = mn - now.minute
min_pos = mn
result = format.format(minute_str=minute_str[str(min_pos)], hour_str=hour_str[hour])
result = minute_str[str(min_pos)].format(hour_str=hour_str[hour])
if unicode_text:
result = result.translate(UNICODE_TEXT_TRANSLATION)

View File

@ -1,7 +1,7 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
__version__ = "2.8.3"
__version__ = "2.8.4"
def get_version():
return __version__

View File

@ -1,7 +1,7 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import imp
import types
import sys
@ -48,7 +48,7 @@ def urllib_read(query_url):
elif query_url.startswith('https://freegeoip.app/json/'):
return '{"ip":"82.145.55.16","country_code":"DE","country_name":"Germany","region_code":"NI","region_name":"Lower Saxony","city":"Meppen","zip_code":"49716","time_zone":"Europe/Berlin","latitude":52.6833,"longitude":7.3167,"metro_code":0}'
elif query_url.startswith('http://geoip.nekudo.com/api/'):
return '{"city":"Meppen","country":{"name":"Germany", "code":"DE"},"location":{"accuracy_radius":100,"latitude":52.6833,"longitude":7.3167,"time_zone":"Europe\/Berlin"},"ip":"82.145.55.16"}'
return r'{"city":"Meppen","country":{"name":"Germany", "code":"DE"},"location":{"accuracy_radius":100,"latitude":52.6833,"longitude":7.3167,"time_zone":"Europe\/Berlin"},"ip":"82.145.55.16"}'
elif query_url.startswith('http://query.yahooapis.com/v1/public/'):
if 'Meppen' in query_url or '52.6833' in query_url:
return r'{"query":{"count":1,"created":"2016-05-13T19:43:18Z","lang":"en-US","results":{"channel":{"units":{"distance":"mi","pressure":"in","speed":"mph","temperature":"C"},"title":"Yahoo! Weather - Meppen, NI, DE","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/","description":"Yahoo! Weather for Meppen, NI, DE","language":"en-us","lastBuildDate":"Fri, 13 May 2016 09:43 PM CEST","ttl":"60","location":{"city":"Meppen","country":"Germany","region":" NI"},"wind":{"chill":"55","direction":"350","speed":"25"},"atmosphere":{"humidity":"57","pressure":"1004.0","rising":"0","visibility":"16.1"},"astronomy":{"sunrise":"5:35 am","sunset":"9:21 pm"},"image":{"title":"Yahoo! Weather","width":"142","height":"18","link":"http://weather.yahoo.com","url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"},"item":{"title":"Conditions for Meppen, NI, DE at 08:00 PM CEST","lat":"52.68993","long":"7.29115","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/","pubDate":"Fri, 13 May 2016 08:00 PM CEST","condition":{"code":"23","date":"Fri, 13 May 2016 08:00 PM CEST","temp":"14","text":"Breezy"},"forecast":[{"code":"30","date":"13 May 2016","day":"Fri","high":"71","low":"48","text":"Partly Cloudy"},{"code":"28","date":"14 May 2016","day":"Sat","high":"54","low":"44","text":"Mostly Cloudy"},{"code":"11","date":"15 May 2016","day":"Sun","high":"55","low":"43","text":"Showers"},{"code":"28","date":"16 May 2016","day":"Mon","high":"54","low":"42","text":"Mostly Cloudy"},{"code":"28","date":"17 May 2016","day":"Tue","high":"57","low":"43","text":"Mostly Cloudy"},{"code":"12","date":"18 May 2016","day":"Wed","high":"62","low":"45","text":"Rain"},{"code":"28","date":"19 May 2016","day":"Thu","high":"63","low":"48","text":"Mostly Cloudy"},{"code":"28","date":"20 May 2016","day":"Fri","high":"67","low":"50","text":"Mostly Cloudy"},{"code":"30","date":"21 May 2016","day":"Sat","high":"71","low":"50","text":"Partly Cloudy"},{"code":"30","date":"22 May 2016","day":"Sun","high":"74","low":"54","text":"Partly Cloudy"}],"description":"<![CDATA[<img src=\"http://l.yimg.com/a/i/us/we/52/23.gif\"/>\n<BR />\n<b>Current Conditions:</b>\n<BR />Breezy\n<BR />\n<BR />\n<b>Forecast:</b>\n<BR /> Fri - Partly Cloudy. High: 71Low: 48\n<BR /> Sat - Mostly Cloudy. High: 54Low: 44\n<BR /> Sun - Showers. High: 55Low: 43\n<BR /> Mon - Mostly Cloudy. High: 54Low: 42\n<BR /> Tue - Mostly Cloudy. High: 57Low: 43\n<BR />\n<BR />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/\">Full Forecast at Yahoo! Weather</a>\n<BR />\n<BR />\n(provided by <a href=\"http://www.weather.com\" >The Weather Channel</a>)\n<BR />\n]]>","guid":{"isPermaLink":"false"}}}}}}'
@ -100,7 +100,7 @@ def replace_module(name, new=None, **kwargs):
def new_module(name, **kwargs):
module = imp.new_module(name)
module = types.ModuleType(name)
for k, v in kwargs.items():
setattr(module, k, v)
return module

View File

@ -111,7 +111,7 @@ class TestVimConfig(TestCase):
class TestConfig(TestCase):
def test_tmux(self):
from powerline.segments import common
from imp import reload
from importlib import reload
reload(common)
from powerline.shell import ShellPowerline
with replace_attr(common, 'urllib_read', urllib_read):
@ -165,7 +165,7 @@ class TestConfig(TestCase):
def test_wm(self):
from powerline.segments import common
from imp import reload
from importlib import reload
reload(common)
from powerline import Powerline
with replace_attr(wthr, 'urllib_read', urllib_read):

View File

@ -843,17 +843,16 @@ class TestTime(TestCommon):
time = Args(hour=0, minute=45)
pl = Pl()
hour_str = ['12', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven']
minute_str = {'0': 'o\'clock', '5': 'five past', '10': 'ten past','15':
'quarter past','20': 'twenty past', '25': 'twenty-five past',
'30': 'half past', '35': 'twenty-five to','40': 'twenty to', '45':
'quarter to', '50': 'ten to', '55': 'five to'}
minute_str = {'0': '{hour_str} o\'clock', '5': 'five past {hour_str}', '10': 'ten past {hour_str}',
'15': 'quarter past {hour_str}', '20': 'twenty past {hour_str}', '25': 'twenty-five past {hour_str}',
'30': 'half past {hour_str}', '35': 'twenty-five to {hour_str}', '40': 'twenty to {hour_str}',
'45': 'quarter to {hour_str}', '50': 'ten to {hour_str}', '55': 'five to {hour_str}'}
special_case_str = {
'(23, 58)': '~ midnight',
'(23, 59)': '~ midnight',
'(0, 0)': 'midnight',
'(0, 1)': '~ midnight',
'(0, 2)': '~ midnight',
'(12, 0)': 'twelve o\'clock'}
'(0, 2)': '~ midnight'}
with replace_attr(self.module, 'datetime', Args(strptime=lambda timezone, fmt: Args(tzinfo=timezone), now=lambda tz: time)):
self.assertEqual(self.module.fuzzy_time(pl=pl, hour_str=hour_str, minute_str=minute_str, special_case_str=special_case_str), 'quarter to one')
self.assertEqual(self.module.fuzzy_time(pl=pl), 'quarter to one')
@ -867,7 +866,7 @@ class TestTime(TestCommon):
self.assertEqual(self.module.fuzzy_time(pl=pl), 'twenty-five to twelve')
time.hour = 12
time.minute = 0
self.assertEqual(self.module.fuzzy_time(pl=pl, hour_str=hour_str, minute_str=minute_str, special_case_str=special_case_str), 'twelve o\'clock')
self.assertEqual(self.module.fuzzy_time(pl=pl, hour_str=hour_str, minute_str=minute_str, special_case_str=special_case_str), '12 o\'clock')
self.assertEqual(self.module.fuzzy_time(pl=pl), 'noon')
time.hour = 11
time.minute = 33
@ -875,7 +874,7 @@ class TestTime(TestCommon):
self.assertEqual(self.module.fuzzy_time(pl=pl, unicode_text=False), 'twenty-five to twelve')
time.hour = 12
time.minute = 0
self.assertEqual(self.module.fuzzy_time(pl=pl, unicode_text=False, hour_str=hour_str, minute_str=minute_str, special_case_str=special_case_str), 'twelve o\'clock')
self.assertEqual(self.module.fuzzy_time(pl=pl, unicode_text=False, hour_str=hour_str, minute_str=minute_str, special_case_str=special_case_str), '12 o\'clock')
self.assertEqual(self.module.fuzzy_time(pl=pl, unicode_text=False), 'noon')
time.hour = 11
time.minute = 33
@ -883,7 +882,7 @@ class TestTime(TestCommon):
self.assertEqual(self.module.fuzzy_time(pl=pl, unicode_text=True), 'twentyfive to twelve')
time.hour = 12
time.minute = 0
self.assertEqual(self.module.fuzzy_time(pl=pl, unicode_text=True, hour_str=hour_str, minute_str=minute_str, special_case_str=special_case_str), 'twelve oclock')
self.assertEqual(self.module.fuzzy_time(pl=pl, unicode_text=True, hour_str=hour_str, minute_str=minute_str, special_case_str=special_case_str), '12 oclock')
self.assertEqual(self.module.fuzzy_time(pl=pl, unicode_text=True),'noon')