Skip to content

Feature/type checks - #211

Merged
hthiery merged 16 commits into
masterfrom
feature/type-checks
Oct 6, 2026
Merged

hthiery merged 16 commits into
masterfrom
feature/type-checks

Conversation

@hthiery

@hthiery hthiery commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

No description provided.

hthiery and others added 16 commits October 6, 2026 19:19
The __fields__ of SetSelTimeReq, SetSelTimeRsp and AddSelEntryReq were
a single field instead of a tuple, because the trailing comma was
missing. Creating one of these messages failed with a TypeError, as
the field is not iterable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
The SDR passes the device ID string as array to SdrTypeLengthString.
An array has no decode() method, so a BCD+ encoded device ID string
failed with an AttributeError. Convert the data to bytes before
decoding it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
read_fru_data() with an offset but without a count failed with a
TypeError, because the end of the read was calculated from the count.
Read from the offset to the end of the FRU inventory area instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
The area offsets of the common header are None for areas that are not
present. Requesting such an area read the FRU data with the offset
None, which is the whole FRU inventory, and decoded it as the area.
Raise DataNotFound instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
The command called send_channel_power() with the channel only, the
required enable and current limit arguments were missing, so the
command always failed with a TypeError. Add the arguments 'on'/'off'
and the current limit in amperes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
'sdr show' failed with a TypeError for a sensor reading without
assertion states, print 'na' instead. Select the output by the class
of the SDR instead of comparing the record type by identity.

get_port_state() returns None for a port that is not supported, which
let 'picmg portstate get' and 'getall' fail with an AttributeError.
Print 'Port not supported' for a single port and skip the port when
all ports are listed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
The check hasattr(self, '_session') was always true, because _session
is set to None by the constructor. Without a session the ipmitool
command failed with an AttributeError on None instead of the intended
RuntimeError. Check for None in a helper that returns the session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
The credentials can be set as str or bytes. Only the password of the
RMCP interface handled bytes, a bytes user name failed in the RMCP
interface, and bytes credentials failed in the RMCP+ and ipmitool
interfaces. The RMCP interface padded a str user name to 16 characters
instead of 16 bytes.

Add auth_username_bytes and auth_password_bytes to the session, they
return the UTF-8 encoded credentials, and use them in the interfaces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
The group extension is None for most messages, so formatting it with
'%d' failed with a TypeError instead of raising the DescriptionError.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
The fields of a message are created as attributes at runtime, so a
type checker reports every access to a field as an error. Declare
__getattr__ and __setattr__ of Message and Bitfield.BitWrapper for
type checking only, the runtime behaviour does not change. Declare the
class attributes set by the message definitions (__netfn__, __cmdid__,
__fields__) and the type of the message registry.

Annotate the helpers in utils: ByteBuffer is iterable and can be
sliced, ByteSequence is the raw data in any of the forms used by the
library, is_string() is a type guard and the BCD codec functions match
the codec protocol. ResponseDecoder declares _from_response().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
The Ipmi class is composed of the command groups (Bmc, Chassis, Fru,
...). They call send_message() and other methods provided by Ipmi or
by another command group, which a type checker cannot know. Add the
base class IpmiMixin that declares these methods for type checking
only, the command groups inherit from it.

Use the property decorator for interface, session and target of Ipmi,
so they override the declarations of IpmiMixin, and annotate the
attributes of Target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
Annotate the attributes of the upgrade image records and narrow the
optional values where they are used:
- the FORMAT fields of UpgradeImageHeaderRecord are declared
- UpgradeImage.actions is an empty list instead of None without a file
- ComponentProperty declares _from_rsp_data() and from_data() returns
  None explicitly for an unknown property
- find_component_id_by_descriptor() checks for the description string
  property by its class
- upload_binary() uses a flag to resend a block with a reduced size
  instead of setting the chunk to None
- the image header prints the signature as text instead of b'...'
- the lists in the __str__() methods do not shadow the str builtin

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
Annotate the attributes that are initialized with None or an empty
list (ChassisStatus, Session, LinkDescriptor, FruInventory) and accept
the raw data as any sequence of ints where bytes, lists and arrays are
passed (FRU, SDR and type/length fields).

Other changes:
- get_port_state() is annotated to return None for an unsupported port
- SelEntry is decoded from the record data by its own constructor
  instead of the response decoder of State
- VersionField loses the 'version' attribute, it was always None
- the command specific completion code is only looked up with a NetFn

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
Annotate the attributes initialized with None and narrow the optional
values where they are used:
- the IPMB header fields are declared as int without a None default,
  they are always set before a header is encoded
- the IPMB, RMCP and ipmidev interfaces raise a ValueError if the
  target has no IPMB address or a bridge has no channel, the shared
  helper target_ipmb_address() checks the address
- ipmidev raises a RuntimeError if the device is not open
- a received RMCP message without data is returned as b'' instead of
  failing in the debug output, an MD5 authenticated message without
  data could not be packed
- the ipmitool interface prints the output of a failed command as text

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
Use separate variables for the FRU areas and the chassis status JSON
instead of reusing one variable for different types, parse the
interface options from the option string only, and close the
connection only if one was created.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
Run mypy on the pyipmi package in the lint workflow. The configuration
is in setup.cfg, the optional dependencies pyserial, pyaardvark and
cryptography are not installed for the check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
@hthiery
hthiery merged commit 3e11a3c into master Oct 6, 2026
25 of 26 checks passed
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 91.397% (+0.002%) from 91.395% — feature/type-checks into master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants