def _limits(self): """ Parses /proc/<pid>/limits and returns an AttrDict """ fields = { 'Max cpu time': 'cpu', 'Max file size': 'fsize', 'Max data size': 'data', 'Max stack size': 'stack', 'Max core file size': 'core', 'Max resident set': 'rss', 'Max processes': 'nproc', 'Max open files': 'nofile', 'Max locked memory': 'memlock', 'Max address space': 'as', 'Max file locks': 'locks', 'Max pending signals': 'sigpending', 'Max msgqueue size': 'msgqueue', 'Max nice priority': 'nice', 'Max realtime priority': 'rtprio', 'Max realtime timeout': 'rttime', } with open("limits", opener=self._opener, encoding="utf-8") as file: data = re.findall( r'^(.*?)\s{2,}(\S+)\s{2,}(\S+)\s{2,}', file.read().replace('unlimited', '-1'), re.MULTILINE) return AttrDict({ fields[k]: AttrDict(zip(('soft', 'hard'), map(int, v))) for (k, *v) in data})
def mountinfo(self): """ Parses /proc/<pid>/mountinfo and returns a list of AttrDict's """ fields = ('mnt_id', 'parent_id', 'major', 'minor', 'root', 'mount', 'options', 'optional', 'fstype', 'source', 'super_options') with open("mountinfo", opener=self._opener) as file: lines = file.read().splitlines() regex = r'(\S+) (\S+) (\d+):(\d+) (\S+) (\S+) (\S+) (.*? - )(\S+) (\S+) (\S+)' entries = [ AttrDict(zip(fields, re.findall(regex, _)[0])) for _ in lines ] for entry in entries: entry.update( mount=Pathname(entry.mount), optional=AttrDict([ _.split(':') for _ in entry.optional[:-len(" - ")].split() ]), options=AttrDict({ k: try_int(v[0]) if v else None for k, *v in [_.split('=', 1) for _ in entry.options.split(',')] }), super_options=AttrDict({ k: try_int(v[0]) if v else None for k, *v in [_.split('=', 1) for _ in entry.super_options.split(',')] })) return entries
def _parser1(self, path): """ Parse /proc/net/{netstat,snmp} """ with open(path, opener=self._opener, encoding="utf-8") as file: lines = file.read().splitlines() headers, values = lines[::2], lines[1::2] return AttrDict({ keys.split()[0][:-1]: AttrDict(zip(keys.split()[1:], map(int, vals.split()[1:]))) for keys, vals in zip(headers, values)})
def _cgroups(self): """ Parses /proc/cgroup and returns an AttrDict """ with open("cgroups", opener=self._opener, encoding="utf-8") as file: header, *lines = file.read().splitlines() keys = header.split()[1:] return AttrDict({ k: AttrDict(zip(keys, map(int, values))) for _ in lines for k, *values in [_.split()]})
def _crypto(self): """ Parses /proc/crypto and returns an AttrDict """ with open("crypto", opener=self._opener, encoding="utf-8") as file: info = file.read().strip().split('\n\n') return AttrDict({ line1.split(':')[1].strip(): AttrDict({ k.strip(): v.strip() for k, v in [_.split(':') for _ in lines]}) for item in info for line1, *lines in [item.splitlines()]})
def _dev(self): """ Parse /proc/net/dev """ with open("net/dev", opener=self._opener, encoding="utf-8") as file: _, line2, *lines = file.read().splitlines() rx, tx = line2.split('|')[1:] keys = ['RX_%s' % _ for _ in rx.split()] + ['TX_%s' % _ for _ in tx.split()] return AttrDict({ iface[:-1]: AttrDict(zip(keys, map(int, values))) for _ in lines for iface, *values in [_.split()]})
def status(self): """ Parses /proc/<pid>/status and returns an AttrDict """ fields = ('real', 'effective', 'saved_set', 'filesystem') with open("status", opener=self._opener) as file: lines = file.read().splitlines() status = AttrDict( {k: try_int(v) for k, v in [_.split(':\t', 1) for _ in lines]}) status.update({ 'Uid': AttrDict(zip(fields, map(Uid, status.Uid.split()))), 'Gid': AttrDict(zip(fields, map(Gid, status.Gid.split()))), 'Groups': list(map(Gid, str(status.Groups).split())) }) status.update({ k: int(status[k].replace('kB', '').strip()) for k in ('HugetlbPages', 'RssAnon', 'RssFile', 'RssShmem', 'VmData', 'VmExe', 'VmHWM', 'VmLck', 'VmLib', 'VmPeak', 'VmPin', 'VmPMD', 'VmPTE', 'VmRSS', 'VmSize', 'VmStk', 'VmSwap') if k in status }) return status
def _io(self): """ Parses /proc/<pid>/io and returns an AttrDict """ with open("io", opener=self._opener, encoding="utf-8") as file: lines = file.read().splitlines() return AttrDict({k: int(v) for k, v in [_.split(': ') for _ in lines]})
def _numa_maps(self): # pylint: disable=star-needs-assignment-target # Make Pylint happy on Python 3.4 """ Parses /proc/<pid>/numa_maps and returns an AttrDict """ with open("numa_maps", opener=self._opener, encoding="utf-8") as file: lines = file.read().splitlines() entry = AttrDict({ address: AttrDict({ k: try_int(v[0]) if v else None for k, *v in [_.split('=', 1) for _ in ['policy=%s' % policy] + values]}) for line in lines for address, policy, *values in [line.split()]}) for key in entry: if 'file' in entry[key]: entry[key].update(file=Pathname(entry[key].file)) return entry
def _config(self): """ Parses /proc/config.gz and returns an AttrDict If /proc/config.gz doesn't exist, try /boot or /lib/modules/ """ lines = None paths = [ "config.gz", "/boot/config-%s" % os.uname().release, "/lib/modules/%s/build/.config" % os.uname().release ] for path in paths: try: os.stat(path, dir_fd=self._dir_fd) except FileNotFoundError: continue if path.endswith(".gz"): with open(path, "rb", opener=self._opener) as f: with gzip.open(f) as file: lines = file.read().decode('utf-8').splitlines() else: with open(path, encoding="utf-8") as file: lines = file.read().splitlines() break if lines is None: return None return AttrDict(_.split('=') for _ in lines if _.startswith("CONFIG_"))
def snmp6(self): """ Parse /proc/net/snmp6 """ with open("net/snmp6", opener=self._opener) as file: lines = file.read().splitlines() return AttrDict({k: int(v) for _ in lines for k, v in [_.split()]})
def _vmstat(self): """ Parses /proc/vmstat and returns an AttrDict """ with open("vmstat", opener=self._opener, encoding="utf-8") as file: lines = file.read().splitlines() return AttrDict({k: int(v) for k, v in [_.split() for _ in lines]})
def _meminfo(self): """ Parses /proc/meminfo and returns an AttrDict """ with open("meminfo", opener=self._opener, encoding="utf-8") as file: lines = file.read().replace('kB\n', '\n').splitlines() return AttrDict({k: int(v.strip()) for k, v in [_.split(':') for _ in lines]})
def _dev_mcast(self): """ Parse /proc/net/dev_mcast """ fields = ('index', 'interface', 'dmi_u', 'dmi_g', 'dmi_address') with open("net/dev_mcast", opener=self._opener, encoding="utf-8") as file: lines = file.read().splitlines() return [AttrDict(zip(fields, _.split())) for _ in lines]
def _statm(self): """ Parses /proc/<pid>/statm and returns an AttrDict """ fields = ('size', 'resident', 'shared', 'text', 'lib', 'data', 'dt') with open("statm", opener=self._opener, encoding="utf-8") as file: data = map(int, file.read().split()) return AttrDict(zip(fields, data))
def _locks(self): """ Parses /proc/locks and returns a list of AttrDict's """ fields = ('type', 'xtype', 'mode', 'pid', 'major', 'minor', 'inode', 'start', 'end') with open("locks", opener=self._opener, encoding="utf-8") as file: data = file.read() return [AttrDict(zip(fields, _.replace(':', ' ').split()[1:])) for _ in data.splitlines()]
def _mounts(self): """ Parses /proc/<pid>/mounts and returns a list of AttrDict's """ fields = ('spec', 'file', 'vfstype', 'mntops', 'freq', 'passno') with open("mounts", opener=self._opener, encoding="utf-8") as file: lines = file.read().splitlines() entries = [ AttrDict(zip(fields, re.findall(r'^(\S+) (.*?) (\S+) (\S+) (\d+) (\d+)$', _)[0])) for _ in lines] for entry in entries: entry.update( file=Pathname(entry.file), mntops=AttrDict({ k: try_int(v[0]) if v else None for k, *v in [_.split('=', 1) for _ in entry.mntops.split(',')]})) return entries
def _environ(self): """ Parses /proc/<pid>/environ and returns an AttrDict """ with open("environ", "rb", opener=self._opener) as file: data = file.read() try: return AttrDict([_.split('=', 1) for _ in data.decode('utf-8')[:-1].split('\0')]) except (UnicodeDecodeError, ValueError): return None
def _route(self): """ Parse /proc/net/route """ with open("net/route", opener=self._opener, encoding="utf-8") as file: header, *lines = file.read().splitlines() entries = [AttrDict(zip(header.split(), _.split())) for _ in lines] for entry in entries: entry.update({k: IPAddr(entry[k]) for k in ('Destination', 'Gateway', 'Mask')}) return entries
def _swaps(self): """ Parses /proc/swaps and returns a list of AttrDict's """ with open("swaps", opener=self._opener, encoding="utf-8") as file: keys, *values = file.read().splitlines() entries = [AttrDict(zip(keys.split(), _.rsplit(maxsplit=5))) for _ in values] for entry in entries: entry.update(Filename=Pathname(entry.Filename)) return entries
def _unix(self): """ Parse /proc/net/unix """ with open("net/unix", opener=self._opener, encoding="utf-8") as file: keys, *lines = file.read().splitlines() # Ignore "Num" entries = [AttrDict(zip_longest(keys.split()[1:], _.split(maxsplit=7)[1:])) for _ in lines] for entry in entries: entry.update(Path=Pathname(entry.Path)) return entries
def test_CustomJSONEncoder(self): d = { 'time': Time(0.0), 'uid': Uid(0), 'gid': Gid(0), 'ip': IPAddr('0' * 8), 'path': Pathname("/etc") } s = '{"gid": 0, "ip": "0.0.0.0", "path": "/etc", "time": "Thu Jan 1 00:00:00 1970", "uid": 0}' self.assertEqual( s, json.dumps(AttrDict(d), cls=CustomJSONEncoder, sort_keys=True))
def _xarp(self, path): """ Parse /proc/net/{arp,rarp} """ with open(path, opener=self._opener, encoding="utf-8") as file: header, *lines = file.read().splitlines() keys = [_.strip().replace(' ', '_') for _ in header.split(' ') if _] entries = [AttrDict(zip(keys, _.split())) for _ in lines] for entry in entries: entry.update(IP_address=IPAddr(entry.IP_address)) return entries
def smaps(self): """ Parses /proc/<pid>/smaps and returns a list of AttrDict's """ with open("smaps", opener=self._opener) as file: lines = file.read().replace('kB\n', '\n').splitlines() step = int(len(lines) / len(self.maps)) maps = [{ k: try_int(v.strip()) if k != "VmFlags" else v.strip().split() for k, v in [_.split(':') for _ in lines[i + 1:i + step]] } for i in range(0, len(lines), step)] return [AttrDict(**a, **b) for a, b in zip(maps, self.maps)]
def stat(self): """ Parses /proc/<pid>/stat and returns an AttrDict """ fields = ( 'pid comm state ppid pgrp session tty_nr tpgid flags ' 'minflt cminflt majflt cmajflt utime stime cutime cstime ' 'priority nice num_threads itrealvalue starttime vsize rss rsslim ' 'startcode endcode startstack kstkesp kstkeip signal blocked ' 'sigignore sigcatch wchan nswap cnswap exit_signal processor ' 'rt_priority policy delayacct_blkio_ticks guest_time cguest_time ' 'start_data end_data start_brk arg_start arg_end env_start env_end ' 'exit_code').split() with open("stat", opener=self._opener) as file: data = re.findall(r"\(.*\)|\S+", file.read()[:-1], re.M | re.S) info = AttrDict(zip(fields, data)) # Remove parentheses info.comm = info.comm[1:-1] # Escape newlines info.comm = info.comm.replace("\n", "\\n") return info
def _sysvipc(self, path): """ Parses /proc/sysvipc/{msg,sem,shm} and returns a list of AttrDict's """ with open(os.path.join("sysvipc", path), opener=self._opener, encoding="utf-8") as file: keys, *values = file.read().splitlines() entries = [AttrDict(zip(keys.split(), _.split())) for _ in values] for entry in entries: entry.update({k: Time(entry[k]) for k in entry if k.endswith('time')}) entry.update({k: Uid(entry[k]) for k in ('uid', 'cuid')}) entry.update({k: Gid(entry[k]) for k in ('gid', 'cgid')}) return entries
def _cpuinfo(self): """ Parses /proc/cpuinfo and returns a list of AttrDict's """ with open("cpuinfo", opener=self._opener, encoding="utf-8") as file: cpus = file.read()[:-1].split('\n\n') entries = [ AttrDict([map(str.strip, _.split(':')) for _ in cpu.splitlines()]) for cpu in cpus ] for entry in entries: entry.flags = set(entry.flags.split()) return entries
def _ipv6_route(self): """ Parse /proc/net/ipv6_route """ fields = ( 'dst_network', 'dst_prefixlen', 'src_network', 'src_prefixlen', 'next_hop', 'metric', 'refcnt', 'usecnt', 'flags', 'device') with open("net/ipv6_route", opener=self._opener, encoding="utf-8") as file: lines = file.read().splitlines() entries = [AttrDict(zip(fields, _.split())) for _ in lines] for entry in entries: entry.update({ k: IPAddr(entry[k], big_endian=False) for k in ('dst_network', 'src_network', 'next_hop')}) entry.update({ k: int(entry[k], base=16) for k in ('dst_prefixlen', 'src_prefixlen', 'metric', 'refcnt', 'usecnt', 'flags')}) return entries
def _proto(self, path): """ Parse /proc/net/{icmp,icmp6,raw,raw6,tcp,tcp6,udp,udp6,udplite,udplite6} """ fields = ( 'local_address', 'local_port', 'remote_address', 'remote_port', 'st', 'tx_queue', 'rx_queue', 'tr', 'tm_when', 'retrnsmt', 'uid', 'timeout', 'inode', 'ref', 'pointer', 'drops') with open(path, opener=self._opener, encoding="utf-8") as file: _, *lines = file.read().splitlines() entries = [AttrDict(zip(fields, _.replace(':', ' ').split()[1:])) for _ in lines] for entry in entries: entry.update( local_address=IPAddr(entry.local_address), remote_address=IPAddr(entry.remote_address), local_port=int(entry.local_port, base=16), remote_port=int(entry.remote_port, base=16), uid=Uid(entry.uid)) return entries
def test_AttrDict(self): d = AttrDict({'a': 1}) self.assertIsInstance(d, AttrDict) self.assertIs(d.a, d['a']) del d.a self.assertEqual(d, {}) d['b'] = 2 self.assertIs(d.b, d['b']) del d['b'] self.assertEqual(d, {}) self.assertIsNone(d.get('a', None)) self.assertEqual(d.get('a', 777), 777) _d = {'a': 888} d.update(_d) self.assertEqual(d, _d)