From 847c898eeb0a41f31dfda5f1dbcc7668bbac29e7 Mon Sep 17 00:00:00 2001 From: themylogin Date: Tue, 20 Feb 2024 16:05:34 +0100 Subject: [PATCH] Initial commit --- .github/workflows/flake8.yml | 24 + .github/workflows/unit_tests.yml | 24 + .gitignore | 4 + debian/changelog | 5 + debian/control | 19 + debian/rules | 9 + debian/source/format | 1 + debian/source/options | 1 + ixhardware/__init__.py | 4 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 449 bytes .../__pycache__/__init__.cpython-38.pyc | Bin 0 -> 237 bytes .../__pycache__/chassis.cpython-311.pyc | Bin 0 -> 828 bytes ixhardware/__pycache__/dmi.cpython-311.pyc | Bin 0 -> 4919 bytes ixhardware/__pycache__/dmi.cpython-38.pyc | Bin 0 -> 2691 bytes ixhardware/chassis.py | 32 ++ ixhardware/dmi.py | 99 +++++ setup.cfg | 2 + setup.py | 13 + .../test_dmi.cpython-38-pytest-5.4.2.pyc | Bin 0 -> 17380 bytes tests/test_dmi.py | 409 ++++++++++++++++++ 20 files changed, 646 insertions(+) create mode 100644 .github/workflows/flake8.yml create mode 100644 .github/workflows/unit_tests.yml create mode 100644 .gitignore create mode 100644 debian/changelog create mode 100644 debian/control create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 debian/source/options create mode 100644 ixhardware/__init__.py create mode 100644 ixhardware/__pycache__/__init__.cpython-311.pyc create mode 100644 ixhardware/__pycache__/__init__.cpython-38.pyc create mode 100644 ixhardware/__pycache__/chassis.cpython-311.pyc create mode 100644 ixhardware/__pycache__/dmi.cpython-311.pyc create mode 100644 ixhardware/__pycache__/dmi.cpython-38.pyc create mode 100644 ixhardware/chassis.py create mode 100644 ixhardware/dmi.py create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tests/__pycache__/test_dmi.cpython-38-pytest-5.4.2.pyc create mode 100644 tests/test_dmi.py diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml new file mode 100644 index 0000000..e699c37 --- /dev/null +++ b/.github/workflows/flake8.yml @@ -0,0 +1,24 @@ +name: flake8 + +on: + pull_request: + types: + - 'synchronize' + - 'opened' + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.9 + uses: actions/setup-python@v1 + with: + python-version: 3.9 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 + - name: Run flake8 + run: flake8 . diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml new file mode 100644 index 0000000..9a99711 --- /dev/null +++ b/.github/workflows/unit_tests.yml @@ -0,0 +1,24 @@ +name: unit_tests + +on: + pull_request: + types: + - 'synchronize' + - 'opened' + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.9 + uses: actions/setup-python@v1 + with: + python-version: 3.9 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest + - name: Run tests + run: pytest -v tests diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d85994 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea/* +build/* +dist/* +ixhardware.egg* diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..c4c0846 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +ixhardware (1.0-0~truenas+1) electriceel-truenas-unstable; urgency=medium + + * Initial release + + -- Vladimir Vinogradenko Tue, 20 Feb 2024 12:33:00 +0200 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..1fb3912 --- /dev/null +++ b/debian/control @@ -0,0 +1,19 @@ +Source: ixhardware +Section: contrib/python +Priority: optional +Maintainer: Vladimir Vinogradenko +Build-Depends: debhelper-compat (= 12), + dh-python, + python3-dev, + python3-setuptools +Standards-Version: 4.4.1 +Homepage: https://github.com/truenas/ixhardware +Testsuite: autopkgtest-pkg-python + +Package: python3-ixhardware +Architecture: any +Depends: ${shlibs:Depends}, + ${misc:Depends}, + ${python3:Depends} +Description: Detect iXsystems hardware. + This package detects iXsystems hardware. diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..7185a39 --- /dev/null +++ b/debian/rules @@ -0,0 +1,9 @@ +#!/usr/bin/make -f +export DH_VERBOSE = 1 + +export PYBUILD_NAME=ixhardware + +%: + dh $@ --with python3 --buildsystem=pybuild + +override_dh_auto_test: diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/source/options b/debian/source/options new file mode 100644 index 0000000..cb61fa5 --- /dev/null +++ b/debian/source/options @@ -0,0 +1 @@ +extend-diff-ignore = "^[^/]*[.]egg-info/" diff --git a/ixhardware/__init__.py b/ixhardware/__init__.py new file mode 100644 index 0000000..211c7ef --- /dev/null +++ b/ixhardware/__init__.py @@ -0,0 +1,4 @@ +from .chassis import PLATFORM_PREFIXES, TRUENAS_UNKNOWN, get_chassis_hardware +from .dmi import DMIInfo, DMIParser, parse_dmi + +__all__ = ["PLATFORM_PREFIXES", "TRUENAS_UNKNOWN", "get_chassis_hardware", "DMIInfo", "DMIParser", "parse_dmi"] diff --git a/ixhardware/__pycache__/__init__.cpython-311.pyc b/ixhardware/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..382e2bd58f0f4b12e1ffdc4cb2031710ad80f90a GIT binary patch literal 449 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 CL6=1U literal 0 HcmV?d00001 diff --git a/ixhardware/__pycache__/dmi.cpython-38.pyc b/ixhardware/__pycache__/dmi.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2fc7961f1c8027476fcbd8290bf36a7ba80c1313 GIT binary patch literal 2691 zcmZ`*TW=f36`q-$y^vf{7b}UK7Vg4;fe>IN+d&d1Fbvz0TnMmf!*rT>kzldnjOeZQ zLd~w+Xh8-=)~r%TM?H|NatT<6P$g(iXT zr`>o09&H2v^uIiLj5@5e-|=_k;s|=ZJ;Au==FaIDx%Lhw6rit9X#cW!Yhx zLq}>4X_aKM2XgPxs7i`FPPM!FaC=dyQQ5NS1yYZkpP*TnF zN2(A9gDT47OzI2eVOh!S{NOX@xsj`)BEmaL5qjmB}yas^0}Em8m6@BjPD9TejXH_3n-C^-sGW-vl3bii2u& zP-#a=uyQ_NFy-t+jM2COtwc4A$uSwzV>%^MbSc_{1)9+aoj-zIbh8|#NtGtKG~rXq zbXR={^WJDvU4pK*&6Ho^vSvS8FTM_z`=;G4n$>>9i&JebK3+`UCX z6Z@Az!oX7R_v#jCIH(RsGPu?a{U=)ww(j<~qRqQcx8_9GyP?~E*5B^ke>BIv(G8t@ z_YBj2y~@WoyCL6x{BZjf{bB%Cc>SGuO&>VrDv%-g4cLT&=a4D+3)|=YnMXiAwILRh z5m=k8UDGsq+fkag(xj{gMK-#99hXCIbO>M%~5)T4a9G2deBL*TTb z!H*eg{+FPS4d(#0JXWv%k^#=eDQ0A>^d?UK1Yl-=h$%Xy6IQV?RAa&Rh`KCDpI~2D zmmtzi4BZfR&M->rmC8EiV>-5`?AV@?uV5@Em9y7WH6;^HNxfRR#~w!WkL>Sk3NMAP z$S3exnDFoU*W?+=+1Jp6DDZl(==zBTM>+W~d?)BlwRbgJzbe+RK6{N0>(B1TNh(E9 z6~S(yvbYNFZ9nP DMIInfo: + return self._parse_dmi(output.splitlines()) + + def _parse_dmi(self, lines: [str]) -> DMIInfo: + info = DMIInfo() + + _type = None + for line in lines: + if "DMI type 0," in line: + _type = "RELEASE_DATE" + if "DMI type 1," in line: + _type = "SYSINFO" + if "DMI type 2," in line: + _type = "BBINFO" + if "DMI type 38," in line: + _type = "IPMI" + + if not line or ":" not in line: + # "sections" are separated by the category name and then + # a newline so ignore those lines + continue + + sect, val = [i.strip() for i in line.split(":", 1)] + if sect == "Release Date": + info.bios_release_date = self._parse_bios_release_date(val) + elif sect == "Manufacturer": + if _type == "SYSINFO": + info.system_manufacturer = val + else: + info.baseboard_manufacturer = val + elif sect == "Product Name": + if _type == "SYSINFO": + info.system_product_name = val + else: + info.baseboard_product_name = val + elif sect == "Serial Number" and _type == "SYSINFO": + info.system_serial_number = val + elif sect == "Version" and _type == "SYSINFO": + info.system_version = val + elif sect == "I2C Slave Address": + info.has_ipmi = True + elif sect == "Error Correction Type": + info.ecc_memory = "ECC" in val + # we break the for loop here since "16" is the last section + # that gets processed + break + + return info + + def _parse_bios_release_date(self, string): + parts = string.strip().split("/") + if len(parts) < 3: + # Don"t know what the BIOS is reporting so assume it"s invalid + return + + # Give the best effort to convert to a date object. + # Searched hundreds of debugs that have been provided + # via end-users and 99% all reported the same date + # format, however, there are a couple that had a + # 2 digit year instead of a 4 digit year...gross + formatter = "%m/%d/%Y" if len(parts[-1]) == 4 else "%m/%d/%y" + try: + return datetime.strptime(string, formatter).date() + except Exception as e: + logger.warning(f"Failed to format BIOS release date to datetime object: {e!r}") + + +def parse_dmi() -> DMIInfo: + return DMIParser().parse( + subprocess.run(DMIParser.command, check=False, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, + encoding="utf-8", errors="ignore").stdout + ) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..aa079ec --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[flake8] +max-line-length=120 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..baeddcb --- /dev/null +++ b/setup.py @@ -0,0 +1,13 @@ +from distutils.core import setup +from setuptools import find_packages + + +setup( + name="ixhardware", + description="Detect iXsystems hardware", + version="1.0", + include_package_data=True, + packages=find_packages(), + license="GNU3", + platforms="any", +) diff --git a/tests/__pycache__/test_dmi.cpython-38-pytest-5.4.2.pyc b/tests/__pycache__/test_dmi.cpython-38-pytest-5.4.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..780fe2c5359f227baf44e91f1e497092b64b5c9d GIT binary patch literal 17380 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 literal 0 HcmV?d00001 diff --git a/tests/test_dmi.py b/tests/test_dmi.py new file mode 100644 index 0000000..74fcfb2 --- /dev/null +++ b/tests/test_dmi.py @@ -0,0 +1,409 @@ +from datetime import date + +from ixhardware import DMIInfo, DMIParser + + +def test__missing(): + assert DMIParser().parse("") == DMIInfo( + bios_release_date=None, + ecc_memory=False, + baseboard_manufacturer="", + baseboard_product_name="", + system_manufacturer="", + system_product_name="", + system_serial_number="", + system_version="", + has_ipmi=False, + ) + + +full_dmi = """ +# dmidecode 3.3 +Getting SMBIOS data from sysfs. +SMBIOS 3.2.1 present. + +Handle 0x0000, DMI type 0, 26 bytes +BIOS Information + Vendor: American Megatrends Inc. + Version: 3.3aV3 + Release Date: 12/03/2020 + Address: 0xF0000 + Runtime Size: 64 kB + ROM Size: 32 MB + Characteristics: + PCI is supported + BIOS is upgradeable + BIOS shadowing is allowed + Boot from CD is supported + Selectable boot is supported + BIOS ROM is socketed + EDD is supported + 5.25"/1.2 MB floppy services are supported (int 13h) + 3.5"/720 kB floppy services are supported (int 13h) + 3.5"/2.88 MB floppy services are supported (int 13h) + Print screen service is supported (int 5h) + Serial services are supported (int 14h) + Printer services are supported (int 17h) + ACPI is supported + USB legacy is supported + BIOS boot specification is supported + Targeted content distribution is supported + UEFI is supported + BIOS Revision: 5.14 + +Handle 0x0001, DMI type 1, 27 bytes +System Information + Manufacturer: iXsystems + Product Name: TRUENAS-M60 + Version: 0123456789 + Serial Number: A1-111111 + UUID: 00000000-0000-0000-0000-3cecef5ee7d6 + Wake-up Type: Power Switch + SKU Number: To be filled by O.E.M. + Family: To be filled by O.E.M. + +Handle 0x0002, DMI type 2, 15 bytes +Base Board Information + Manufacturer: Supermicro + Product Name: X11SPH-nCTPF + Version: 1.01 + Serial Number: 0000000000000 + Asset Tag: To be filled by O.E.M. + Features: + Board is a hosting board + Board is replaceable + Location In Chassis: To be filled by O.E.M. + Chassis Handle: 0x0003 + Type: Motherboard + Contained Object Handles: 0 + +Handle 0x0014, DMI type 38, 18 bytes +IPMI Device Information + Interface Type: KCS (Keyboard Control Style) + Specification Version: 2.0 + I2C Slave Address: 0x10 + NV Storage Device: Not Present + Base Address: 0x0000000000000CA2 (I/O) + Register Spacing: Successive Byte Boundaries + +Handle 0x0024, DMI type 16, 23 bytes +Physical Memory Array + Location: System Board Or Motherboard + Use: System Memory + Error Correction Type: Single-bit ECC + Maximum Capacity: 2304 GB + Error Information Handle: Not Provided + Number Of Devices: 4 + +Handle 0x002C, DMI type 16, 23 bytes +Physical Memory Array + Location: System Board Or Motherboard + Use: System Memory + Error Correction Type: Single-bit ECC + Maximum Capacity: 2304 GB + Error Information Handle: Not Provided + Number Of Devices: 4 + +""" + + +def test__full(): + assert DMIParser().parse(full_dmi) == DMIInfo( + bios_release_date=date(2020, 12, 3), + ecc_memory=True, + baseboard_manufacturer="Supermicro", + baseboard_product_name="X11SPH-nCTPF", + system_manufacturer="iXsystems", + system_product_name="TRUENAS-M60", + system_serial_number="A1-111111", + system_version="0123456789", + has_ipmi=True, + ) + + +double_colon_dmi = """ +# dmidecode 3.3 +Getting SMBIOS data from sysfs. +SMBIOS 2.7 present.Handle 0x0001, DMI type 1, 27 bytes +System Information + Manufacturer: Supermicro + Product Name: X9DRi-LN4+/X9DR3-LN4+ + Version: 0123456789 + Serial Number: 0123456789 + UUID: 00000000-0000-0000-0000-002590f3967a + Wake-up Type: Power Switch + SKU Number: To be filled by O.E.M. + Family: To be filled by O.E.M.Handle 0x0002, DMI type 2, 15 bytes +Base Board Information + Manufacturer: Supermicro + Product Name: X9DRi-LN4+/X9DR3-LN4+ + Version: REV:1.20A + Serial Number: FAKE + Asset Tag: To be filled by O.E.M. + Features: + Board is a hosting board + Board is replaceable + Location In Chassis: To be filled by O.E.M. + Chassis Handle: 0x0003 + Type: Motherboard + Contained Object Handles: 0Handle 0x002F, DMI type 16, 23 bytes +Physical Memory Array + Location: System Board Or Motherboard + Use: System Memory + Error Correction Type: Multi-bit ECC + Maximum Capacity: 768 GB + Error Information Handle: Not Provided + Number Of Devices: 12Handle 0x0049, DMI type 16, 23 bytes +Physical Memory Array + Location: System Board Or Motherboard + Use: System Memory + Error Correction Type: Multi-bit ECC + Maximum Capacity: 768 GB + Error Information Handle: Not Provided + Number Of Devices: 12 +""" + + +def test__double_colon(): + assert DMIParser().parse(double_colon_dmi) == DMIInfo( + bios_release_date=None, + ecc_memory=True, + baseboard_manufacturer="Supermicro", + baseboard_product_name="X9DRi-LN4+/X9DR3-LN4+", + system_manufacturer="Supermicro", + system_product_name="X9DRi-LN4+/X9DR3-LN4+", + system_serial_number="0123456789", + system_version="0123456789", + has_ipmi=False, + ) + + +missing_dmi_type1 = """ +# dmidecode 3.3 +Getting SMBIOS data from sysfs. +SMBIOS 2.8 present. + +Handle 0x0002, DMI type 2, 15 bytes +Base Board Information + Manufacturer: Supermicro + Product Name: X11SPH-nCTPF + Version: 1.01 + Serial Number: 0000000000000 + Asset Tag: To be filled by O.E.M. + Features: + Board is a hosting board + Board is replaceable + Location In Chassis: To be filled by O.E.M. + Chassis Handle: 0x0003 + Type: Motherboard + Contained Object Handles: 0 + +Handle 0x1000, DMI type 16, 23 bytes +Physical Memory Array + Location: Other + Use: System Memory + Error Correction Type: Multi-bit ECC + Maximum Capacity: 8 GB + Error Information Handle: Not Provided + Number Of Devices: 1 + +""" + + +def test__missing_dmi_type1(): + assert DMIParser().parse(missing_dmi_type1) == DMIInfo( + bios_release_date=None, + ecc_memory=True, + baseboard_manufacturer="Supermicro", + baseboard_product_name="X11SPH-nCTPF", + system_manufacturer="", + system_product_name="", + system_serial_number="", + system_version="", + has_ipmi=False, + ) + + +missing_dmi_type2 = """ +# dmidecode 3.3 +Getting SMBIOS data from sysfs. +SMBIOS 2.8 present. + +Handle 0x0100, DMI type 1, 27 bytes +System Information + Manufacturer: QEMU + Product Name: Standard PC (Q35 + ICH9, 2009) + Version: pc-q35-5.2 + Serial Number: Not Specified + UUID: 236ce080-e87b-4d21-b9dd-3e43b8fb58dd + Wake-up Type: Power Switch + SKU Number: Not Specified + Family: Not Specified + +Handle 0x1000, DMI type 16, 23 bytes +Physical Memory Array + Location: Other + Use: System Memory + Error Correction Type: Multi-bit ECC + Maximum Capacity: 8 GB + Error Information Handle: Not Provided + Number Of Devices: 1 + +""" + + +def test__missing_dmi_type2(): + assert DMIParser().parse(missing_dmi_type2) == DMIInfo( + bios_release_date=None, + ecc_memory=True, + baseboard_manufacturer="", + baseboard_product_name="", + system_manufacturer="QEMU", + system_product_name="Standard PC (Q35 + ICH9, 2009)", + system_serial_number="Not Specified", + system_version="pc-q35-5.2", + has_ipmi=False, + ) + + +missing_dmi_type16 = """ +# dmidecode 3.3 +Getting SMBIOS data from sysfs. +SMBIOS 2.8 present. + +Handle 0x0100, DMI type 1, 27 bytes +System Information + Manufacturer: QEMU + Product Name: Standard PC (Q35 + ICH9, 2009) + Version: pc-q35-5.2 + Serial Number: Not Specified + UUID: 236ce080-e87b-4d21-b9dd-3e43b8fb58dd + Wake-up Type: Power Switch + SKU Number: Not Specified + Family: Not Specified + +Handle 0x0002, DMI type 2, 15 bytes +Base Board Information + Manufacturer: Supermicro + Product Name: X11SPH-nCTPF + Version: 1.01 + Serial Number: 0000000000000 + Asset Tag: To be filled by O.E.M. + Features: + Board is a hosting board + Board is replaceable + Location In Chassis: To be filled by O.E.M. + Chassis Handle: 0x0003 + Type: Motherboard + Contained Object Handles: 0 + +""" + + +def test__missing_dmi_type16(): + assert DMIParser().parse(missing_dmi_type16) == DMIInfo( + bios_release_date=None, + ecc_memory=False, + baseboard_manufacturer="Supermicro", + baseboard_product_name="X11SPH-nCTPF", + system_manufacturer="QEMU", + system_product_name="Standard PC (Q35 + ICH9, 2009)", + system_serial_number="Not Specified", + system_version="pc-q35-5.2", + has_ipmi=False, + ) + + +missing_dmi_type38 = """ +# dmidecode 3.3 +Getting SMBIOS data from sysfs. +SMBIOS 3.2.1 present. + +Handle 0x0000, DMI type 0, 26 bytes +BIOS Information + Vendor: American Megatrends Inc. + Version: 3.3aV3 + Release Date: 12/03/2020 + Address: 0xF0000 + Runtime Size: 64 kB + ROM Size: 32 MB + Characteristics: + PCI is supported + BIOS is upgradeable + BIOS shadowing is allowed + Boot from CD is supported + Selectable boot is supported + BIOS ROM is socketed + EDD is supported + 5.25"/1.2 MB floppy services are supported (int 13h) + 3.5"/720 kB floppy services are supported (int 13h) + 3.5"/2.88 MB floppy services are supported (int 13h) + Print screen service is supported (int 5h) + Serial services are supported (int 14h) + Printer services are supported (int 17h) + ACPI is supported + USB legacy is supported + BIOS boot specification is supported + Targeted content distribution is supported + UEFI is supported + BIOS Revision: 5.14 + +Handle 0x0001, DMI type 1, 27 bytes +System Information + Manufacturer: iXsystems + Product Name: TRUENAS-M60 + Version: 0123456789 + Serial Number: A1-111111 + UUID: 00000000-0000-0000-0000-3cecef5ee7d6 + Wake-up Type: Power Switch + SKU Number: To be filled by O.E.M. + Family: To be filled by O.E.M. + +Handle 0x0002, DMI type 2, 15 bytes +Base Board Information + Manufacturer: Supermicro + Product Name: X11SPH-nCTPF + Version: 1.01 + Serial Number: 0000000000000 + Asset Tag: To be filled by O.E.M. + Features: + Board is a hosting board + Board is replaceable + Location In Chassis: To be filled by O.E.M. + Chassis Handle: 0x0003 + Type: Motherboard + Contained Object Handles: 0 + +Handle 0x0024, DMI type 16, 23 bytes +Physical Memory Array + Location: System Board Or Motherboard + Use: System Memory + Error Correction Type: Single-bit ECC + Maximum Capacity: 2304 GB + Error Information Handle: Not Provided + Number Of Devices: 4 + +Handle 0x002C, DMI type 16, 23 bytes +Physical Memory Array + Location: System Board Or Motherboard + Use: System Memory + Error Correction Type: Single-bit ECC + Maximum Capacity: 2304 GB + Error Information Handle: Not Provided + Number Of Devices: 4 + +""" + + +def test__missing_dmi_type38(): + assert DMIParser().parse(missing_dmi_type38) == DMIInfo( + bios_release_date=date(2020, 12, 3), + ecc_memory=True, + baseboard_manufacturer="Supermicro", + baseboard_product_name="X11SPH-nCTPF", + system_manufacturer="iXsystems", + system_product_name="TRUENAS-M60", + system_serial_number="A1-111111", + system_version="0123456789", + has_ipmi=False, + )