# vim:fileencoding=utf-8:noet from __future__ import (unicode_literals, division, absolute_import, print_function) import imp import sys class Pl(object): def __init__(self): self.exceptions = [] self.errors = [] self.warns = [] self.debugs = [] self.infos = [] self.prefix = None self.use_daemon_threads = True for meth in ('error', 'warn', 'debug', 'exception', 'info'): exec(( 'def {0}(self, msg, *args, **kwargs):\n' ' self.{0}s.append((kwargs.get("prefix") or self.prefix, msg, args, kwargs))\n' ).format(meth)) def __nonzero__(self): return bool(self.exceptions or self.errors or self.warns) __bool__ = __nonzero__ class Args(object): theme_override = {} config_override = {} config_path = None ext = ['shell'] renderer_module = None def __init__(self, **kwargs): self.__dict__.update(kwargs) def urllib_read(query_url): if query_url.startswith('http://ipv'): if query_url.startswith('http://ipv4.icanhazip.com'): return '127.0.0.1' elif query_url.startswith('http://ipv6.icanhazip.com'): return '2001:4801:7818:6:abc5:ba2c:ff10:275f' 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"}' 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":"\n
\nCurrent Conditions:\n
Breezy\n
\n
\nForecast:\n
Fri - Partly Cloudy. High: 71Low: 48\n
Sat - Mostly Cloudy. High: 54Low: 44\n
Sun - Showers. High: 55Low: 43\n
Mon - Mostly Cloudy. High: 54Low: 42\n
Tue - Mostly Cloudy. High: 57Low: 43\n
\n
\nFull Forecast at Yahoo! Weather\n
\n
\n(provided by The Weather Channel)\n
\n]]>","guid":{"isPermaLink":"false"}}}}}}' elif 'Moscow' in query_url: return r'{"query":{"count":1,"created":"2016-05-13T19:47:01Z","lang":"en-US","results":{"channel":{"units":{"distance":"mi","pressure":"in","speed":"mph","temperature":"C"},"title":"Yahoo! Weather - Moscow, Moscow Federal City, RU","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/","description":"Yahoo! Weather for Moscow, Moscow Federal City, RU","language":"en-us","lastBuildDate":"Fri, 13 May 2016 10:47 PM MSK","ttl":"60","location":{"city":"Moscow","country":"Russia","region":" Moscow Federal City"},"wind":{"chill":"45","direction":"80","speed":"11"},"atmosphere":{"humidity":"52","pressure":"993.0","rising":"0","visibility":"16.1"},"astronomy":{"sunrise":"4:19 am","sunset":"8:34 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 Moscow, Moscow Federal City, RU at 09:00 PM MSK","lat":"55.741638","long":"37.605061","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/","pubDate":"Fri, 13 May 2016 09:00 PM MSK","condition":{"code":"33","date":"Fri, 13 May 2016 09:00 PM MSK","temp":"9","text":"Mostly Clear"},"forecast":[{"code":"30","date":"13 May 2016","day":"Fri","high":"62","low":"41","text":"Partly Cloudy"},{"code":"30","date":"14 May 2016","day":"Sat","high":"64","low":"43","text":"Partly Cloudy"},{"code":"30","date":"15 May 2016","day":"Sun","high":"63","low":"44","text":"Partly Cloudy"},{"code":"12","date":"16 May 2016","day":"Mon","high":"60","low":"47","text":"Rain"},{"code":"12","date":"17 May 2016","day":"Tue","high":"64","low":"48","text":"Rain"},{"code":"28","date":"18 May 2016","day":"Wed","high":"67","low":"48","text":"Mostly Cloudy"},{"code":"12","date":"19 May 2016","day":"Thu","high":"68","low":"49","text":"Rain"},{"code":"39","date":"20 May 2016","day":"Fri","high":"66","low":"50","text":"Scattered Showers"},{"code":"39","date":"21 May 2016","day":"Sat","high":"69","low":"49","text":"Scattered Showers"},{"code":"30","date":"22 May 2016","day":"Sun","high":"73","low":"50","text":"Partly Cloudy"}],"description":"\n
\nCurrent Conditions:\n
Mostly Clear\n
\n
\nForecast:\n
Fri - Partly Cloudy. High: 62Low: 41\n
Sat - Partly Cloudy. High: 64Low: 43\n
Sun - Partly Cloudy. High: 63Low: 44\n
Mon - Rain. High: 60Low: 47\n
Tue - Rain. High: 64Low: 48\n
\n
\nFull Forecast at Yahoo! Weather\n
\n
\n(provided by The Weather Channel)\n
\n]]>","guid":{"isPermaLink":"false"}}}}}}' elif query_url.startswith('https://api.openweathermap.org/data/2.5/'): if 'Meppen' in query_url or '52.6833' in query_url: return r'{"coord":{"lon":7.29,"lat":52.69},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"base":"stations","main":{"temp":293.15,"feels_like":295.16,"temp_min":293.15,"temp_max":295.37,"pressure":1018,"humidity":77},"visibility":10000,"wind":{"speed":1.12,"deg":126},"clouds":{"all":0},"dt":1600196220,"sys":{"type":1,"id":1871,"country":"DE","sunrise":1600146332,"sunset":1600191996},"timezone":7200,"id":2871845,"name":"Meppen","cod":200}' elif 'Moscow' in query_url: return r'{"coord":{"lon":37.62,"lat":55.75},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"base":"stations","main":{"temp":283.15,"feels_like":280.78,"temp_min":283.15,"temp_max":284.26,"pressure":1019,"humidity":71},"visibility":10000,"wind":{"speed":3,"deg":330},"clouds":{"all":0},"dt":1600196224,"sys":{"type":1,"id":9029,"country":"RU","sunrise":1600138909,"sunset":1600184863},"timezone":10800,"id":524901,"name":"Moscow","cod":200}' raise NotImplementedError class Process(object): def __init__(self, output, err): self.output = output self.err = err def communicate(self): return self.output, self.err class ModuleReplace(object): def __init__(self, name, new): self.name = name self.new = new def __enter__(self): self.old = sys.modules.get(self.name) if not self.old: try: self.old = __import__(self.name) except ImportError: pass sys.modules[self.name] = self.new def __exit__(self, *args): if self.old: sys.modules[self.name] = self.old else: sys.modules.pop(self.name) def replace_module(name, new=None, **kwargs): if not new: new = new_module(name, **kwargs) return ModuleReplace(name, new) def new_module(name, **kwargs): module = imp.new_module(name) for k, v in kwargs.items(): setattr(module, k, v) return module class AttrReplace(object): def __init__(self, obj, *args): self.obj = obj self.attrs = args[::2] self.new = args[1::2] def __enter__(self): self.old = {} for i, attr in enumerate(self.attrs): try: self.old[i] = getattr(self.obj, attr) except AttributeError: pass for attr, new in zip(self.attrs, self.new): setattr(self.obj, attr, new) def __exit__(self, *args): for i, attr in enumerate(self.attrs): try: old = self.old[i] except KeyError: delattr(self.obj, attr) else: setattr(self.obj, attr, old) replace_attr = AttrReplace def replace_module_module(module, name, **kwargs): return replace_attr(module, name, new_module(name, **kwargs)) class ItemReplace(object): def __init__(self, d, key, new, r=None): self.key = key self.new = new self.d = d self.r = r def __enter__(self): self.old = self.d.get(self.key) self.d[self.key] = self.new return self.r def __exit__(self, *args): if self.old is None: try: self.d.pop(self.key) except KeyError: pass else: self.d[self.key] = self.old def replace_item(d, key, new): return ItemReplace(d, key, new, d) def replace_env(key, new, environ=None, **kwargs): r = kwargs.copy() r['environ'] = environ or {} return ItemReplace(r['environ'], key, new, r) class PowerlineSingleTest(object): def __init__(self, suite, name): self.suite = suite self.name = name def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): if exc_type is not None: self.exception('Exception while running test: {0!r}'.format( exc_value)) def fail(self, message, allow_failure=False): return self.suite.fail(self.name, message, allow_failure) def exception(self, message, allow_failure=False): return self.suite.exception(self.name, message, allow_failure)