aboutsummaryrefslogblamecommitdiffstats
path: root/src/plugins/cpuinfo.py
blob: 8a11fdd990e1761f03a6f2d00979ac9837e80ba3 (plain) (tree)
1
2
3
4


                                               
                                                                            









































































































































                                                                                                  
# -*- python -*-
'''
xpybar – xmobar replacement written in python
Copyright © 2014, 2015, 2016, 2017, 2018  Mattias Andrée (maandree@kth.se)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''


class CPUInfo: # TODO enable setting scaling
    '''
    Data from /proc/cpuinfo and /sys/devices/system/cpu
    
    @variable  cpus:list<dict<str, str>>  Information about each CPU
    '''
    
    
    BIOS_FREQUENCY_LIMIT = 'cpufreq/bios_limit'
    '''
    CPU frequency limit per BIOS, in kHz
    
    @mapping  int
    '''
    
    SCALING_GOVERNOR = 'cpufreq/scaling_governor'
    '''
    CPU frequency scaling governor
    
    @mapping  str
    '''
    
    CPU_TRANSITION_LATENCY = 'cpufreq/cpuinfo_transition_latency'
    '''
    CPU transition latency, in ns
    
    @mapping  int
    '''
    
    AVAILABLE_FREQUENCIES = 'cpufreq/scaling_available_frequencies'
    '''
    Available CPU scaling frequencies, in kHz
    
    @mapping  itr<int>
    '''
    
    SCALING_DRIVER = 'cpufreq/scaling_driver'
    '''
    CPU frequency scaling driver
    
    @mapping  str
    '''
    
    AVAILABLE_SCALING_GOVERNORS = 'cpufreq/scaling_available_governors'
    '''
    Available CPU frequency scaling governor
    
    @mapping  itr<str>
    '''
    
    CURRENT_FREQUENCY = 'cpufreq/cpuinfo_cur_freq'
    MINIMUM_FREQUENCY = 'cpufreq/cpuinfo_min_freq'
    MAXIMUM_FREQUENCY = 'cpufreq/cpuinfo_max_freq'
    CURRENT_SCALING_FREQUENCY = 'cpufreq/scaling_cur_freq'
    MINIMUM_SCALING_FREQUENCY = 'cpufreq/scaling_min_freq'
    MAXIMUM_SCALING_FREQUENCY = 'cpufreq/scaling_max_freq'
    # TODO more CPU info
    #'cpufreq/affected_cpus'
    #'cpufreq/related_cpus'
    #'cpufreq/scaling_setspeed'
    #cache/
    #power/
    #topology/
    #thermal_throttle
    #/sys/devices/system/cpu/cpufreq/
    #/sys/devices/system/cpu/cpuidle/
    #/sys/devices/system/cpu/power/
    
    
    
    def __init__(self):
        '''
        Constructor
        '''
        cpuinfo = None
        with open('/proc/cpuinfo', 'rb') as file:
            cpuinfo = file.read()
        cpuinfo = cpuinfo.decode('utf-8', 'replace').replace('\t', '')
        cpuinfo = filter(lambda cpu : not cpu == '', cpuinfo.split('\n\n'))
        
        def f(line):
            cols = line.split(': ')
            key, value = cols[0].replace('_', ' '), ': '.join(cols[1:])
            return (key, value)
        self.cpus = [dict(f(line) for line in cpu.split('\n') if ': ' in line) for cpu in cpuinfo]
    
    
    def __contains__(self, key):
        '''
        Get whether or not a key is available for any CPU
        
        @param   key:str  The key
        @return  :bool    The availability
        '''
        return any(map(key in self.cpus, self.cpus))
    
    
    def __getitem__(self, key):
        '''
        Look up a field from '/proc/cpuinfo' for each CPU
        
        @param   key:str      The key
        @return  :list<str?>  The value associated with the key for each CPU, `None` where missing
        '''
        return [cpu[key] if key in cpu else None for cpu in self.cpus]
    
    
    def get(self, cpu, data):
        '''
        Read a information from sysfs for a CPU
        
        @param   cpu:int   The index of the CPU
        @param   data:str  The file inside the CPU's directory
        @return  :str      The content of the file
        '''
        if data == CPUInfo.CURRENT_FREQUENCY:
            return str(int(float(self['cpu MHz'][cpu]) * 1000))
        path = '/sys/devices/system/cpu/cpu%i/%s' % (cpu, data)
        with open(path, 'rb') as file:
            cont = file.read().decode('utf-8', 'replace').rstrip('\n')
        return cont