From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id D428A45813; Mon, 19 Aug 2024 13:11:24 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 60EBE40291; Mon, 19 Aug 2024 13:11:24 +0200 (CEST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mails.dpdk.org (Postfix) with ESMTP id D70BD40267 for ; Mon, 19 Aug 2024 13:11:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1724065882; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Mihe6nnpf7Ljqqy4+xqjfJQJN/sb3teZJ4w5Oj6gfKk=; b=L9QIrAeOQPoX+41USbZUpaLzfnnvEWfT9XGefatYxP3wQ6F77YKa/gQ8RkU8OSBNij/R1j lN4cWpsjKhtJ8/iNgnOVdsdA9mLv28ezHcir+1z3nnt1U7nVVQVxPpYA823s6JHAQaVqBU s2FW9k1XXuFjYXFY+x5LUmzorxQJEKs= Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-674-tmUBgLXqN3qiTgr56dzJ3A-1; Mon, 19 Aug 2024 07:11:21 -0400 X-MC-Unique: tmUBgLXqN3qiTgr56dzJ3A-1 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-3718baf35e0so2102374f8f.1 for ; Mon, 19 Aug 2024 04:11:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724065880; x=1724670680; h=in-reply-to:references:user-agent:to:from:cc:subject:message-id :date:content-transfer-encoding:mime-version:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Mihe6nnpf7Ljqqy4+xqjfJQJN/sb3teZJ4w5Oj6gfKk=; b=CcCwpSkXM+S+go5az7tS09BbGxZcjgWKJ3kU9HZGBBIaiFIW1bbGof7Lc3keO4Pfl/ MMZ/BmiQBHGGf+SjOuNA+d4gc+8qCnq1TM3eSfAkwTU45TgJK944yVHp4+tnUuYjBsLV r+43iDVlHUui4Kg8qHRvpemtZ2eyzhjzLo1bjVP7JTaIX6w5wRbJ24fNJS9p50FwVe0R pQql7nLU7B8jrpWNSjbLkGPwTDfBV1tGj7vxiV9tYgg6hbAIdefwXREAQVMAQGIL7yup 36mls3TicOQAq5meHRDJa8VSM5AT02LFcEG8kQDsA+MQb/woDsoj8TqI1DTyRKW+EjX5 HDIg== X-Forwarded-Encrypted: i=1; AJvYcCWeTs3ruQHooVhqQQVugM7D2ZIuE74aV5WJPihXrGvCiOMyfMUSqxjyiPQZX4dupJQ02EQSFpGWUMZipgY= X-Gm-Message-State: AOJu0Yzf2cFmUppGa2UX/3T4Ssr07btnmELaSq6wdQvJO68QCGy7OlkW akbRVgj8eM+8TEvjgLXGxJzW6zIwcxHr32/ah9IWfydKUx9vn9V7PgUQxxe1arfF4X7gFcAqpGD qnQ6YIefKFeHZWRAns5GB5MV+a9dPmsYjxdxF66p4 X-Received: by 2002:a5d:5f42:0:b0:36b:b297:1419 with SMTP id ffacd0b85a97d-371a73ea90emr5811087f8f.20.1724065879930; Mon, 19 Aug 2024 04:11:19 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEMAasoaQKTwokDd9kbWMZOYrQlvoOgxQznx9893O7EzoaXioyMSO8NVKAlk4qrkO6RzFjBRw== X-Received: by 2002:a5d:5f42:0:b0:36b:b297:1419 with SMTP id ffacd0b85a97d-371a73ea90emr5811066f8f.20.1724065879436; Mon, 19 Aug 2024 04:11:19 -0700 (PDT) Received: from localhost (2a01cb00025433006239e1f47a0b2371.ipv6.abo.wanadoo.fr. [2a01:cb00:254:3300:6239:e1f4:7a0b:2371]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-371898498e1sm10280485f8f.41.2024.08.19.04.11.18 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 19 Aug 2024 04:11:19 -0700 (PDT) Mime-Version: 1.0 Date: Mon, 19 Aug 2024 13:11:18 +0200 Message-Id: Subject: Re: [PATCH v2 1/4] usertools/cpu_layout: update coding style Cc: From: "Robin Jarry" To: "Anatoly Burakov" , User-Agent: aerc/0.18.2-23-g4abdbd4014f5-dirty References: <4844fc3a4604ffef789702752ff04699ab5118db.1723810613.git.anatoly.burakov@intel.com> In-Reply-To: <4844fc3a4604ffef789702752ff04699ab5118db.1723810613.git.anatoly.burakov@intel.com> X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=UTF-8; format=Flowed X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Anatoly Burakov, Aug 16, 2024 at 14:16: > Update coding style: > > - make it PEP-484 compliant > - address all flake8, mypy etc. warnings > - use f-strings in place of old-style string interpolation > - refactor printing to make the code more readable > > Signed-off-by: Anatoly Burakov > --- > usertools/cpu_layout.py | 162 ++++++++++++++++++++++++++-------------- > 1 file changed, 104 insertions(+), 58 deletions(-) > > diff --git a/usertools/cpu_layout.py b/usertools/cpu_layout.py > index 891b9238fa..be86f06938 100755 > --- a/usertools/cpu_layout.py > +++ b/usertools/cpu_layout.py > @@ -3,62 +3,108 @@ > # Copyright(c) 2010-2014 Intel Corporation > # Copyright(c) 2017 Cavium, Inc. All rights reserved. > =20 > -sockets =3D [] > -cores =3D [] > -core_map =3D {} > -base_path =3D "/sys/devices/system/cpu" > -fd =3D open("{}/kernel_max".format(base_path)) > -max_cpus =3D int(fd.read()) > -fd.close() > -for cpu in range(max_cpus + 1): > - try: > - fd =3D open("{}/cpu{}/topology/core_id".format(base_path, cpu)) > - except IOError: > - continue > - core =3D int(fd.read()) > - fd.close() > - fd =3D open("{}/cpu{}/topology/physical_package_id".format(base_path= , cpu)) > - socket =3D int(fd.read()) > - fd.close() > - if core not in cores: > - cores.append(core) > - if socket not in sockets: > - sockets.append(socket) > - key =3D (socket, core) > - if key not in core_map: > - core_map[key] =3D [] > - core_map[key].append(cpu) > - > -print(format("=3D" * (47 + len(base_path)))) > -print("Core and Socket Information (as reported by '{}')".format(base_pa= th)) > -print("{}\n".format("=3D" * (47 + len(base_path)))) > -print("cores =3D ", cores) > -print("sockets =3D ", sockets) > -print("") > - > -max_processor_len =3D len(str(len(cores) * len(sockets) * 2 - 1)) > -max_thread_count =3D len(list(core_map.values())[0]) > -max_core_map_len =3D (max_processor_len * max_thread_count) \ > - + len(", ") * (max_thread_count - 1) \ > - + len('[]') + len('Socket ') > -max_core_id_len =3D len(str(max(cores))) > - > -output =3D " ".ljust(max_core_id_len + len('Core ')) > -for s in sockets: > - output +=3D " Socket %s" % str(s).ljust(max_core_map_len - len('Sock= et ')) > -print(output) > - > -output =3D " ".ljust(max_core_id_len + len('Core ')) > -for s in sockets: > - output +=3D " --------".ljust(max_core_map_len) > - output +=3D " " > -print(output) > - > -for c in cores: > - output =3D "Core %s" % str(c).ljust(max_core_id_len) > - for s in sockets: > - if (s, c) in core_map: > - output +=3D " " + str(core_map[(s, c)]).ljust(max_core_map_l= en) > +from typing import List, Set, Dict, Tuple Minor nit pick: recently I started using `import typing as T` and then=20 referencing T.List, T.Tuple, etc. This avoids clobbering the patches when new symbols from the typing=20 module are required and using a short alias keeps the code readable. > + > + > +def _range_expand(rstr: str) -> List[int]: def range_expand(rstr: str) -> T.List[int]: > + """Expand a range string into a list of integers.""" > + # 0,1-3 =3D> [0, 1-3] > + ranges =3D rstr.split(",") > + valset: List[int] =3D [] > + for r in ranges: > + # 1-3 =3D> [1, 2, 3] > + if "-" in r: > + start, end =3D r.split("-") > + valset.extend(range(int(start), int(end) + 1)) > else: > - output +=3D " " * (max_core_map_len + 1) > - print(output) > + valset.append(int(r)) > + return valset > + > + > +def _read_sysfs(path: str) -> str: > + with open(path, encoding=3D"utf-8") as fd: > + return fd.read().strip() > + > + > +def _print_row(row: Tuple[str, ...], col_widths: List[int]) -> None: def print_row(row: T.Tuple[str, ...], col_widths: T.List[int]) -> None: > + first, *rest =3D row > + w_first, *w_rest =3D col_widths > + first_end =3D " " * 4 > + rest_end =3D " " * 10 > + > + print(first.ljust(w_first), end=3Dfirst_end) > + for cell, width in zip(rest, w_rest): > + print(cell.rjust(width), end=3Drest_end) > + print() > + > + > +def _print_section(heading: str) -> None: > + sep =3D "=3D" * len(heading) > + print(sep) > + print(heading) > + print(sep) > + print() > + > + > +def _main() -> None: > + sockets_s: Set[int] =3D set() > + cores_s: Set[int] =3D set() > + core_map: Dict[Tuple[int, int], List[int]] =3D {} sockets_s: T.Set[int] =3D set() cores_s: T.Set[int] =3D set() core_map: T.Dict[Tuple[int, int], T.List[int]] =3D {} > + base_path =3D "/sys/devices/system/cpu" > + > + cpus =3D _range_expand(_read_sysfs(f"{base_path}/online")) > + > + for cpu in cpus: > + lcore_base =3D f"{base_path}/cpu{cpu}" > + core =3D int(_read_sysfs(f"{lcore_base}/topology/core_id")) > + socket =3D int(_read_sysfs(f"{lcore_base}/topology/physical_pack= age_id")) > + > + cores_s.add(core) > + sockets_s.add(socket) > + key =3D (socket, core) > + core_map.setdefault(key, []) > + core_map[key].append(cpu) > + > + cores =3D sorted(cores_s) > + sockets =3D sorted(sockets_s) > + > + _print_section("Core and Socket Information " > + f"(as reported by '{base_path}')") > + > + print("cores =3D ", cores) > + print("sockets =3D ", sockets) > + print() > + > + # Core, [Socket, Socket, ...] > + heading_strs =3D "", *[f"Socket {s}" for s in sockets] > + sep_strs =3D tuple("-" * len(hstr) for hstr in heading_strs) > + rows: List[Tuple[str, ...]] =3D [] rows: T.List[T.Tuple[str, ...]] =3D [] > + > + for c in cores: > + # Core, > + row: Tuple[str, ...] =3D (f"Core {c}",) row: T.Tuple[str, ...] =3D (f"Core {c}",) > + > + # [lcores, lcores, ...] > + for s in sockets: > + try: > + lcores =3D core_map[(s, c)] > + row +=3D (str(lcores),) > + except KeyError: > + row +=3D ("",) > + rows +=3D [row] > + > + # find max widths for each column, including header and rows > + col_widths =3D [ > + max([len(tup[col_idx]) for tup in rows + [heading_strs]]) > + for col_idx in range(len(heading_strs)) > + ] > + > + # print out table taking row widths into account > + _print_row(heading_strs, col_widths) > + _print_row(sep_strs, col_widths) > + for row in rows: > + _print_row(row, col_widths) > + > + > +if __name__ =3D=3D "__main__": > + _main() > --=20 > 2.43.5 FYI: if we change the minimum supported python version to 3.9, we could=20 even get rid of this import completely as builtin types `set`, `list`,=20 `tuple` and `dict` have become subscriptable. https://peps.python.org/pep-0585/ You can use them directly instead of the symbols defined in the typing=20 module. E.g. the following becomes valid syntax: def foo(a: list[set[int]]) -> dict[str, tuple[str]]: Instead of the more verbose: def foo(a: T.List[T.Set[int]]) -> T.Dict[str, T.Tuple[str]]: But we can keep that for another day.