From 1df343e9ab7defa284a73390210a65cf2112f17e Mon Sep 17 00:00:00 2001 From: Bill Meek Date: Fri, 15 Nov 2019 10:20:16 -0600 Subject: [PATCH] Hardware Profile: Now works python2 and python3 New packages required: python-uritools python3-uritools python-mailer python3-mailer python-simplejson python3-simplejson python3-mysqldb # required for bindings too python3-future # required for bindings too --- mythtv/configure | 9 +- .../hardwareprofile/MultipartPostHandler.py | 57 ++-- .../scripts/hardwareprofile/config.py | 13 +- .../scripts/hardwareprofile/deleteProfile.py | 36 ++- .../scripts/hardwareprofile/devicelist.py | 7 +- .../scripts/hardwareprofile/distros/all.py | 2 +- .../scripts/hardwareprofile/distros/distro.py | 3 +- .../distros/mythtv_data/data_mythtv.py | 72 +++-- .../distros/mythtv_data/main.py | 7 +- .../distros/mythtv_data/makeopts.py | 9 +- .../distros/mythtv_data/orddict.py | 19 +- .../distros/mythtv_data/request.py | 15 +- .../distros/mythtv_data/uuiddb.py | 25 +- .../scripts/hardwareprofile/fs_util.py | 19 +- .../programs/scripts/hardwareprofile/gate.py | 12 +- .../scripts/hardwareprofile/getLink.py | 36 ++- .../scripts/hardwareprofile/hwdata.py | 20 +- .../programs/scripts/hardwareprofile/i18n.py | 6 +- .../scripts/hardwareprofile/os_detect.py | 23 +- .../scripts/hardwareprofile/request.py | 15 +- .../programs/scripts/hardwareprofile/scan.py | 45 +-- .../scripts/hardwareprofile/sendProfile.py | 51 +-- .../programs/scripts/hardwareprofile/smolt.py | 301 ++++++++++-------- .../scripts/hardwareprofile/software.py | 20 +- .../scripts/hardwareprofile/uuiddb.py | 13 +- 25 files changed, 484 insertions(+), 351 deletions(-) mode change 100644 => 100755 mythtv/programs/scripts/hardwareprofile/deleteProfile.py diff --git a/mythtv/configure b/mythtv/configure index d19f95188f9..d65891916d8 100755 --- a/mythtv/configure +++ b/mythtv/configure @@ -6991,11 +6991,14 @@ fi # Check for python dependencies if enabled bindings_python; then - is_python3 && python=python2 - check_python || disable_bindings_python "Python 2.6" + check_python || disable_bindings_python "Python 2.6 or greater" check_py_lib MySQLdb || disable_bindings_python "MySQLdb" check_py_lib lxml || disable_bindings_python "lxml" - check_py_lib urlgrabber || disable_bindings_python "urlgrabber" + check_py_lib requests || disable_bindings_python "requests" + check_py_lib uritools || disable_bindings_python "uritools" + check_py_lib email || disable_bindings_python "email" + check_py_lib simplejson || disable_bindings_python "simplejson" + check_py_lib future || disable_bindings_python "future" fi # Check for perl dependencies diff --git a/mythtv/programs/scripts/hardwareprofile/MultipartPostHandler.py b/mythtv/programs/scripts/hardwareprofile/MultipartPostHandler.py index 2579fce123d..fc9e3275707 100644 --- a/mythtv/programs/scripts/hardwareprofile/MultipartPostHandler.py +++ b/mythtv/programs/scripts/hardwareprofile/MultipartPostHandler.py @@ -3,18 +3,18 @@ #### # 02/2006 Will Holcomb -# +# # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. -# +# # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # -# 7/26/07 Slightly modified by Brian Schneider +# 7/26/07 Slightly modified by Brian Schneider # in order to support unicode files ( multipart_encode function ) """ Usage: @@ -40,14 +40,19 @@ The main function of this file is a sample which downloads a page and then uploads it to the W3C validator. """ - -import urllib -import urllib2 -import mimetools, mimetypes +from __future__ import print_function + +from future import standard_library +standard_library.install_aliases() +from builtins import object +import urllib.request, urllib.error, urllib.parse +from email.generator import _make_boundary +import mimetypes import os, stat -from cStringIO import StringIO +import sys +from io import StringIO -class Callable: +class Callable(object): def __init__(self, anycallable): self.__call__ = anycallable @@ -55,45 +60,43 @@ def __init__(self, anycallable): # assigning a sequence. doseq = 1 -class MultipartPostHandler(urllib2.BaseHandler): - handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first +class MultipartPostHandler(urllib.request.BaseHandler): + handler_order = urllib.request.HTTPHandler.handler_order - 10 # needs to run first def http_request(self, request): - data = request.get_data() + data = request.data if data is not None and type(data) != str: v_files = [] v_vars = [] try: - for(key, value) in data.items(): - if type(value) == file: - v_files.append((key, value)) - else: - v_vars.append((key, value)) + for(key, value) in list(data.items()): + # 'file' type doesn't exist in python3 and we didn't use it. Removed if: + v_vars.append((key, value)) except TypeError: systype, value, traceback = sys.exc_info() - raise TypeError, "not a valid non-string sequence or mapping object", traceback + raise TypeError("not a valid non-string sequence or mapping object", traceback) if len(v_files) == 0: - data = urllib.urlencode(v_vars, doseq) + data = urllib.parse.urlencode(v_vars, doseq) else: boundary, data = self.multipart_encode(v_vars, v_files) contenttype = 'multipart/form-data; boundary=%s' % boundary if(request.has_header('Content-Type') and request.get_header('Content-Type').find('multipart/form-data') != 0): - print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data') + print("Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data')) request.add_unredirected_header('Content-Type', contenttype) - request.add_data(data) - + request.data = bytearray(data, 'latin1') + return request - def multipart_encode(vars, files, boundary = None, buf = None): + def multipart_encode(self, these_vars, files, boundary = None, buf = None): if boundary is None: - boundary = mimetools.choose_boundary() + boundary = _make_boundary(os.getuid + os.getpid()) if buf is None: buf = StringIO() - for(key, value) in vars: + for(key, value) in these_vars: buf.write('--%s\r\n' % boundary) buf.write('Content-Disposition: form-data; name="%s"' % key) buf.write('\r\n\r\n' + value + '\r\n') @@ -118,7 +121,7 @@ def main(): import tempfile, sys validatorURL = "http://validator.w3.org/check" - opener = urllib2.build_opener(MultipartPostHandler) + opener = urllib.request.build_opener(MultipartPostHandler) def validateFile(url): temp = tempfile.mkstemp(suffix=".html") @@ -126,7 +129,7 @@ def validateFile(url): params = { "ss" : "0", # show source "doctype" : "Inline", "uploaded_file" : open(temp[1], "rb") } - print opener.open(validatorURL, params).read() + print(opener.open(validatorURL, params).read()) os.remove(temp[1]) if len(sys.argv[1:]) > 0: diff --git a/mythtv/programs/scripts/hardwareprofile/config.py b/mythtv/programs/scripts/hardwareprofile/config.py index 51eff2e022d..d15b25f94a5 100644 --- a/mythtv/programs/scripts/hardwareprofile/config.py +++ b/mythtv/programs/scripts/hardwareprofile/config.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -import os,re -import commands +import os, re, sys +from subprocess import Popen, PIPE import os_detect SMOON_URL = "http://smolt.mythtv.org/" @@ -10,7 +10,7 @@ from MythTV import MythDB confdir = os.path.join(MythDB().dbconfig.confdir, 'HardwareProfile') try: - os.mkdir(confdir, 0700) + os.mkdir(confdir, 0o700) except OSError: pass @@ -27,8 +27,13 @@ FS_T_FILTER=False FS_M_FILTER=True -FS_MOUNTS=commands.getoutput('rpm -ql filesystem').split('\n') +try: + p = Popen(['rpm', '-ql', 'filesystem'], stdout=PIPE) + p.wait() + FS_MOUNTS = p.stdout.read().strip() +except OSError: + FS_MOUNTS = '' #This will attempt to find the distro. #Uncomment any of the OS lines below to hardcode. diff --git a/mythtv/programs/scripts/hardwareprofile/deleteProfile.py b/mythtv/programs/scripts/hardwareprofile/deleteProfile.py old mode 100644 new mode 100755 index db3aac2f553..025e52fa231 --- a/mythtv/programs/scripts/hardwareprofile/deleteProfile.py +++ b/mythtv/programs/scripts/hardwareprofile/deleteProfile.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python2 # smolt - Fedora hardware profiler # @@ -19,10 +19,11 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +from __future__ import print_function +from builtins import str import sys -import urlgrabber.grabber +import requests from optparse import OptionParser -from urlparse import urljoin def main(): @@ -36,7 +37,7 @@ def main(): def serverMessage(page): for line in page.split("\n"): if 'ServerMessage:' in line: - error(_('Server Message: "%s"') % line.split('ServerMessage: ')[1]) + error(_('Server Message: "%s"' % line.split('ServerMessage: ')[1])) if 'Critical' in line: sys.exit(3) @@ -78,11 +79,14 @@ def serverMessage(page): smolt.DEBUG = opts.DEBUG smolt.hw_uuid_file = opts.uuidFile - grabber = urlgrabber.grabber.URLGrabber(user_agent=opts.user_agent, timeout=opts.timeout) - uuid = smolt.read_uuid() delHostString = 'uuid=%s' % uuid + session = requests.Session() + session.headers.update({'USER-AGENT': opts.user_agent}) + session.headers.update({'Content-type': 'application/x-www-form-urlencoded'}) + session.headers.update({'Content-length': '%i' % len(delHostString)}) + # Try retrieving current pub_uuid (from cache or remotely if necessary) pub_uuid = None try: @@ -90,25 +94,29 @@ def serverMessage(page): except PubUUIDError: pass + exceptions = (requests.exceptions.HTTPError, + requests.exceptions.URLRequired, + requests.exceptions.Timeout, + requests.exceptions.ConnectionError, + requests.exceptions.InvalidURL) try: - o=grabber.urlopen(urljoin(opts.smoonURL + '/', '/client/delete'), data=delHostString, http_headers=( - ('Content-length', '%i' % len(delHostString)), - ('Content-type', 'application/x-www-form-urlencoded'))) - except urlgrabber.grabber.URLGrabError, e: + o = session.post(opts.smoonURL + 'client/delete', data=delHostString, + timeout=opts.timeout) + except exceptions as e: sys.stderr.write(_('Error contacting Server:')) sys.stderr.write(str(e)) sys.stderr.write('\n') sys.exit(1) else: - serverMessage(o.read()) - o.close() + serverMessage(o.text) + session.close() if pub_uuid is None: - profile_url = urljoin(opts.smoonURL + '/', '/client/show?%s' % delHostString) + profile_url = opts.smoonURL + 'client/show?%s' % delHostString else: profile_url = get_profile_link(opts.smoonURL, pub_uuid) - print _('Profile removed, please verify at'), profile_url + print((_('Profile removed, please verify at'), profile_url)) if __name__ == '__main__': diff --git a/mythtv/programs/scripts/hardwareprofile/devicelist.py b/mythtv/programs/scripts/hardwareprofile/devicelist.py index 22cd8020f5c..2a91d8ad89c 100644 --- a/mythtv/programs/scripts/hardwareprofile/devicelist.py +++ b/mythtv/programs/scripts/hardwareprofile/devicelist.py @@ -19,6 +19,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +from builtins import object import os from hwdata import DeviceMap @@ -92,8 +93,8 @@ 'subsystem_vendor', 'subsystem_device'] -def cat(file): - fd = open(file, 'r') +def cat(file_name): + fd = open(file_name, 'r') results = fd.readlines() fd.close() return results @@ -160,7 +161,7 @@ def process(self): desc = cat(PATH + 'product')[0].strip().decode('ASCII', errors='ignore') except: #The fedora python pkg is broken and doesn't like decode with options, so this is a fallback - desc = cat(PATH + 'product')[0].strip().decode() + desc = cat(PATH + 'product')[0].strip() self.description = usb.device(self.vendorid, self.deviceid, alt=desc) diff --git a/mythtv/programs/scripts/hardwareprofile/distros/all.py b/mythtv/programs/scripts/hardwareprofile/distros/all.py index 3cde05cdece..2c7fae6eca6 100644 --- a/mythtv/programs/scripts/hardwareprofile/distros/all.py +++ b/mythtv/programs/scripts/hardwareprofile/distros/all.py @@ -17,7 +17,7 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. #from gentoo.main import create_gentoo -from mythtv_data.main import create_mythtv +from distros.mythtv_data.main import create_mythtv def get(): #res = [create_gentoo(),create_mythtv()] diff --git a/mythtv/programs/scripts/hardwareprofile/distros/distro.py b/mythtv/programs/scripts/hardwareprofile/distros/distro.py index a3bac89372b..b5ac8a0c862 100644 --- a/mythtv/programs/scripts/hardwareprofile/distros/distro.py +++ b/mythtv/programs/scripts/hardwareprofile/distros/distro.py @@ -16,7 +16,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -class Distro: +from builtins import object +class Distro(object): def _raise_abstract(self): raise Exception('Function must be overwritten.') diff --git a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/data_mythtv.py b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/data_mythtv.py index 6b809840ae4..64a4b2648c4 100644 --- a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/data_mythtv.py +++ b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/data_mythtv.py @@ -19,27 +19,30 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +from __future__ import division +from __future__ import print_function +from builtins import range +from builtins import object +from past.utils import old_div import os import re -import statvfs from i18n import _ from datetime import timedelta -from orddict import OrdDict -from uuiddb import UuidDb +from distros.mythtv_data.orddict import OrdDict +from distros.mythtv_data.uuiddb import UuidDb import MythTV -from user import home _DB = MythTV.MythDB() _BE = MythTV.MythBE(db=_DB) _SETTINGS = _DB.settings[_DB.gethostname()] prefix = 'mythtv' -class _Mythtv_data: +class _Mythtv_data(object): def __init__(self, gate): self.get_data(gate) - + def isBackend(self): return (_SETTINGS.BackendServerIP is not None) @@ -68,7 +71,7 @@ def ProcessVersion(self): 'Library API' : 'libapi', 'QT Version' : 'qtversion'} - for line in res.split('\n'): + for line in res.decode().split('\n'): try: prop, val = line.split(':') data[names[prop.strip()]] = val.strip() @@ -181,10 +184,13 @@ def processdirs(paths): free = 0 for path in paths: - stat = os.statvfs(path) - bsize = stat[statvfs.F_FRSIZE] - total += stat[statvfs.F_BLOCKS]*bsize - free += stat[statvfs.F_BFREE]*bsize + try: + stat = os.statvfs(path) + bsize = stat.f_frsize + total += stat.f_blocks*bsize + free += stat.f_bfree*bsize + except OSError: + pass return (total, free) @@ -229,22 +235,22 @@ def _read_file(filename): except: pass return firstline - - + + def _oss_alsa(): snd_type = "unknown" version = "unknown" alsasnd = "/proc/asound/version" osssnd = "/dev/sndstat" - + if os.path.exists(alsasnd): snd_type = "ALSA" version = _read_file(alsasnd)[-1].rstrip(".") - + elif os.path.exists(osssnd): version = _read_file(osssnd)[1] snd_type = "OSS" - + return snd_type , version def _process_search(processname): @@ -295,7 +301,7 @@ def _pulse(): data.jack = _jack() data.pulse = _pulse() data.audio_sys, data.audio_sys_version = _oss_alsa() - + return {'audio': data} def ProcessVideoProfile(self): @@ -371,8 +377,8 @@ def ProcessMySQL(self): def ProcessScheduler(self): def stddev(data): - avg = sum(data)/len(data) - return avg, (sum([(d-avg)**2 for d in data])/len(data))**.5 + avg = old_div(sum(data),len(data)) + return avg, (old_div(sum([(d-avg)**2 for d in data]),len(data)))**.5 data = OrdDict() data.count = 0 @@ -405,7 +411,7 @@ def stddev(data): match = [float(r[1]) for r in runs] place = [float(r[2]) for r in runs] - data.count = int(sum(count)/len(count)) + data.count = int(old_div(sum(count),len(count))) data.match_avg, data.match_stddev = stddev(match) data.place_avg, data.place_stddev = stddev(place) @@ -432,13 +438,13 @@ class CaptureCard( MythTV.database.DBData ): pass else: virtual[1] += isvirt - data = {'tuners':dict([(k,len(v)) for k,v in cardtypes.items()])} + data = {'tuners':dict([(k,len(v)) for k,v in list(cardtypes.items())])} if virtual[0]: - data['vtpertuner'] = sum(virtual)/float(virtual[0]) + data['vtpertuner'] = old_div(sum(virtual),float(virtual[0])) return data def ProcessSmoltInfo(self): - smoltfile=home+"/.mythtv/smolt.info" + smoltfile=os.path.expanduser('~') +"/.mythtv/smolt.info" config = {} try: config_file= open(smoltfile) @@ -466,7 +472,7 @@ def ProcessSmoltInfo(self): def ProcessLogUrgency(self): c = _DB.cursor() c.execute("""SELECT level,count(level) FROM logging GROUP BY level""") - levels = ('EMERG', 'ALERT', 'CRIT', 'ERR', + levels = ('EMERG', 'ALERT', 'CRIT', 'ERR', 'WARNING', 'NOTICE', 'INFO') # ignore debugging from totals counts = {} total = 0. @@ -474,8 +480,8 @@ def ProcessLogUrgency(self): if level in range(len(levels)): counts[levels[level]] = count total += count - for k,v in counts.items(): - counts[k] = v/total + for k,v in list(counts.items()): + counts[k] = old_div(v,total) return {'logurgency':counts} def get_data(self,gate): @@ -496,7 +502,7 @@ def get_data(self,gate): self._data.update(func()) except: pass - + self._data.theme = _SETTINGS.Theme if _DB.settings.NULL.country is not None: self._data.country = _DB.settings.NULL.country @@ -516,8 +522,8 @@ def get_data(self,gate): _DB.settings.NULL.SystemUUID = UuidDb().gen_uuid() self._data.uuid = _DB.settings.NULL.SystemUUID - - + + def serialize(self): res = self._data @@ -527,7 +533,7 @@ def _dump_rst_section(self, lines, title, data, line_break=True): lines.append(title) for k,v in sorted(data.items()): lines.append('- %s:\n %s \n' %(k,v)) - + if line_break: lines.append('') @@ -541,13 +547,13 @@ def dump_rst(self, lines): def _dump(self): lines = [] self.dump_rst(lines) - print '\n'.join(lines) - print + print('\n'.join(lines)) + print() def create_mythtv_data(gate): return _Mythtv_data(gate) - + if __name__ == '__main__': diff --git a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/main.py b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/main.py index a69fe85232a..d18d235a64f 100644 --- a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/main.py +++ b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/main.py @@ -1,3 +1,4 @@ +from __future__ import print_function # smolt - Fedora hardware profiler # # Copyright (C) 2009 Sebastian Pipping @@ -35,8 +36,8 @@ def detected(self, debug=False): def gather(self, gate, debug=False): def _stage(text): - print 'Processing %s' % (text) - from data_mythtv import create_mythtv_data + print('Processing %s' % (text)) + from distros.mythtv_data.data_mythtv import create_mythtv_data _stage('MythTV Data') features = create_mythtv_data(gate) @@ -89,4 +90,4 @@ def create_mythtv(): mythtv = create_mythtv() mythtv.gather(create_passing_gate(), debug=True) - print mythtv.rst() + print(mythtv.rst()) diff --git a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/makeopts.py b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/makeopts.py index 64cdc369820..3f06a866d33 100644 --- a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/makeopts.py +++ b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/makeopts.py @@ -1,3 +1,4 @@ +from __future__ import print_function # smolt - Fedora hardware profiler # # Copyright (C) 2009 Sebastian Pipping @@ -16,6 +17,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +from builtins import str +from builtins import object import re import portage @@ -23,7 +26,7 @@ LONG_PARA_PATTERN = '--\\S+|--\\S+=\\S+' PARA_PATTERN = re.compile('(%s|%s)\\b' % (SHORT_PARA_PATTERN, LONG_PARA_PATTERN)) -class MakeOpts: +class MakeOpts(object): def __init__(self, value=None): """ >>> m = MakeOpts("-C dir -f file -I dir -o file -W file -j 3 -l 4 -j -j3 -l --always-make") @@ -48,8 +51,8 @@ def serialize(self): return self._makeopts def dump(self): - print 'MAKEOPTS: ' + str(self.get()) - print + print('MAKEOPTS: ' + str(self.get())) + print() if __name__ == '__main__': diff --git a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/orddict.py b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/orddict.py index 69290378577..800d30ee8b4 100644 --- a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/orddict.py +++ b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/orddict.py @@ -17,10 +17,13 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +from builtins import zip +from builtins import map +from builtins import str __doc__="""This is an ordered dictionary implementation to be used to store client data before transmission to the server.""" -from itertools import imap, izip + class OrdDict( dict ): """ @@ -68,17 +71,17 @@ def __delitem__(self, name): def update(self, *data, **kwdata): if len(data) == 1: try: - for k,v in data[0].iteritems(): + for k,v in data[0].items(): self[k] = v except AttributeError: for k,v in iter(data[0]): self[k] = v if len(kwdata): - for k,v in kwdata.iteritems(): + for k,v in kwdata.items(): self[k] = v def __iter__(self): - return self.iterkeys() + return iter(self.keys()) def iterkeys(self): return iter(self._field_order) @@ -87,25 +90,25 @@ def keys(self): return list(self.iterkeys()) def itervalues(self): - return imap(self.get, self.iterkeys()) + return map(self.get, iter(self.keys())) def values(self): return list(self.itervalues()) def iteritems(self): - return izip(self.iterkeys(), self.itervalues()) + return zip(iter(self.keys()), iter(self.values())) def items(self): return list(self.iteritems()) def copy(self): c = self.__class__() - for k,v in self.items(): + for k,v in list(self.items()): try: c[k] = v.copy() except AttributeError: c[k] = v - for k,v in self.__dict__.items(): + for k,v in list(self.__dict__.items()): try: c[k] = v.copy() except AttributeError: diff --git a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/request.py b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/request.py index 21916c23ad1..2ae4fd3fdda 100644 --- a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/request.py +++ b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/request.py @@ -21,15 +21,18 @@ # providing the base url, user agent, and proxy information. # The object returned is slightly modified, with a shortcut to urlopen. -import urllib2 -import urlparse +from future import standard_library +standard_library.install_aliases() +from builtins import object +import urllib.request, urllib.error, urllib.parse +import urllib.parse -class _Request( urllib2.Request ): +class _Request( urllib.request.Request ): timeout = None def open(self): if self.timeout: - return urllib2.urlopen(self, None, self.timeout) - return urllib2.urlopen(self) + return urllib.request.urlopen(self, None, self.timeout) + return urllib.request.urlopen(self) class _RequestFactory( object ): def __init__(self, baseurl, user_agent, timeout, proxy): @@ -42,7 +45,7 @@ def __call__(self, *args, **kwargs): return self.new_request(*args, **kwargs) def new_request(self, url): - url = urlparse.urljoin(self.base_url, url) + url = urllib.parse.urljoin(self.base_url, url) req = _Request(url) req.timeout = self.timeout if self.proxy: diff --git a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/uuiddb.py b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/uuiddb.py index b7535de8a73..c0b12a089c6 100644 --- a/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/uuiddb.py +++ b/mythtv/programs/scripts/hardwareprofile/distros/mythtv_data/uuiddb.py @@ -16,10 +16,15 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -import ConfigParser +from future import standard_library +standard_library.install_aliases() +from builtins import map +from builtins import str +from builtins import object +import configparser import logging -import os , sys -sys.path.extend(map(os.path.abspath, ['../../'])) +import os , sys +sys.path.extend(list(map(os.path.abspath, ['../../']))) from smolt_config import get_config_attr from request import Request @@ -43,12 +48,12 @@ def __init__(self, message): def __str__(self): return str(self.msg) -class _UuidDb: +class _UuidDb(object): hw_uuid = None def __init__(self, database_filename): self._database_filename = database_filename - self._config = ConfigParser.RawConfigParser() + self._config = configparser.RawConfigParser() self._config.read(self._database_filename) if not self._config.has_section(_SECTION): self._config.add_section(_SECTION) @@ -58,7 +63,7 @@ def _flush(self): try: smolt_user_config_dir = os.path.expanduser('~/.smolt/') if not os.path.exists(smolt_user_config_dir): - os.mkdir(smolt_user_config_dir, 0700) + os.mkdir(smolt_user_config_dir, 0o700) f = open(self._database_filename, 'w') self._config.write(f) f.close() @@ -70,17 +75,17 @@ def get_pub_uuid(self, hw_uuid, host): pub_uuid = self._config.get(_SECTION, _get_option_name(hw_uuid, host)) logging.info('Public UUID "%s" read from database' % pub_uuid) return pub_uuid - except ConfigParser.NoOptionError: + except configparser.NoOptionError: try: req = Request('/client/pub_uuid/%s' % self.get_priv_uuid()) pudict = json.loads(req.open().read()) self.set_pub_uuid(self.hw_uuid, Request(), pudict['pub_uuid']) return pudict['pub_uuid'] - except Exception, e: + except Exception as e: error(_('Error determining public UUID: %s') % e) sys.stderr.write(_("Unable to determine Public UUID! This could be a network error or you've\n")) sys.stderr.write(_("not submitted your profile yet.\n")) - raise PubUUIDError, 'Could not determine Public UUID!\n' + raise PubUUIDError('Could not determine Public UUID!\n') def set_pub_uuid(self, hw_uuid, host, pub_uuid): for i in (hw_uuid, host, pub_uuid): @@ -114,7 +119,7 @@ def get_priv_uuid(self): try: # make sure directory exists, create if not file(self.hw_uuid_file).write(self.hw_uuid) - except Exception, e: + except Exception as e: raise UUIDError('Unable to save UUID to %s. Please run once as root.' % self.hw_uuid_file) return self.hw_uuid diff --git a/mythtv/programs/scripts/hardwareprofile/fs_util.py b/mythtv/programs/scripts/hardwareprofile/fs_util.py index b31f041af71..7442cca6ede 100644 --- a/mythtv/programs/scripts/hardwareprofile/fs_util.py +++ b/mythtv/programs/scripts/hardwareprofile/fs_util.py @@ -2,7 +2,7 @@ # fs_util.py - misc. routines not categorized in other modules # # Copyright 2008 Mike McGrath -# This file incorporates work covered by the following copyright +# This file incorporates work covered by the following copyright # Copyright 2006-2007 Red Hat, Inc. # # This copyrighted material is made available to anyone wishing to use, modify, @@ -17,12 +17,13 @@ # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat # trademarks that are incorporated in the source code or documentation are not # subject to the GNU General Public License and may only be used or replicated -# with the express permission of Red Hat, Inc. +# with the express permission of Red Hat, Inc. # +from builtins import object import os -# We cache the contents of /etc/mtab ... the following variables are used +# We cache the contents of /etc/mtab ... the following variables are used # to keep our cache in sync mtab_mtime = None mtab_map = [] @@ -46,7 +47,7 @@ def __dict__(self): def __str__(self): return "%s %s %s %s %s %s" % (self.mnt_fsname, self.mnt_dir, self.mnt_type, \ self.mnt_opts, self.mnt_freq, self.mnt_passno) - + class FileSystem(object): def __init__(self, mntent): self.mnt_dev = mntent.mnt_fsname @@ -65,7 +66,7 @@ def __init__(self, mntent): self.f_files = stat_res.f_files self.f_ffree = stat_res.f_ffree self.f_favail = stat_res.f_favail - + def to_dict(self): return dict(mnt_pnt=self.mnt_pnt, fs_type=self.fs_type, f_favail=self.f_favail, f_bsize=self.f_bsize, f_frsize=self.f_frsize, f_blocks=self.f_blocks, @@ -74,12 +75,12 @@ def to_dict(self): def __str__(self): return "%s %s %s %s %s %s %s %s %s %s %s" % \ - (self.mnt_dev, self.mnt_pnt, self.fs_type, + (self.mnt_dev, self.mnt_pnt, self.fs_type, self.f_bsize, self.f_frsize, self.f_blocks, self.f_bfree, self.f_bavail, self.f_files, self.f_ffree, self.f_favail) - + def get_mtab(mtab="/proc/mounts", vfstype=None): global mtab_mtime, mtab_map @@ -129,10 +130,10 @@ def get_file_device_path(fname): # find a best match fdir = os.path.dirname(fname) - match = mtab_dict.has_key(fdir) + match = fdir in mtab_dict while not match: fdir = os.path.realpath(os.path.join(fdir, os.path.pardir)) - match = mtab_dict.has_key(fdir) + match = fdir in mtab_dict # construct file path relative to device if fdir != os.path.sep: diff --git a/mythtv/programs/scripts/hardwareprofile/gate.py b/mythtv/programs/scripts/hardwareprofile/gate.py index 13f7e463e18..2ca0f522bda 100644 --- a/mythtv/programs/scripts/hardwareprofile/gate.py +++ b/mythtv/programs/scripts/hardwareprofile/gate.py @@ -17,12 +17,14 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -import ConfigParser +from builtins import str +from builtins import object +import configparser import os import logging -class _GateBase: +class _GateBase(object): def process(self, data_set, value_if_granted, value_else): if self.grants(data_set): return value_if_granted @@ -37,7 +39,7 @@ def __init__(self, config_files=None): '/etc/smolt/client.cfg', os.path.expanduser('~/.smolt/client.cfg'), ] - self.config = ConfigParser.ConfigParser() + self.config = configparser.ConfigParser() self.config.read(config_files) def grants(*args): @@ -55,8 +57,8 @@ def _grants(self, distro, data_set): try: return self.config.getboolean(distro, data_set) except (ValueError, - ConfigParser.NoOptionError, - ConfigParser.NoSectionError): + configparser.NoOptionError, + configparser.NoSectionError): # TODO warn about error? # Allow if in doubt - backwards compat return True diff --git a/mythtv/programs/scripts/hardwareprofile/getLink.py b/mythtv/programs/scripts/hardwareprofile/getLink.py index 2c33492c969..0bb957d4304 100644 --- a/mythtv/programs/scripts/hardwareprofile/getLink.py +++ b/mythtv/programs/scripts/hardwareprofile/getLink.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +### This module isn't used anywhere in the MythTV repository. + # smolt - Fedora hardware profiler # # Copyright (C) 2008 Yaakov M. Nemoy @@ -19,10 +21,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +from __future__ import print_function import sys from optparse import OptionParser -from urlparse import urljoin -import urlgrabber.grabber +import requests import json sys.path.append('/usr/share/smolt/client') @@ -65,23 +67,33 @@ def main(): from gate import create_default_gate profile = smolt.create_profile(create_default_gate(), smolt.read_uuid()) - grabber = urlgrabber.grabber.URLGrabber(user_agent=opts.user_agent, timeout=opts.timeout) + session = requests.Session() + session.headers.update({'USER-AGENT': opts.user_agent}) + + o = session.post(opts.smoonURL + '', timeout=opts.timeout) + + exceptions = (requests.exceptions.HTTPError, + requests.exceptions.URLRequired, + requests.exceptions.Timeout, + requests.exceptions.ConnectionError, + requests.exceptions.InvalidURL) + #first find out the server desired protocol try: #fli is a file like item - pub_uuid_fli = grabber.urlopen(urljoin(opts.smoonURL + "/", '/client/pub_uuid?uuid=%s' % profile.host.UUID, False)) - except urlgrabber.grabber.URLGrabError, e: + pub_uuid_fli = opts.smoonURL + 'client/pub_uuid?uuid=%s' % profile.host.UUID + pub_uuid_fli = session.get(pub_uuid_fli, timeout=opts.timeout) + except exceptions as e: error(_('Error contacting Server: %s') % e) return 1 - pub_uuid_str = pub_uuid_fli.read() try: + pub_uuid_obj = pub_uuid_fli.json() try: - pub_uuid_obj = json.loads(pub_uuid_str) - print _('To view your profile visit: %s') % smolt.get_profile_link(opts.smoonURL, pub_uuid_obj["pub_uuid"]) - except ValueError, e: + print(_('To view your profile visit: %s') % smolt.get_profile_link(opts.smoonURL, pub_uuid_obj["pub_uuid"])) + except ValueError as e: error(_('Something went wrong fetching the public UUID')) finally: - pub_uuid_fli.close() - + session.close() + if __name__ == '__main__': - main() + main() diff --git a/mythtv/programs/scripts/hardwareprofile/hwdata.py b/mythtv/programs/scripts/hardwareprofile/hwdata.py index f5eac2daed4..ba297bf24f5 100644 --- a/mythtv/programs/scripts/hardwareprofile/hwdata.py +++ b/mythtv/programs/scripts/hardwareprofile/hwdata.py @@ -19,6 +19,15 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +from __future__ import print_function +from __future__ import unicode_literals +from __future__ import division +from __future__ import absolute_import +from builtins import int +from builtins import open +from future import standard_library +standard_library.install_aliases() +from builtins import object from smolt_config import get_config_attr class myVendor(object): @@ -34,7 +43,7 @@ def __init__(self): self.subvendors = {} self.vendor = "" -class DeviceMap: +class DeviceMap(object): vendors = {} def __init__(self, bus='pci'): @@ -49,13 +58,14 @@ def device_map(self, bus='pci'): if os.path.isfile(fn + ".gz"): import gzip try: - fo = gzip.open(fn + ".gz", 'r') + # File isn't in the default python3 UTF-8, using latin1 + fo = gzip.open(fn + ".gz", 'rt', encoding='latin1') break except IOError: pass else: try: - fo = open(fn, 'r') + fo = open(fn, 'rt', encoding='latin1') break except IOError: pass @@ -99,7 +109,7 @@ def device_map(self, bus='pci'): continue subvend.name = "" - if not curdevice.subvendors.has_key(subvend.num): + if subvend.num not in curdevice.subvendors: curdevice.subvendors[subvend.num] = subvend subvend.devices[thisdev.num] = thisdev else: @@ -123,7 +133,7 @@ def device_map(self, bus='pci'): curvendor.devices[curdevice.num] = curdevice continue else: - print line + print(line) continue fo.close() # This introduces a bug, will fix later. diff --git a/mythtv/programs/scripts/hardwareprofile/i18n.py b/mythtv/programs/scripts/hardwareprofile/i18n.py index 48e57ca94a7..57fde9764cd 100644 --- a/mythtv/programs/scripts/hardwareprofile/i18n.py +++ b/mythtv/programs/scripts/hardwareprofile/i18n.py @@ -26,6 +26,7 @@ import os import gettext +import sys try: if os.path.isdir('po'): @@ -39,4 +40,7 @@ locale.setlocale(locale.LC_ALL, 'C') t = gettext.translation('smolt', '/usr/share/locale/', fallback=True, languages='en_US') -_ = t.ugettext +if sys.version_info[0] == 2: + _ = t.ugettext +else: + _ = t.gettext diff --git a/mythtv/programs/scripts/hardwareprofile/os_detect.py b/mythtv/programs/scripts/hardwareprofile/os_detect.py index 02acf5395e2..e73ca990cd4 100644 --- a/mythtv/programs/scripts/hardwareprofile/os_detect.py +++ b/mythtv/programs/scripts/hardwareprofile/os_detect.py @@ -5,8 +5,8 @@ # # Copyright (C) 2008 James Meyer # Copyright (C) 2008 Yaakov M. Nemoy -# Copyright (C) 2009 Carlos Gon�alves -# Copyright (C) 2009 Fran�ois Cami +# Copyright (C) 2009 Carlos Goncalves +# Copyright (C) 2009 Francois Cami # Copyright (C) 2010 Mike McGrath # Copyright (C) 2012 Raymond Wagner # @@ -24,7 +24,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +from __future__ import print_function +from builtins import object import os +from future.utils import with_metaclass class OrderedType( type ): # provide global sequencing for OS class and subclasses to ensure @@ -35,8 +38,7 @@ def __new__(mcs, name, bases, attrs): mcs.nextorder += 1 return type.__new__(mcs, name, bases, attrs) -class OS( object ): - __metaclass__ = OrderedType +class OS( with_metaclass(OrderedType, object) ): _requires_func = True def __init__(self, ostype=-1, func=None, inst=None): if callable(ostype): @@ -168,7 +170,7 @@ def do_test(self, *args, **kwargs): class OSInfoType( type ): def __new__(mcs, name, bases, attrs): OSs = [] - for k,v in attrs.items(): + for k,v in list(attrs.items()): if isinstance(v, OS): # build list of stored OS types OSs.append((v._order, k)) @@ -188,9 +190,7 @@ def __call__(cls): # fall through to Unknown return 'Unknown' -class get_os_info( object ): - __metaclass__ = OSInfoType - +class get_os_info( with_metaclass(OSInfoType, object) ): @OS('nt') def windows(self): win_version = { @@ -284,10 +284,15 @@ def linuxstandardbase(self): p = Popen([fullpath, '--id', '--codename', '--release', '--short'], stdout=PIPE, close_fds=True) p.wait() - return p.stdout.read().strip().replace('\n', ' ') + return p.stdout.read().decode().strip().replace('\n', ' ') @OSFromUname def Linux(self, OS, version): if OS == 'Linux': return 'Unknown Linux '+version return False + + +if __name__ == '__main__': + results = get_os_info() + print('Test results="{}"'.format(results)) diff --git a/mythtv/programs/scripts/hardwareprofile/request.py b/mythtv/programs/scripts/hardwareprofile/request.py index 722606bc182..f1a57e575a8 100644 --- a/mythtv/programs/scripts/hardwareprofile/request.py +++ b/mythtv/programs/scripts/hardwareprofile/request.py @@ -21,15 +21,18 @@ # providing the base url, user agent, and proxy information. # The object returned is slightly modified, with a shortcut to urlopen. -import urllib2 -import urlparse +from future import standard_library +standard_library.install_aliases() +from builtins import object +import urllib.request, urllib.error, urllib.parse +import urllib.parse -class _Request( urllib2.Request ): +class _Request( urllib.request.Request ): timeout = None def open(self): if self.timeout: - return urllib2.urlopen(self, None, self.timeout) - return urllib2.urlopen(self) + return urllib.request.urlopen(self, None, self.timeout) + return urllib.request.urlopen(self) class _RequestFactory( object ): def __init__(self, baseurl, user_agent, timeout, proxy): @@ -42,7 +45,7 @@ def __call__(self, *args, **kwargs): return self.new_request(*args, **kwargs) def new_request(self, url): - url = urlparse.urljoin(self.base_url, url) + url = urllib.parse.urljoin(self.base_url, url) req = _Request(url) req.timeout = self.timeout if self.proxy: diff --git a/mythtv/programs/scripts/hardwareprofile/scan.py b/mythtv/programs/scripts/hardwareprofile/scan.py index a58d9046318..51ab45cd975 100644 --- a/mythtv/programs/scripts/hardwareprofile/scan.py +++ b/mythtv/programs/scripts/hardwareprofile/scan.py @@ -17,17 +17,20 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +from __future__ import print_function +from future import standard_library +standard_library.install_aliases() import smolt -import json, urllib +import json, urllib.request, urllib.parse, urllib.error from i18n import _ from smolt_config import get_config_attr def rating(profile, smoonURL, gate): - print "" - print _("Current rating for vendor/model.") - print "" - scanURL='%s/client/host_rating?vendor=%s&system=%s' % (smoonURL, urllib.quote(profile.host.systemVendor), urllib.quote(profile.host.systemModel)) - r = json.load(urllib.urlopen(scanURL))['ratings'] + print("") + print(_("Current rating for vendor/model.")) + print("") + scanURL='%s/client/host_rating?vendor=%s&system=%s' % (smoonURL, urllib.parse.quote(profile.host.systemVendor), urllib.parse.quote(profile.host.systemModel)) + r = json.load(urllib.request.urlopen(scanURL))['ratings'] rating_system = { '0' : _('Unrated/Unknown'), '1' : _('Non-working'), '2' : _('Partially-working'), @@ -35,13 +38,13 @@ def rating(profile, smoonURL, gate): '4' : _('Works, needs additional configuration'), '5' : _('Works out of the box') } - print "\tCount\tRating" - print "\t-----------------" + print("\tCount\tRating") + print("\t-----------------") for rate in r: - print "\t%s\t%s" % (r[rate], rating_system[rate]) + print("\t%s\t%s" % (r[rate], rating_system[rate])) def scan(profile, smoonURL, gate): - print _("Scanning %s for known errata.\n" % smoonURL) + print(_("Scanning %s for known errata.\n" % smoonURL)) devices = [] for VendorID, DeviceID, SubsysVendorID, SubsysDeviceID, Bus, Driver, Type, Description in profile.deviceIter(): if VendorID: @@ -51,15 +54,15 @@ def scan(profile, smoonURL, gate): int(SubsysVendorID or 0), int(SubsysDeviceID or 0)) ) searchDevices = 'NULLPAGE' - devices.append('System/%s/%s' % ( urllib.quote(profile.host.systemVendor), urllib.quote(profile.host.systemModel) )) + devices.append('System/%s/%s' % ( urllib.parse.quote(profile.host.systemVendor), urllib.parse.quote(profile.host.systemModel) )) for dev in devices: searchDevices = "%s|%s" % (searchDevices, dev) - scanURL='%s/smolt-w/api.php' % smoonURL + scanURL='%ssmolt-w/api.php' % smoonURL scanData = 'action=query&titles=%s&format=json' % searchDevices try: - r = json.load(urllib.urlopen(scanURL, scanData)) + r = json.load(urllib.request.urlopen(scanURL, bytes(scanData, 'latin1'))) except ValueError: - print "Could not wiki for errata!" + print("Could not wiki for errata!") return found = [] @@ -71,14 +74,14 @@ def scan(profile, smoonURL, gate): pass if found: - print _("\tErrata Found!") - for f in found: print "\t%s" % f + print(_("\tErrata Found!")) + for f in found: print("\t%s" % f) else: - print _("\tNo errata found, if this machine is having issues please go to") - print _("\tyour profile and create a wiki page for the device so others can") - print _("\tbenefit") - -if __name__ == "__main__": + print(_("\tNo errata found, if this machine is having issues please go to")) + print(_("\tyour profile and create a wiki page for the device so others can")) + print(_("\tbenefit")) + +if __name__ == "__main__": from gate import create_passing_gate gate = create_passing_gate() smoonURL = get_config_attr("SMOON_URL", "http://smolts.org/") diff --git a/mythtv/programs/scripts/hardwareprofile/sendProfile.py b/mythtv/programs/scripts/hardwareprofile/sendProfile.py index 6e3a5b38725..88c93be4547 100755 --- a/mythtv/programs/scripts/hardwareprofile/sendProfile.py +++ b/mythtv/programs/scripts/hardwareprofile/sendProfile.py @@ -20,6 +20,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +from __future__ import print_function +from builtins import str +from builtins import input import sys import time import os @@ -162,7 +165,7 @@ def inner_indent(text): def dump_excerpts(excerpts): - print """\ + print("""\ ===================================================== %(label_intro)s @@ -183,7 +186,7 @@ def dump_excerpts(excerpts): %(label_question_view)s %(label_question_send)s %(label_question_quit)s -""" % excerpts +""" % excerpts) def present_and_require_confirmation(profile): @@ -201,24 +204,24 @@ def present_and_require_confirmation(profile): dump_excerpts(excerpts) try: - choice = raw_input(_('Your choice (s)end (v)iew (q)uit: ')).strip() + choice = input(_('Your choice (s)end (v)iew (q)uit: ')).strip() except KeyboardInterrupt: error(_('Exiting...')) sys.exit(4) if choice in (_('s|y|yes')).split('|'): submit = True - print '\n\n' + print('\n\n') elif choice in (_('q|n|no')).split('|'): sys.exit(0) elif choice in (_('v')).split('|'): - f = NamedTemporaryFile() + f = NamedTemporaryFile(suffix=b'') for line in profile.getProfile(): try: - f.write(line + '\n') + f.write(bytes(line + '\n', 'latin1')) except UnicodeEncodeError: pass f.flush() - os.chmod(f.name, 0400) + os.chmod(f.name, 0o400) try: pager_command = os.environ['PAGER'] except KeyError: @@ -234,7 +237,7 @@ def present_and_require_confirmation(profile): except NameError: os.system(' '.join([pager_command, f.name])) f.close() - print '\n\n' + print('\n\n') else: error(_('Exiting...')) sys.exit(4) @@ -264,7 +267,7 @@ def send_profile(uuiddb, uuid, profile, opts, proxies): else: (error_code, pub_uuid, admin) = do_send_profile(uuiddb, uuid, profile, opts, proxies) if error_code: - print _('Could not send - Exiting') + print(_('Could not send - Exiting')) sys.exit(1) return (error_code, pub_uuid, admin) @@ -276,15 +279,15 @@ def mention_profile_web_view(opts, pub_uuid, admin): from i18n import _ pubUrl = smolt.get_profile_link(opts.smoonURL, pub_uuid) - print - print _('To share your profile: \n\t%s (public)') % pubUrl + print() + print(_('To share your profile: \n\t%s (public)') % pubUrl) if not smolt.secure: - print _('\tAdmin Password: %s') % admin + print(_('\tAdmin Password: %s') % admin) def get_proxies(opts): if opts.httpproxy == None: - proxies = None + proxies = dict() else: proxies = {'http':opts.httpproxy} return proxies @@ -297,13 +300,13 @@ def read_profile(gate, uuid): try: profile = smolt.create_profile(gate, uuid) - except smolt.UUIDError, e: + except smolt.UUIDError as e: sys.stderr.write(_('%s\n' % e)) sys.exit(9) return profile -def register_with_fedora_account_system(opts): +def register_with_fedora_account_system(opts, profile): ensure_code_reachability() from i18n import _ @@ -313,7 +316,7 @@ def register_with_fedora_account_system(opts): password = opts.password if profile.register(userName=opts.userName, password=password, user_agent=opts.user_agent, smoonURL=opts.smoonURL, timeout=opts.timeout): - print _('Registration Failed, Try again') + print(_('Registration Failed, Try again')) def do_scan_remote(profile, opts, gate): @@ -324,14 +327,14 @@ def do_scan_remote(profile, opts, gate): try: rating(profile, opts.smoonURL, gate) except ValueError: - print "Could not get rating!" + print("Could not get rating!") def mention_missing_uuid(): ensure_code_reachability() from i18n import _ - print - print _('No Public UUID found! Please re-run with -n to generate a new public uuid') + print() + print(_('No Public UUID found! Please re-run with -n to generate a new public uuid')) def main_request_new_public_uuid(uuiddb, uuid, profile, opts): @@ -343,11 +346,11 @@ def main_request_new_public_uuid(uuiddb, uuid, profile, opts): pub_uuid = profile.regenerate_pub_uuid(uuiddb, uuid, user_agent=opts.user_agent, smoonURL=opts.smoonURL, timeout=opts.timeout) - except ServerError, e: + except ServerError as e: error(_('Error contacting server: %s') % str(e)) sys.exit(1) - print _('Success! Your new public UUID is: %s' % pub_uuid) + print(_('Success! Your new public UUID is: %s' % pub_uuid)) sys.exit(0) @@ -359,7 +362,7 @@ def main_scan_only(profile, opts, gate): def main_print_only(profile): for line in profile.getProfile(): if not line.startswith('#'): - print line.encode('utf-8') + print(line) sys.exit(0) @@ -372,7 +375,7 @@ def main_send_profile(uuiddb, uuid, profile, opts, gate): (error_code, pub_uuid, admin) = send_profile(uuiddb, uuid, profile, opts, proxies) if opts.userName: - register_with_fedora_account_system(opts) + register_with_fedora_account_system(opts, profile) if opts.scan_remote and not opts.cron_mode: do_scan_remote(profile, opts, gate) @@ -407,7 +410,7 @@ def main(): uuid = smolt.read_uuid() main_request_new_public_uuid(uuiddb, uuid, profile, opts) elif not opts.send_profile: - main_scan_only(profile, opts) + main_scan_only(profile, opts, gate) elif opts.printOnly and not opts.autoSend: main_print_only(profile) else: diff --git a/mythtv/programs/scripts/hardwareprofile/smolt.py b/mythtv/programs/scripts/hardwareprofile/smolt.py index 40a421e2b18..b756854d246 100644 --- a/mythtv/programs/scripts/hardwareprofile/smolt.py +++ b/mythtv/programs/scripts/hardwareprofile/smolt.py @@ -31,21 +31,26 @@ # Find out what we're not getting # -from i18n import _ - +from __future__ import print_function #import dbus +from i18n import _ import platform import software -import commands -import urlgrabber.grabber +import subprocess +import requests import sys import os -from urlparse import urljoin -from urlparse import urlparse -from urllib import urlencode -import urllib +try: + from urllib.request import build_opener +except ImportError: + from urllib2 import build_opener +try: + from urllib.parse import urlparse +except ImportError: + from urlparse import urlparse import json from json import JSONEncoder +from simplejson import errors as sje import datetime import logging @@ -59,19 +64,27 @@ from logging.handlers import RotatingFileHandler import codecs import MultipartPostHandler -import urllib2 try: import subprocess -except ImportError, e: +except ImportError as e: pass +try: + long() +except NameError: + long = int WITHHELD_MAGIC_STRING = 'WITHHELD' SELINUX_ENABLED = 1 SELINUX_DISABLED = 0 SELINUX_WITHHELD = -1 +EXCEPTIONS = (requests.exceptions.HTTPError, + requests.exceptions.URLRequired, + requests.exceptions.Timeout, + requests.exceptions.ConnectionError, + requests.exceptions.InvalidURL) fs_types = get_config_attr("FS_TYPES", ["ext2", "ext3", "xfs", "reiserfs"]) fs_mounts = dict.fromkeys(get_config_attr("FS_MOUNTS", ["/", "/home", "/etc", "/var", "/boot"]), True) @@ -88,7 +101,7 @@ supported_protocols = ['0.97',] user_agent = 'smolt/%s' % smoltProtocol timeout = 120.0 -proxies = None +proxies = dict() DEBUG = False @@ -190,6 +203,8 @@ ] def to_ascii(o, current_encoding='utf-8'): + ''' This shouldn't even be required in python3 ''' + return o if not isinstance(o, basestring): return o @@ -217,20 +232,26 @@ def __init__(self, gate, uuid): self.numCpus = gate.process('cpu', cpuInfo.get('count', 0), 0) self.cpuSpeed = gate.process('cpu', cpuInfo.get('speed', 0), 0) - self.systemMemory = gate.process('ram_size', memory['ram'], 0) - self.systemSwap = gate.process('swap_size', memory['swap'], 0) + try: # These fail on the one *buntu 19.04 host tested, see get_sendable_host() + self.systemMemory = gate.process('ram_size', memory['ram'], 0) + self.systemSwap = gate.process('swap_size', memory['swap'], 0) + except TypeError: + self.systemMemory = 0 + self.systemSwap = 0 + self.kernelVersion = gate.process('kernel', os.uname()[2], WITHHELD_MAGIC_STRING) if gate.grants('language'): try: self.language = os.environ['LANG'] except KeyError: try: - status, lang = commands.getstatusoutput("grep LANG /etc/sysconfig/i18n") - if status == 0: - self.language = lang.split('"')[1] + lang = subprocess.run(['grep', 'LANG', '/etc/sysconfig/i18n'], + stdout=subprocess.PIPE) + if lang.returncode == 0: + self.language = lang.stdout.strip().split(b'"')[1] else: self.language = 'Unknown' - except: + except subprocess.CalledProcessError: self.language = 'Unknown' else: self.language = WITHHELD_MAGIC_STRING @@ -272,26 +293,27 @@ def __init__(self, gate, uuid): self.formfactor = WITHHELD_MAGIC_STRING if tempform == 'ppc64': - if hostInfo.get('openfirmware.model'): - if hostInfo['openfirmware.model'][:3] == 'IBM': - self.systemVendor = 'IBM' - model = hostInfo['openfirmware.model'][4:8] - - model_map = { - '8842':'JS20', - '6779':'JS21', - '6778':'JS21', - '7988':'JS21', - '8844':'JS21', - '0200':'QS20', - '0792':'QS21', - } - try: - model_name = model_map[model] - self.systemModel = gate.process('model', model_name) - self.formfactor = gate.process('form_factor', 'Blade') - except KeyError: - pass + pass + # if hostInfo.get('openfirmware.model'): + # if hostInfo['openfirmware.model'][:3] == 'IBM': + # self.systemVendor = 'IBM' + # model = hostInfo['openfirmware.model'][4:8] + + # model_map = { + # '8842':'JS20', + # '6779':'JS21', + # '6778':'JS21', + # '7988':'JS21', + # '8844':'JS21', + # '0200':'QS20', + # '0792':'QS21', + # } + # try: + # model_name = model_map[model] + # self.systemModel = gate.process('model', model_name) + # self.formfactor = gate.process('form_factor', 'Blade') + # except KeyError: + # pass if gate.grants('selinux'): try: @@ -377,21 +399,22 @@ def __str__(self): return repr(self.value) def serverMessage(page): - for line in page.split("\n"): - if 'UUID:' in line: + for line in page.split(b"\n"): + if b'UUID:' in line: return line.strip()[6:] - if 'ServerMessage:' in line: - if 'Critical' in line: - raise ServerError, line.split('ServerMessage: ')[1] + if b'ServerMessage:' in line: + if b'Critical' in line: + raise ServerError(line.split('ServerMessage: ')[1]) else: - print _('Server Message: "%s"') % line.split('ServerMessage: ')[1] + print(_('Server Message: "%s"') % line.split(b'ServerMessage: ')[1]) def error(message): - print >> sys.stderr, message + print(message) + #print(message, file=sys.stderr) def debug(message): if DEBUG: - print message + print(message) def reset_resolver(): '''Attempt to reset the system hostname resolver. @@ -402,7 +425,7 @@ def reset_resolver(): resolv = ctypes.CDLL("libresolv.so.2") r = resolv.__res_init() except (OSError, AttributeError): - print "Warning: could not find __res_init in libresolv.so.2" + print("Warning: could not find __res_init in libresolv.so.2") r = -1 return r except ImportError: @@ -449,6 +472,7 @@ def __init__(self, gate, uuid): # self.systemBus = systemBus if gate.grants('devices'): + self.host = Host(gate, uuid) self.devices = get_device_list() # for udi in all_dev_lst: # props = self.get_properties_for_udi (udi) @@ -510,19 +534,20 @@ def __init__(self, gate, uuid): # elif boardproduct is not None and boardproduct is not None: # props['system.vendor'] = boardvendor # props['system.product'] = boardproduct - self.host = Host(gate, uuid) self.fss = get_file_systems(gate) self.distro_specific = self.get_distro_specific_data(gate) + self.session = requests.Session() + self.session.headers.update({'USER-AGENT': user_agent}) def get_distro_specific_data(self, gate): dist_dict = {} try: import distros.all - except: + except ImportError: return dist_dict - + for d in distros.all.get(): key = d.key() if d.detected(): @@ -615,17 +640,18 @@ def write_pub_uuid(self, uuiddb, smoonURL, pub_uuid, uuid): return try: - uuiddb.set_pub_uuid(uuid, smoonURLparsed[1], pub_uuid) - except Exception, e: + uuiddb.set_pub_uuid(uuid, smoonURLparsed.netloc, pub_uuid) + except Exception as e: sys.stderr.write(_('\tYour pub_uuid could not be written.\n\n')) return def write_admin_token(self,smoonURL,admin,admin_token_file): smoonURLparsed=urlparse(smoonURL) - admin_token_file += ("-"+smoonURLparsed[1]) + admin_token_file += ("-"+smoonURLparsed.netloc) try: - file(admin_token_file, 'w').write(admin) - except Exception, e: + with open(admin_token_file, 'w') as at_file: + at_file.write(admin) + except Exception as e: sys.stderr.write(_('\tYour admin token could not be cached: %s\n' % e)) return @@ -662,28 +688,28 @@ def serialize(object, human=False): return JSONEncoder(indent=indent, sort_keys=sort_keys).encode(object) reset_resolver() - grabber = urlgrabber.grabber.URLGrabber(user_agent=user_agent, timeout=timeout, proxies=proxies) + #first find out the server desired protocol try: - token = grabber.urlopen(urljoin(smoonURL + "/", '/tokens/token_json?uuid=%s' % self.host.UUID, False)) - except urlgrabber.grabber.URLGrabError, e: - error(_('Error contacting Server: %s') % e) + current_url = smoonURL + 'tokens/token_json?uuid=%s' % self.host.UUID + token = self.session.post(current_url, proxies=proxies, timeout=timeout) + except EXCEPTIONS as e: + error(_('Error contacting Server (tokens): {}'.format(e))) + self.session.close() return (1, None, None) - tok_str = token.read() + tok_obj = token.json() try: - try: - tok_obj = json.loads(tok_str) - if tok_obj['prefered_protocol'] in supported_protocols: - prefered_protocol = tok_obj['prefered_protocol'] - else: - error(_('Wrong version, server incapable of handling your client')) - return (1, None, None) - tok = tok_obj['token'] - - except ValueError, e: - error(_('Something went wrong fetching a token')) - finally: - token.close() + if tok_obj['prefered_protocol'] in supported_protocols: + prefered_protocol = tok_obj['prefered_protocol'] + else: + self.session.close() + error(_('Wrong version, server incapable of handling your client')) + return (1, None, None) + tok = tok_obj['token'] + + except ValueError as e: + self.session.close() + error(_('Something went wrong fetching a token')) send_host_obj = self.get_submission_data(prefered_protocol) @@ -701,7 +727,7 @@ def serialize(object, human=False): logdir = os.path.expanduser('~/.smolt/') try: if not os.path.exists(logdir): - os.mkdir(logdir, 0700) + os.mkdir(logdir, 0o0700) for k, v in log_matrix.items(): filename = os.path.expanduser(os.path.join( @@ -722,28 +748,29 @@ def serialize(object, human=False): debug('Sending Host') if batch: - entry_point = "/client/batch_add_json" + entry_point = "client/batch_add_json" logging.debug('Submitting in asynchronous mode') else: - entry_point = "/client/add_json" + entry_point = "client/add_json" logging.debug('Submitting in synchronous mode') - request_url = urljoin(smoonURL + "/", entry_point, False) + request_url = smoonURL + entry_point logging.debug('Sending request to %s' % request_url) try: - opener = urllib2.build_opener(MultipartPostHandler.MultipartPostHandler) + opener = build_opener(MultipartPostHandler.MultipartPostHandler) params = { 'uuid':self.host.UUID, 'host':serialized_host_obj_machine, 'token':tok, 'smolt_protocol':smoltProtocol} o = opener.open(request_url, params) - except Exception, e: - error(_('Error contacting Server: %s') % e) + except Exception as e: + error(_('Error contacting Server ([batch_]add_json): {}'.format(e))) return (1, None, None) else: try: server_response = serverMessage(o.read()) - except ServerError, e: + except ServerError as e: + self.session.close() error(_('Error contacting server: %s') % e) return (1, None, None) @@ -751,45 +778,59 @@ def serialize(object, human=False): if batch: pub_uuid = None else: - pub_uuid = server_response + pub_uuid = server_response.decode('latin1') self.write_pub_uuid(uuiddb, smoonURL, pub_uuid, uuid) try: - admin_token = grabber.urlopen(urljoin(smoonURL + "/", '/tokens/admin_token_json?uuid=%s' % self.host.UUID, False)) - except urlgrabber.grabber.URLGrabError, e: + admin_token = self.session.get(smoonURL + 'tokens/admin_token_json?uuid=%s' % self.host.UUID, + proxies=proxies, timeout=timeout) + except EXCEPTIONS as e: + self.session.close() error(_('An error has occured while contacting the server: %s' % e)) sys.exit(1) - admin_str = admin_token.read() - admin_obj = json.loads(admin_str) + + try: + admin_obj = admin_token.json() + except sje.JSONDecodeError: + self.session.close() + error(_('Incorrect server response. Expected a JSON string')) + return (1, None, None) + if admin_obj['prefered_protocol'] in supported_protocols: prefered_protocol = admin_obj['prefered_protocol'] else: + self.session.close() error(_('Wrong version, server incapable of handling your client')) return (1, None, None) admin = admin_obj['token'] if not admin_token_file == '' : self.write_admin_token(smoonURL,admin,admin_token_file) + return (0, pub_uuid, admin) +# end of _HardwareProfile.send() + + def regenerate_pub_uuid(self, uuiddb, uuid, user_agent=user_agent, smoonURL=smoonURL, timeout=timeout): - grabber = urlgrabber.grabber.URLGrabber(user_agent=user_agent, timeout=timeout) try: - new_uuid = grabber.urlopen(urljoin(smoonURL + "/", '/client/regenerate_pub_uuid?uuid=%s' % self.host.UUID)) - except urlgrabber.grabber.URLGrabError, e: - raise ServerError, str(e) + new_uuid = self.session.get(smoonURL + 'client/regenerate_pub_uuid?uuid=%s' % self.host.UUID, + proxies=proxies, timeout=timeout) + except EXCEPTIONS as e: + raise ServerError(str(e)) - response = new_uuid.read() # Either JSON or an error page in (X)HTML try: - response_dict = json.loads(response) - except Exception, e: - serverMessage(response) - raise ServerError, _('Reply from server could not be interpreted') + response_dict = new_uuid.json() # Either JSON or an error page in (X)HTML + except Exception as e: + self.session.close() + serverMessage(new_uuid.text) + raise ServerError(_('Reply from server could not be interpreted')) else: try: pub_uuid = response_dict['pub_uuid'] except KeyError: - raise ServerError, _('Reply from server could not be interpreted') + self.session.close() + raise ServerError(_('Reply from server could not be interpreted')) self.write_pub_uuid(uuiddb, smoonURL, pub_uuid, uuid) return pub_uuid @@ -926,7 +967,7 @@ def deviceIter(self): def read_cpuinfo(): def get_entry(a, entry): e = entry.lower() - if not a.has_key(e): + if e not in a: return "" return a[e] @@ -1120,7 +1161,8 @@ def get_entry(a, entry): if not os.access("/proc/openprom/banner-name", os.R_OK): system = 'Unknown' if os.access("/proc/openprom/banner-name", os.R_OK): - system = open("/proc/openprom/banner-name", "r").read() + with open("/proc/openprom/banner-name", "r") as banner_name: + banner_name.read() hwdict['platform'] = uname hwdict['count'] = get_entry(tmpdict, 'ncpus probed') hwdict['model'] = get_entry(tmpdict, 'cpu') @@ -1166,7 +1208,8 @@ def get_entry(a, entry): # assume that the rest of the CPUs are the same. if os.path.exists('/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq'): - hwdict['speed'] = int(file('/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq').read().strip()) / 1000 + with open('/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq') as cpu_m_freq: + hwdict['speed'] = int(cpu_m_freq.read().strip()) / 1000 # This whole things hurts a lot. return hwdict @@ -1191,13 +1234,14 @@ def read_memory_2_4(): if not os.access("/proc/meminfo", os.R_OK): return {} - meminfo = open("/proc/meminfo", "r").read() + with open("/proc/meminfo", "r") as m_info: + meminfo = m_info.read() lines = meminfo.split("\n") curline = lines[1] memlist = curline.split() memdict = {} memdict['class'] = "MEMORY" - megs = int(long(memlist[1])/(1024*1024)) + megs = long(memlist[1])/(1024*1024) if megs < 32: megs = megs + (4 - (megs % 4)) else: @@ -1206,14 +1250,15 @@ def read_memory_2_4(): curline = lines[2] memlist = curline.split() # otherwise, it breaks on > ~4gigs of swap - megs = int(long(memlist[1])/(1024*1024)) + megs = long(memlist[1])/(1024*1024) memdict['swap'] = str(megs) return memdict def read_memory_2_6(): if not os.access("/proc/meminfo", os.R_OK): return {} - meminfo = open("/proc/meminfo", "r").read() + with open("/proc/meminfo", "r") as m_info: + meminfo = m_info.read() lines = meminfo.split("\n") dict = {} for line in lines: @@ -1253,7 +1298,7 @@ def create_profile_nocatch(gate, uuid): def create_profile(gate, uuid): try: return create_profile_nocatch(gate, uuid) - except SystemBusError, e: + except SystemBusError as e: error(_('Error:') + ' ' + e.msg) if e.hint is not None: error('\t' + _('Hint:') + ' ' + e.hint) @@ -1261,39 +1306,37 @@ def create_profile(gate, uuid): ##This is another def get_profile_link(smoonURL, pub_uuid): - return urljoin(smoonURL, '/client/show/%s' % pub_uuid) + return smoonURL + 'client/show/%s' % pub_uuid def read_uuid(): try: - UUID = file(hw_uuid_file).read().strip() + with open(hw_uuid_file) as hw_uuid: + UUID = hw_uuid.read().strip() except IOError: try: - UUID = file('/proc/sys/kernel/random/uuid').read().strip() - try: - file(hw_uuid_file, 'w').write(UUID) - except Exception, e: - raise UUIDError, 'Unable to save UUID to %s. Please run once as root.' % hw_uuid_file + with open('/proc/sys/kernel/random/uuid') as rand_uuid: + UUID = rand_uuid.read().strip() + rand_uuid.write(UUID) except IOError: sys.stderr.write(_('Unable to determine UUID of system!\n')) - raise UUIDError, 'Could not determine UUID of system!\n' + raise UUIDError('Unable to get/save UUID. file = %s. Please run once as root.' % hw_uuid_file) return UUID def read_pub_uuid(uuiddb, uuid, user_agent=user_agent, smoonURL=smoonURL, timeout=timeout, silent=False): - smoonURLparsed=urlparse(smoonURL) - res = uuiddb.get_pub_uuid(uuid, smoonURLparsed[1]) - if res: - return res - - grabber = urlgrabber.grabber.URLGrabber(user_agent=user_agent, timeout=timeout, proxies=proxies) - try: - o = grabber.urlopen(urljoin(smoonURL + "/", '/client/pub_uuid/%s' % uuid)) - pudict = json.loads(o.read()) - o.close() - uuiddb.set_pub_uuid(uuid, smoonURLparsed[1], pudict["pub_uuid"]) - return pudict["pub_uuid"] - except Exception, e: - if not silent: - error(_('Error determining public UUID: %s') % e) - sys.stderr.write(_("Unable to determine Public UUID! This could be a network error or you've\n")) - sys.stderr.write(_("not submitted your profile yet.\n")) - raise PubUUIDError, 'Could not determine Public UUID!\n' + smoonURLparsed=urlparse(smoonURL) + res = uuiddb.get_pub_uuid(uuid, smoonURLparsed.netloc) + if res: + return res + + try: + o = requests.get(smoonURL + 'client/pub_uuid?uuid=%s' % uuid, + proxies=proxies, timeout=timeout) + pudict = o.json() + uuiddb.set_pub_uuid(uuid, smoonURLparsed.netloc, pudict["pub_uuid"]) + return pudict["pub_uuid"] + except Exception as e: + if not silent: + error(_('Error determining public UUID: %s') % e) + sys.stderr.write(_("Unable to determine Public UUID! This could be a network error or you've\n")) + sys.stderr.write(_("not submitted your profile yet.\n")) + raise PubUUIDError('Could not determine Public UUID!\n') diff --git a/mythtv/programs/scripts/hardwareprofile/software.py b/mythtv/programs/scripts/hardwareprofile/software.py index b89ad58a1c4..53ec59084d7 100644 --- a/mythtv/programs/scripts/hardwareprofile/software.py +++ b/mythtv/programs/scripts/hardwareprofile/software.py @@ -17,8 +17,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +from __future__ import print_function import os -import commands +import subprocess import re import sys import smolt_config @@ -27,7 +28,7 @@ def read_lsb_release(): if os.access('/usr/bin/lsb_release', os.X_OK): - return commands.getstatusoutput('/usr/bin/lsb_release')[1].strip() + return subprocess.getstatusoutput('/usr/bin/lsb_release')[1].strip() return '' initdefault_re = re.compile(r':(\d+):initdefault:') @@ -35,15 +36,16 @@ def read_lsb_release(): def read_runlevel(): defaultRunlevel = '9' try: - inittab = file('/etc/inittab').read() + with open('/etc/inittab') as i_tab: + inittab = i_tab.read() match = initdefault_re.search(inittab) if match: defaultRunlevel = match.group(1) except IOError: - try: - defaultRunlevel = commands.getstatusoutput('/sbin/runlevel')[1].split()[1].strip() - except: - sys.stderr.write(_('Cannot Determine Runlevel')) + try: + defaultRunlevel = subprocess.getstatusoutput('/sbin/runlevel')[1].split()[1].strip() + except: + sys.stderr.write(_('Cannot Determine Runlevel')) return defaultRunlevel.strip() def read_os(): @@ -55,5 +57,5 @@ def read_os(): 'Run level':read_runlevel(), 'OS':read_os(), } - for k, v in dict.items(): - print '%s: "%s"' % (k, v) + for k, v in list(dict.items()): + print('%s: "%s"' % (k, v)) diff --git a/mythtv/programs/scripts/hardwareprofile/uuiddb.py b/mythtv/programs/scripts/hardwareprofile/uuiddb.py index 10d80b46825..c24c929d43a 100644 --- a/mythtv/programs/scripts/hardwareprofile/uuiddb.py +++ b/mythtv/programs/scripts/hardwareprofile/uuiddb.py @@ -16,7 +16,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -import ConfigParser +from future import standard_library +standard_library.install_aliases() +from builtins import object +import configparser import logging import os @@ -27,10 +30,10 @@ def _get_option_name(hw_uuid, host): return '%s__%s' % (hw_uuid, host) -class _UuidDb: +class _UuidDb(object): def __init__(self, database_filename): self._database_filename = database_filename - self._config = ConfigParser.RawConfigParser() + self._config = configparser.RawConfigParser() self._config.read(self._database_filename) if not self._config.has_section(_SECTION): self._config.add_section(_SECTION) @@ -39,7 +42,7 @@ def _flush(self): try: smolt_user_config_dir = os.path.expanduser('~/.smolt/') if not os.path.exists(smolt_user_config_dir): - os.mkdir(smolt_user_config_dir, 0700) + os.mkdir(smolt_user_config_dir, 0o700) f = open(self._database_filename, 'w') self._config.write(f) f.close() @@ -51,7 +54,7 @@ def get_pub_uuid(self, hw_uuid, host): pub_uuid = self._config.get(_SECTION, _get_option_name(hw_uuid, host)) logging.info('Public UUID "%s" read from database' % pub_uuid) return pub_uuid - except ConfigParser.NoOptionError: + except configparser.NoOptionError: return None def set_pub_uuid(self, hw_uuid, host, pub_uuid):