We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Reporting the wrong number of cores_total
Hi folks...

I think we are noticing a bug that comes from a misunderstanding of cpuinfos processor[N]."cpu_cores" value.

That value is not a count of cores per "cpu". Instead it is a count of the cores on the logical cpus parent package.

i.e. for 2x 6 core CPUs each cpu stanza (12 of them) should show "cpu cores : 6"
But there are not 12x6 cpus. There are 12.

In a big.little arch with 1x 4 core and 1x 2 core you'd see
processor       : 0
cpu cores       : 4
...
processor       : 1
cpu cores       : 4
...
processor       : 2
cpu cores       : 4
...
processor       : 3
cpu cores       : 4
...
processor       : 4
cpu cores       : 2
...
processor       : 5
cpu cores       : 2


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `insights/parsers/cpuinfo.py`
Content:
```
1 """
2 CpuInfo - file ``/proc/cpuinfo``
3 ================================
4 
5 This parser reads the content of the ``/proc/cpuinfo`` file and parses it
6 into a dictionary of lists, keyed on the left hand column of the cpuinfo
7 output.
8 
9 The object also provides properties for the standard information about the
10 CPU and motherboard architecture.
11 
12 Sample input::
13 
14     processor       : 0
15     vendor_id       : GenuineIntel
16     cpu family      : 6
17     model           : 45
18     model name      : Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz
19     stepping        : 2
20     microcode       : 1808
21     cpu MHz         : 2900.000
22     cache size      : 20480 KB
23     physical id     : 0
24     siblings        : 1
25     core id         : 0
26     cpu cores       : 1
27     apicid          : 0
28     flags           : fpu vme de pse tsc msr pae mce
29     address sizes   : 40 bits physical, 48 bits virtual
30     bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit
31 
32     processor       : 1
33     vendor_id       : GenuineIntel
34     cpu family      : 6
35     model           : 45
36     model name      : Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz
37     stepping        : 2
38     microcode       : 1808
39     cpu MHz         : 2900.000
40     cache size      : 20480 KB
41     physical id     : 2
42     siblings        : 1
43     core id         : 0
44     cpu cores       : 1
45     apicid          : 2
46     flags           : fpu vme de pse tsc msr pae mce
47     address sizes   : 40 bits physical, 48 bits virtual
48     bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit
49 
50 Examples:
51 
52     >>> cpu_info.cpu_count
53     2
54     >>> sorted(cpu_info.apicid)
55     ['0', '2']
56     >>> cpu_info.socket_count
57     2
58     >>> cpu_info.vendor
59     'GenuineIntel'
60     >>> "fpu" in cpu_info.flags
61     True
62     >>> cpu_info.model_name
63     'Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz'
64     >>> cpu_info.get_processor_by_index(0)['cpus']
65     '0'
66     >>> cpu_info.get_processor_by_index(0)['vendors']
67     'GenuineIntel'
68 """
69 
70 from collections import defaultdict
71 from .. import Parser, parser, defaults, get_active_lines, LegacyItemAccess
72 from insights.specs import Specs
73 
74 
75 @parser(Specs.cpuinfo)
76 class CpuInfo(LegacyItemAccess, Parser):
77     """
78     CpuInfo parser - able to be used as a dictionary through the
79     LegacyItemAccess mixin class.
80 
81     The following items are remapped into lists, with the element number
82     corresponding to the CPU.  For example, given the following input::
83 
84         processor       : 1
85         vendor_id       : GenuineIntel
86         cpu family      : 6
87         model           : 45
88         model name      : Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz
89         stepping        : 2
90         microcode       : 1808
91         cpu MHz         : 2900.000
92         cache size      : 20480 KB
93         physical id     : 2
94         siblings        : 1
95         core id         : 0
96         cpu cores       : 1
97         apicid          : 2
98         address sizes   : 40 bits physical, 48 bits virtual
99         bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit
100 
101     The following keys would be lists of:
102 
103     * **cpus** - the *processor* line (e.g. ``1``)
104     * **sockets** - the *physical id* line (e.g. ``2``)
105     * **vendors** - the *vendor_id* line (e.g. ``GenuineIntel``)
106     * **models** - the *model name* line (e.g. ``Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz``)
107     * **model_ids** - the *model* line (e.g. ``45``)
108     * **families** - the *cpu family* line (e.g. ``6``)
109     * **clockspeeds** - the *cpu MHz* line (e.g. ``2900.000``)
110     * **cache_sizes** - the *cache size* line (e.g. ``20480 KB``)
111     * **cpu_cores** - the *cpu cores* line (e.g. ``1``)
112     * **apicid** - the *apicid* line (e.g. ``1``)
113     * **stepping** - the *stepping* line (e.g. ``2``)
114     * **address_sizes** - the *address sizes* line (e.g. ``40 bits physical, 48 bits virtual``)
115     * **bugs** - the *bugs* line (e.g. ``cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit``)
116     """
117 
118     def parse_content(self, content):
119 
120         self.data = defaultdict(list)
121         mappings = {
122             "processor": "cpus",
123             "physical id": "sockets",
124             "vendor_id": "vendors",
125             "model name": "models",
126             "model": "model_ids",
127             "cpu family": "families",
128             "cpu MHz": "clockspeeds",
129             "cache size": "cache_sizes",
130             "cpu cores": "cpu_cores",
131             "apicid": "apicid",
132             "flags": "flags",
133             "stepping": "stepping",
134             "Features": "features",
135             "CPU implementer": "cpu_implementer",
136             "CPU architecture": "cpu_architecture",
137             "CPU variant": "cpu_variant",
138             "CPU part": "cpu_part",
139             "CPU revision": "cpu_revision",
140             "cpu": "cpu",
141             "revision": "revision",
142             "address sizes": "address_sizes",
143             "bugs": "bugs",
144             "apicid": "apicid"
145         }
146 
147         for line in get_active_lines(content, comment_char="COMMAND>"):
148             key, value = [p.strip() for p in line.split(":", 1)]
149             if key in mappings:
150                 self.data[mappings[key]].append(value)
151 
152         if "cpu" in self.data and "POWER" in self.data["cpu"][0]:
153             # this works differently than on x86 and is not per-cpu
154             del self.data["model_ids"]
155 
156         self.data = dict(self.data)
157 
158     def __iter__(self):
159         """
160         Iterating through this object will yield the ``get_processor_by_index``
161         information for each CPU.
162         """
163         for idx in range(len(self["cpus"])):
164             yield self.get_processor_by_index(idx)
165 
166     @property
167     @defaults()
168     def cpu_speed(self):
169         """
170         str: Returns the CPU speed of the first CPU.
171         """
172         return self.data["clockspeeds"][0]
173 
174     @property
175     @defaults()
176     def cache_size(self):
177         """
178         str: Returns the cache size of the first CPU.
179         """
180         return self.data["cache_sizes"][0]
181 
182     @property
183     @defaults()
184     def cpu_count(self):
185         """
186         str: Returns the number of CPUs.
187         """
188         return len(self.data.get("cpus", []))
189 
190     @property
191     @defaults()
192     def apicid(self):
193         """
194         str: Returns the apicid of the processor.
195         """
196         return self.data["apicid"]
197 
198     @property
199     @defaults()
200     def socket_count(self):
201         """
202         str: Returns the number of sockets.  This is distinct from the number
203         of CPUs.
204         """
205         return len(set(self.data.get("sockets", [])))
206 
207     @property
208     @defaults()
209     def model_name(self):
210         """
211         str: Returns the model name of the first CPU.
212         """
213         return self.data["models"][0]
214 
215     @property
216     @defaults()
217     def model_number(self):
218         """
219         str: Returns the model ID of the first CPU.
220         """
221         return self.data["model_ids"][0]
222 
223     @property
224     @defaults()
225     def flags(self):
226         """
227         list: Returns a list of feature flags for the first CPU.
228         """
229         return self.data["flags"][0].split()
230 
231     @property
232     @defaults()
233     def vendor(self):
234         """
235         str: Returns the vendor of the first CPU.
236         """
237         return self.data["vendors"][0]
238 
239     @property
240     @defaults()
241     def core_total(self):
242         """
243         str: Returns the total number of cores for the server if available, else None.
244         """
245         if self.data and 'cpu_cores' in self.data:
246             return sum([int(c) for c in self.data['cpu_cores']])
247         else:
248             return None
249 
250     def get_processor_by_index(self, index):
251         """
252         Construct a dictionary of the information stored for the given CPU.
253 
254         Parameters:
255             index (int): The CPU index to retrieve.
256 
257         Returns:
258             dict: A dictionary of the information for that CPU.
259         """
260         return dict((k, v[index]) for k, v in self.data.items())
261
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/insights/parsers/cpuinfo.py b/insights/parsers/cpuinfo.py
--- a/insights/parsers/cpuinfo.py
+++ b/insights/parsers/cpuinfo.py
@@ -240,10 +240,24 @@
     @defaults()
     def core_total(self):
         """
-        str: Returns the total number of cores for the server if available, else None.
+        int: Returns the total number of cores for the server if available, else None.
+
+        .. warning::
+            This function is deprecated.  Please use the
+            :py:class:`insights.parsers.lscpu.LsCPU` class attribute
+            ``info['Cores per socket']`` and ``info['Sockets']`` values instead.
         """
         if self.data and 'cpu_cores' in self.data:
-            return sum([int(c) for c in self.data['cpu_cores']])
+            # I guess we can't get this fancey on older versions of RHEL
+            # return sum({e['sockets']: int(e['cpu_cores']) for e in self}.values())
+            physical_dict = {}
+            for e in self:
+                # we should rename sockets here to physical_ids as cpuinfo
+                # has it there can be many physical_ids per socket
+                # see fgrep 'physical id' /proc/cpuinfo on a single
+                # package system
+                physical_dict[e['sockets']] = int(e['cpu_cores'])
+            return sum(physical_dict.values())
         else:
             return None

{"golden_diff": "diff --git a/insights/parsers/cpuinfo.py b/insights/parsers/cpuinfo.py\n--- a/insights/parsers/cpuinfo.py\n+++ b/insights/parsers/cpuinfo.py\n@@ -240,10 +240,24 @@\n     @defaults()\n     def core_total(self):\n         \"\"\"\n-        str: Returns the total number of cores for the server if available, else None.\n+        int: Returns the total number of cores for the server if available, else None.\n+\n+        .. warning::\n+            This function is deprecated.  Please use the\n+            :py:class:`insights.parsers.lscpu.LsCPU` class attribute\n+            ``info['Cores per socket']`` and ``info['Sockets']`` values instead.\n         \"\"\"\n         if self.data and 'cpu_cores' in self.data:\n-            return sum([int(c) for c in self.data['cpu_cores']])\n+            # I guess we can't get this fancey on older versions of RHEL\n+            # return sum({e['sockets']: int(e['cpu_cores']) for e in self}.values())\n+            physical_dict = {}\n+            for e in self:\n+                # we should rename sockets here to physical_ids as cpuinfo\n+                # has it there can be many physical_ids per socket\n+                # see fgrep 'physical id' /proc/cpuinfo on a single\n+                # package system\n+                physical_dict[e['sockets']] = int(e['cpu_cores'])\n+            return sum(physical_dict.values())\n         else:\n             return None\n", "issue": "Reporting the wrong number of cores_total\nHi folks...\r\n\r\nI think we are noticing a bug that comes from a misunderstanding of cpuinfos processor[N].\"cpu_cores\" value.\r\n\r\nThat value is not a count of cores per \"cpu\". Instead it is a count of the cores on the logical cpus parent package.\r\n\r\ni.e. for 2x 6 core CPUs each cpu stanza (12 of them) should show \"cpu cores : 6\"\r\nBut there are not 12x6 cpus. There are 12.\r\n\r\nIn a big.little arch with 1x 4 core and 1x 2 core you'd see\r\nprocessor       : 0\r\ncpu cores       : 4\r\n...\r\nprocessor       : 1\r\ncpu cores       : 4\r\n...\r\nprocessor       : 2\r\ncpu cores       : 4\r\n...\r\nprocessor       : 3\r\ncpu cores       : 4\r\n...\r\nprocessor       : 4\r\ncpu cores       : 2\r\n...\r\nprocessor       : 5\r\ncpu cores       : 2\r\n\n", "before_files": [{"content": "\"\"\"\nCpuInfo - file ``/proc/cpuinfo``\n================================\n\nThis parser reads the content of the ``/proc/cpuinfo`` file and parses it\ninto a dictionary of lists, keyed on the left hand column of the cpuinfo\noutput.\n\nThe object also provides properties for the standard information about the\nCPU and motherboard architecture.\n\nSample input::\n\n    processor       : 0\n    vendor_id       : GenuineIntel\n    cpu family      : 6\n    model           : 45\n    model name      : Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz\n    stepping        : 2\n    microcode       : 1808\n    cpu MHz         : 2900.000\n    cache size      : 20480 KB\n    physical id     : 0\n    siblings        : 1\n    core id         : 0\n    cpu cores       : 1\n    apicid          : 0\n    flags           : fpu vme de pse tsc msr pae mce\n    address sizes   : 40 bits physical, 48 bits virtual\n    bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit\n\n    processor       : 1\n    vendor_id       : GenuineIntel\n    cpu family      : 6\n    model           : 45\n    model name      : Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz\n    stepping        : 2\n    microcode       : 1808\n    cpu MHz         : 2900.000\n    cache size      : 20480 KB\n    physical id     : 2\n    siblings        : 1\n    core id         : 0\n    cpu cores       : 1\n    apicid          : 2\n    flags           : fpu vme de pse tsc msr pae mce\n    address sizes   : 40 bits physical, 48 bits virtual\n    bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit\n\nExamples:\n\n    >>> cpu_info.cpu_count\n    2\n    >>> sorted(cpu_info.apicid)\n    ['0', '2']\n    >>> cpu_info.socket_count\n    2\n    >>> cpu_info.vendor\n    'GenuineIntel'\n    >>> \"fpu\" in cpu_info.flags\n    True\n    >>> cpu_info.model_name\n    'Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz'\n    >>> cpu_info.get_processor_by_index(0)['cpus']\n    '0'\n    >>> cpu_info.get_processor_by_index(0)['vendors']\n    'GenuineIntel'\n\"\"\"\n\nfrom collections import defaultdict\nfrom .. import Parser, parser, defaults, get_active_lines, LegacyItemAccess\nfrom insights.specs import Specs\n\n\n@parser(Specs.cpuinfo)\nclass CpuInfo(LegacyItemAccess, Parser):\n    \"\"\"\n    CpuInfo parser - able to be used as a dictionary through the\n    LegacyItemAccess mixin class.\n\n    The following items are remapped into lists, with the element number\n    corresponding to the CPU.  For example, given the following input::\n\n        processor       : 1\n        vendor_id       : GenuineIntel\n        cpu family      : 6\n        model           : 45\n        model name      : Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz\n        stepping        : 2\n        microcode       : 1808\n        cpu MHz         : 2900.000\n        cache size      : 20480 KB\n        physical id     : 2\n        siblings        : 1\n        core id         : 0\n        cpu cores       : 1\n        apicid          : 2\n        address sizes   : 40 bits physical, 48 bits virtual\n        bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit\n\n    The following keys would be lists of:\n\n    * **cpus** - the *processor* line (e.g. ``1``)\n    * **sockets** - the *physical id* line (e.g. ``2``)\n    * **vendors** - the *vendor_id* line (e.g. ``GenuineIntel``)\n    * **models** - the *model name* line (e.g. ``Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz``)\n    * **model_ids** - the *model* line (e.g. ``45``)\n    * **families** - the *cpu family* line (e.g. ``6``)\n    * **clockspeeds** - the *cpu MHz* line (e.g. ``2900.000``)\n    * **cache_sizes** - the *cache size* line (e.g. ``20480 KB``)\n    * **cpu_cores** - the *cpu cores* line (e.g. ``1``)\n    * **apicid** - the *apicid* line (e.g. ``1``)\n    * **stepping** - the *stepping* line (e.g. ``2``)\n    * **address_sizes** - the *address sizes* line (e.g. ``40 bits physical, 48 bits virtual``)\n    * **bugs** - the *bugs* line (e.g. ``cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit``)\n    \"\"\"\n\n    def parse_content(self, content):\n\n        self.data = defaultdict(list)\n        mappings = {\n            \"processor\": \"cpus\",\n            \"physical id\": \"sockets\",\n            \"vendor_id\": \"vendors\",\n            \"model name\": \"models\",\n            \"model\": \"model_ids\",\n            \"cpu family\": \"families\",\n            \"cpu MHz\": \"clockspeeds\",\n            \"cache size\": \"cache_sizes\",\n            \"cpu cores\": \"cpu_cores\",\n            \"apicid\": \"apicid\",\n            \"flags\": \"flags\",\n            \"stepping\": \"stepping\",\n            \"Features\": \"features\",\n            \"CPU implementer\": \"cpu_implementer\",\n            \"CPU architecture\": \"cpu_architecture\",\n            \"CPU variant\": \"cpu_variant\",\n            \"CPU part\": \"cpu_part\",\n            \"CPU revision\": \"cpu_revision\",\n            \"cpu\": \"cpu\",\n            \"revision\": \"revision\",\n            \"address sizes\": \"address_sizes\",\n            \"bugs\": \"bugs\",\n            \"apicid\": \"apicid\"\n        }\n\n        for line in get_active_lines(content, comment_char=\"COMMAND>\"):\n            key, value = [p.strip() for p in line.split(\":\", 1)]\n            if key in mappings:\n                self.data[mappings[key]].append(value)\n\n        if \"cpu\" in self.data and \"POWER\" in self.data[\"cpu\"][0]:\n            # this works differently than on x86 and is not per-cpu\n            del self.data[\"model_ids\"]\n\n        self.data = dict(self.data)\n\n    def __iter__(self):\n        \"\"\"\n        Iterating through this object will yield the ``get_processor_by_index``\n        information for each CPU.\n        \"\"\"\n        for idx in range(len(self[\"cpus\"])):\n            yield self.get_processor_by_index(idx)\n\n    @property\n    @defaults()\n    def cpu_speed(self):\n        \"\"\"\n        str: Returns the CPU speed of the first CPU.\n        \"\"\"\n        return self.data[\"clockspeeds\"][0]\n\n    @property\n    @defaults()\n    def cache_size(self):\n        \"\"\"\n        str: Returns the cache size of the first CPU.\n        \"\"\"\n        return self.data[\"cache_sizes\"][0]\n\n    @property\n    @defaults()\n    def cpu_count(self):\n        \"\"\"\n        str: Returns the number of CPUs.\n        \"\"\"\n        return len(self.data.get(\"cpus\", []))\n\n    @property\n    @defaults()\n    def apicid(self):\n        \"\"\"\n        str: Returns the apicid of the processor.\n        \"\"\"\n        return self.data[\"apicid\"]\n\n    @property\n    @defaults()\n    def socket_count(self):\n        \"\"\"\n        str: Returns the number of sockets.  This is distinct from the number\n        of CPUs.\n        \"\"\"\n        return len(set(self.data.get(\"sockets\", [])))\n\n    @property\n    @defaults()\n    def model_name(self):\n        \"\"\"\n        str: Returns the model name of the first CPU.\n        \"\"\"\n        return self.data[\"models\"][0]\n\n    @property\n    @defaults()\n    def model_number(self):\n        \"\"\"\n        str: Returns the model ID of the first CPU.\n        \"\"\"\n        return self.data[\"model_ids\"][0]\n\n    @property\n    @defaults()\n    def flags(self):\n        \"\"\"\n        list: Returns a list of feature flags for the first CPU.\n        \"\"\"\n        return self.data[\"flags\"][0].split()\n\n    @property\n    @defaults()\n    def vendor(self):\n        \"\"\"\n        str: Returns the vendor of the first CPU.\n        \"\"\"\n        return self.data[\"vendors\"][0]\n\n    @property\n    @defaults()\n    def core_total(self):\n        \"\"\"\n        str: Returns the total number of cores for the server if available, else None.\n        \"\"\"\n        if self.data and 'cpu_cores' in self.data:\n            return sum([int(c) for c in self.data['cpu_cores']])\n        else:\n            return None\n\n    def get_processor_by_index(self, index):\n        \"\"\"\n        Construct a dictionary of the information stored for the given CPU.\n\n        Parameters:\n            index (int): The CPU index to retrieve.\n\n        Returns:\n            dict: A dictionary of the information for that CPU.\n        \"\"\"\n        return dict((k, v[index]) for k, v in self.data.items())\n", "path": "insights/parsers/cpuinfo.py"}], "after_files": [{"content": "\"\"\"\nCpuInfo - file ``/proc/cpuinfo``\n================================\n\nThis parser reads the content of the ``/proc/cpuinfo`` file and parses it\ninto a dictionary of lists, keyed on the left hand column of the cpuinfo\noutput.\n\nThe object also provides properties for the standard information about the\nCPU and motherboard architecture.\n\nSample input::\n\n    processor       : 0\n    vendor_id       : GenuineIntel\n    cpu family      : 6\n    model           : 45\n    model name      : Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz\n    stepping        : 2\n    microcode       : 1808\n    cpu MHz         : 2900.000\n    cache size      : 20480 KB\n    physical id     : 0\n    siblings        : 1\n    core id         : 0\n    cpu cores       : 1\n    apicid          : 0\n    flags           : fpu vme de pse tsc msr pae mce\n    address sizes   : 40 bits physical, 48 bits virtual\n    bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit\n\n    processor       : 1\n    vendor_id       : GenuineIntel\n    cpu family      : 6\n    model           : 45\n    model name      : Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz\n    stepping        : 2\n    microcode       : 1808\n    cpu MHz         : 2900.000\n    cache size      : 20480 KB\n    physical id     : 2\n    siblings        : 1\n    core id         : 0\n    cpu cores       : 1\n    apicid          : 2\n    flags           : fpu vme de pse tsc msr pae mce\n    address sizes   : 40 bits physical, 48 bits virtual\n    bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit\n\nExamples:\n\n    >>> cpu_info.cpu_count\n    2\n    >>> sorted(cpu_info.apicid)\n    ['0', '2']\n    >>> cpu_info.socket_count\n    2\n    >>> cpu_info.vendor\n    'GenuineIntel'\n    >>> \"fpu\" in cpu_info.flags\n    True\n    >>> cpu_info.model_name\n    'Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz'\n    >>> cpu_info.get_processor_by_index(0)['cpus']\n    '0'\n    >>> cpu_info.get_processor_by_index(0)['vendors']\n    'GenuineIntel'\n\"\"\"\n\nfrom collections import defaultdict\nfrom .. import Parser, parser, defaults, get_active_lines, LegacyItemAccess\nfrom insights.specs import Specs\n\n\n@parser(Specs.cpuinfo)\nclass CpuInfo(LegacyItemAccess, Parser):\n    \"\"\"\n    CpuInfo parser - able to be used as a dictionary through the\n    LegacyItemAccess mixin class.\n\n    The following items are remapped into lists, with the element number\n    corresponding to the CPU.  For example, given the following input::\n\n        processor       : 1\n        vendor_id       : GenuineIntel\n        cpu family      : 6\n        model           : 45\n        model name      : Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz\n        stepping        : 2\n        microcode       : 1808\n        cpu MHz         : 2900.000\n        cache size      : 20480 KB\n        physical id     : 2\n        siblings        : 1\n        core id         : 0\n        cpu cores       : 1\n        apicid          : 2\n        address sizes   : 40 bits physical, 48 bits virtual\n        bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit\n\n    The following keys would be lists of:\n\n    * **cpus** - the *processor* line (e.g. ``1``)\n    * **sockets** - the *physical id* line (e.g. ``2``)\n    * **vendors** - the *vendor_id* line (e.g. ``GenuineIntel``)\n    * **models** - the *model name* line (e.g. ``Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz``)\n    * **model_ids** - the *model* line (e.g. ``45``)\n    * **families** - the *cpu family* line (e.g. ``6``)\n    * **clockspeeds** - the *cpu MHz* line (e.g. ``2900.000``)\n    * **cache_sizes** - the *cache size* line (e.g. ``20480 KB``)\n    * **cpu_cores** - the *cpu cores* line (e.g. ``1``)\n    * **apicid** - the *apicid* line (e.g. ``1``)\n    * **stepping** - the *stepping* line (e.g. ``2``)\n    * **address_sizes** - the *address sizes* line (e.g. ``40 bits physical, 48 bits virtual``)\n    * **bugs** - the *bugs* line (e.g. ``cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit``)\n    \"\"\"\n\n    def parse_content(self, content):\n\n        self.data = defaultdict(list)\n        mappings = {\n            \"processor\": \"cpus\",\n            \"physical id\": \"sockets\",\n            \"vendor_id\": \"vendors\",\n            \"model name\": \"models\",\n            \"model\": \"model_ids\",\n            \"cpu family\": \"families\",\n            \"cpu MHz\": \"clockspeeds\",\n            \"cache size\": \"cache_sizes\",\n            \"cpu cores\": \"cpu_cores\",\n            \"apicid\": \"apicid\",\n            \"flags\": \"flags\",\n            \"stepping\": \"stepping\",\n            \"Features\": \"features\",\n            \"CPU implementer\": \"cpu_implementer\",\n            \"CPU architecture\": \"cpu_architecture\",\n            \"CPU variant\": \"cpu_variant\",\n            \"CPU part\": \"cpu_part\",\n            \"CPU revision\": \"cpu_revision\",\n            \"cpu\": \"cpu\",\n            \"revision\": \"revision\",\n            \"address sizes\": \"address_sizes\",\n            \"bugs\": \"bugs\",\n            \"apicid\": \"apicid\"\n        }\n\n        for line in get_active_lines(content, comment_char=\"COMMAND>\"):\n            key, value = [p.strip() for p in line.split(\":\", 1)]\n            if key in mappings:\n                self.data[mappings[key]].append(value)\n\n        if \"cpu\" in self.data and \"POWER\" in self.data[\"cpu\"][0]:\n            # this works differently than on x86 and is not per-cpu\n            del self.data[\"model_ids\"]\n\n        self.data = dict(self.data)\n\n    def __iter__(self):\n        \"\"\"\n        Iterating through this object will yield the ``get_processor_by_index``\n        information for each CPU.\n        \"\"\"\n        for idx in range(len(self[\"cpus\"])):\n            yield self.get_processor_by_index(idx)\n\n    @property\n    @defaults()\n    def cpu_speed(self):\n        \"\"\"\n        str: Returns the CPU speed of the first CPU.\n        \"\"\"\n        return self.data[\"clockspeeds\"][0]\n\n    @property\n    @defaults()\n    def cache_size(self):\n        \"\"\"\n        str: Returns the cache size of the first CPU.\n        \"\"\"\n        return self.data[\"cache_sizes\"][0]\n\n    @property\n    @defaults()\n    def cpu_count(self):\n        \"\"\"\n        str: Returns the number of CPUs.\n        \"\"\"\n        return len(self.data.get(\"cpus\", []))\n\n    @property\n    @defaults()\n    def apicid(self):\n        \"\"\"\n        str: Returns the apicid of the processor.\n        \"\"\"\n        return self.data[\"apicid\"]\n\n    @property\n    @defaults()\n    def socket_count(self):\n        \"\"\"\n        str: Returns the number of sockets.  This is distinct from the number\n        of CPUs.\n        \"\"\"\n        return len(set(self.data.get(\"sockets\", [])))\n\n    @property\n    @defaults()\n    def model_name(self):\n        \"\"\"\n        str: Returns the model name of the first CPU.\n        \"\"\"\n        return self.data[\"models\"][0]\n\n    @property\n    @defaults()\n    def model_number(self):\n        \"\"\"\n        str: Returns the model ID of the first CPU.\n        \"\"\"\n        return self.data[\"model_ids\"][0]\n\n    @property\n    @defaults()\n    def flags(self):\n        \"\"\"\n        list: Returns a list of feature flags for the first CPU.\n        \"\"\"\n        return self.data[\"flags\"][0].split()\n\n    @property\n    @defaults()\n    def vendor(self):\n        \"\"\"\n        str: Returns the vendor of the first CPU.\n        \"\"\"\n        return self.data[\"vendors\"][0]\n\n    @property\n    @defaults()\n    def core_total(self):\n        \"\"\"\n        int: Returns the total number of cores for the server if available, else None.\n\n        .. warning::\n            This function is deprecated.  Please use the\n            :py:class:`insights.parsers.lscpu.LsCPU` class attribute\n            ``info['Cores per socket']`` and ``info['Sockets']`` values instead.\n        \"\"\"\n        if self.data and 'cpu_cores' in self.data:\n            # I guess we can't get this fancey on older versions of RHEL\n            # return sum({e['sockets']: int(e['cpu_cores']) for e in self}.values())\n            physical_dict = {}\n            for e in self:\n                # we should rename sockets here to physical_ids as cpuinfo\n                # has it there can be many physical_ids per socket\n                # see fgrep 'physical id' /proc/cpuinfo on a single\n                # package system\n                physical_dict[e['sockets']] = int(e['cpu_cores'])\n            return sum(physical_dict.values())\n        else:\n            return None\n\n    def get_processor_by_index(self, index):\n        \"\"\"\n        Construct a dictionary of the information stored for the given CPU.\n\n        Parameters:\n            index (int): The CPU index to retrieve.\n\n        Returns:\n            dict: A dictionary of the information for that CPU.\n        \"\"\"\n        return dict((k, v[index]) for k, v in self.data.items())\n", "path": "insights/parsers/cpuinfo.py"}]}