OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 |
| 3 # This Source Code Form is subject to the terms of the Mozilla Public |
| 4 # License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| 5 # You can obtain one at http://mozilla.org/MPL/2.0/. |
| 6 |
| 7 """ |
| 8 file for interface to transform introspected system information to a format |
| 9 pallatable to Mozilla |
| 10 |
| 11 Information: |
| 12 - os : what operating system ['win', 'mac', 'linux', ...] |
| 13 - bits : 32 or 64 |
| 14 - processor : processor architecture ['x86', 'x86_64', 'ppc', ...] |
| 15 - version : operating system version string |
| 16 |
| 17 For windows, the service pack information is also included |
| 18 """ |
| 19 |
| 20 # TODO: it might be a good idea of adding a system name (e.g. 'Ubuntu' for |
| 21 # linux) to the information; I certainly wouldn't want anyone parsing this |
| 22 # information and having behaviour depend on it |
| 23 |
| 24 import os |
| 25 import platform |
| 26 import re |
| 27 import sys |
| 28 |
| 29 # keep a copy of the os module since updating globals overrides this |
| 30 _os = os |
| 31 |
| 32 class unknown(object): |
| 33 """marker class for unknown information""" |
| 34 def __nonzero__(self): |
| 35 return False |
| 36 def __str__(self): |
| 37 return 'UNKNOWN' |
| 38 unknown = unknown() # singleton |
| 39 |
| 40 # get system information |
| 41 info = {'os': unknown, |
| 42 'processor': unknown, |
| 43 'version': unknown, |
| 44 'bits': unknown } |
| 45 (system, node, release, version, machine, processor) = platform.uname() |
| 46 (bits, linkage) = platform.architecture() |
| 47 |
| 48 # get os information and related data |
| 49 if system in ["Microsoft", "Windows"]: |
| 50 info['os'] = 'win' |
| 51 # There is a Python bug on Windows to determine platform values |
| 52 # http://bugs.python.org/issue7860 |
| 53 if "PROCESSOR_ARCHITEW6432" in os.environ: |
| 54 processor = os.environ.get("PROCESSOR_ARCHITEW6432", processor) |
| 55 else: |
| 56 processor = os.environ.get('PROCESSOR_ARCHITECTURE', processor) |
| 57 system = os.environ.get("OS", system).replace('_', ' ') |
| 58 service_pack = os.sys.getwindowsversion()[4] |
| 59 info['service_pack'] = service_pack |
| 60 elif system == "Linux": |
| 61 (distro, version, codename) = platform.dist() |
| 62 version = "%s %s" % (distro, version) |
| 63 if not processor: |
| 64 processor = machine |
| 65 info['os'] = 'linux' |
| 66 elif system in ['DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD']: |
| 67 info['os'] = 'bsd' |
| 68 version = sys.platform |
| 69 elif system == "Darwin": |
| 70 (release, versioninfo, machine) = platform.mac_ver() |
| 71 version = "OS X %s" % release |
| 72 info['os'] = 'mac' |
| 73 elif sys.platform in ('solaris', 'sunos5'): |
| 74 info['os'] = 'unix' |
| 75 version = sys.platform |
| 76 info['version'] = version # os version |
| 77 |
| 78 # processor type and bits |
| 79 if processor in ["i386", "i686"]: |
| 80 if bits == "32bit": |
| 81 processor = "x86" |
| 82 elif bits == "64bit": |
| 83 processor = "x86_64" |
| 84 elif processor.upper() == "AMD64": |
| 85 bits = "64bit" |
| 86 processor = "x86_64" |
| 87 elif processor == "Power Macintosh": |
| 88 processor = "ppc" |
| 89 bits = re.search('(\d+)bit', bits).group(1) |
| 90 info.update({'processor': processor, |
| 91 'bits': int(bits), |
| 92 }) |
| 93 |
| 94 # standard value of choices, for easy inspection |
| 95 choices = {'os': ['linux', 'bsd', 'win', 'mac', 'unix'], |
| 96 'bits': [32, 64], |
| 97 'processor': ['x86', 'x86_64', 'ppc']} |
| 98 |
| 99 |
| 100 def sanitize(info): |
| 101 """Do some sanitization of input values, primarily |
| 102 to handle universal Mac builds.""" |
| 103 if "processor" in info and info["processor"] == "universal-x86-x86_64": |
| 104 # If we're running on OS X 10.6 or newer, assume 64-bit |
| 105 if release[:4] >= "10.6": # Note this is a string comparison |
| 106 info["processor"] = "x86_64" |
| 107 info["bits"] = 64 |
| 108 else: |
| 109 info["processor"] = "x86" |
| 110 info["bits"] = 32 |
| 111 |
| 112 # method for updating information |
| 113 def update(new_info): |
| 114 """update the info""" |
| 115 info.update(new_info) |
| 116 sanitize(info) |
| 117 globals().update(info) |
| 118 |
| 119 # convenience data for os access |
| 120 for os_name in choices['os']: |
| 121 globals()['is' + os_name.title()] = info['os'] == os_name |
| 122 # unix is special |
| 123 if isLinux or isBsd: |
| 124 globals()['isUnix'] = True |
| 125 |
| 126 update({}) |
| 127 |
| 128 # exports |
| 129 __all__ = info.keys() |
| 130 __all__ += ['is' + os_name.title() for os_name in choices['os']] |
| 131 __all__ += ['info', 'unknown', 'main', 'choices', 'update'] |
| 132 |
| 133 |
| 134 def main(args=None): |
| 135 |
| 136 # parse the command line |
| 137 from optparse import OptionParser |
| 138 parser = OptionParser(description=__doc__) |
| 139 for key in choices: |
| 140 parser.add_option('--%s' % key, dest=key, |
| 141 action='store_true', default=False, |
| 142 help="display choices for %s" % key) |
| 143 options, args = parser.parse_args() |
| 144 |
| 145 # args are JSON blobs to override info |
| 146 if args: |
| 147 try: |
| 148 from json import loads |
| 149 except ImportError: |
| 150 try: |
| 151 from simplejson import loads |
| 152 except ImportError: |
| 153 def loads(string): |
| 154 """*really* simple json; will not work with unicode""" |
| 155 return eval(string, {'true': True, 'false': False, 'null': N
one}) |
| 156 for arg in args: |
| 157 if _os.path.exists(arg): |
| 158 string = file(arg).read() |
| 159 else: |
| 160 string = arg |
| 161 update(loads(string)) |
| 162 |
| 163 # print out choices if requested |
| 164 flag = False |
| 165 for key, value in options.__dict__.items(): |
| 166 if value is True: |
| 167 print '%s choices: %s' % (key, ' '.join([str(choice) |
| 168 for choice in choices[key]]
)) |
| 169 flag = True |
| 170 if flag: return |
| 171 |
| 172 # otherwise, print out all info |
| 173 for key, value in info.items(): |
| 174 print '%s: %s' % (key, value) |
| 175 |
| 176 if __name__ == '__main__': |
| 177 main() |
OLD | NEW |